aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dw/hyphenator.cc4
-rw-r--r--dw/layout.hh5
-rw-r--r--dw/textblock.hh1
-rw-r--r--dw/textblock_linebreaking.cc226
-rw-r--r--lout/misc.hh9
-rw-r--r--test/liang.cc2
6 files changed, 190 insertions, 57 deletions
diff --git a/dw/hyphenator.cc b/dw/hyphenator.cc
index 998b7975..b617993a 100644
--- a/dw/hyphenator.cc
+++ b/dw/hyphenator.cc
@@ -134,7 +134,7 @@ Vector <String> *Hyphenator::hyphenateWord(const char *word)
{
Vector <String> *pieces = new Vector <String> (1, true);
- if (!isHyphenationCandidate (word) <= 4) {
+ if (!isHyphenationCandidate (word)) {
pieces->put (new String (word));
return pieces;
}
@@ -184,7 +184,7 @@ Vector <String> *Hyphenator::hyphenateWord(const char *word)
points.put (new Integer (0), 2);
points.put (new Integer (0), points.size () - 2);
points.put (new Integer (0), points.size () - 3);
-
+
// Examine the points to build the pieces list.
char temp[strlen (word) + 1], *ptemp = temp;
diff --git a/dw/layout.hh b/dw/layout.hh
index 45187490..4b80456b 100644
--- a/dw/layout.hh
+++ b/dw/layout.hh
@@ -290,6 +290,11 @@ public:
void scrollPosChanged (View *view, int x, int y);
void viewportSizeChanged (View *view, int width, int height);
+ inline Platform *getPlatform ()
+ {
+ return platform;
+ }
+
/* delegated */
inline int textWidth (style::Font *font, const char *text, int len)
diff --git a/dw/textblock.hh b/dw/textblock.hh
index b06bc3c7..124f81be 100644
--- a/dw/textblock.hh
+++ b/dw/textblock.hh
@@ -435,6 +435,7 @@ protected:
void accumulateWordExtremees (int firstWord, int lastWord,
int *maxOfMinWidth, int *sumOfMaxWidth);
virtual void wordWrap (int wordIndex, bool wrapAll);
+ void hyphenateWord (int wordIndex);
void accumulateWordForLine (int lineIndex, int wordIndex);
void accumulateWordData(int wordIndex);
int calcAvailWidth ();
diff --git a/dw/textblock_linebreaking.cc b/dw/textblock_linebreaking.cc
index 430f51aa..3d612097 100644
--- a/dw/textblock_linebreaking.cc
+++ b/dw/textblock_linebreaking.cc
@@ -398,71 +398,187 @@ void Textblock::wordWrap (int wordIndex, bool wrapAll)
accumulateWordData (wordIndex);
- int breakPos = -1;
- for (int i = firstIndex; i <= searchUntil; i++) {
- Word *w = words->getRef(i);
-
- if(word->content.type && core::Content::REAL_CONTENT) {
- PRINTF (" %d (of %d): ", i, words->size ());
-
- switch(w->content.type) {
- case core::Content::TEXT:
- PRINTF ("\"%s\"", w->content.text);
- break;
- case core::Content::WIDGET:
- PRINTF ("<widget: %p>\n", w->content.widget);
- break;
- case core::Content::BREAK:
- PRINTF ("<break>\n");
- break;
- default:
- PRINTF ("<?>\n");
- break;
+ bool lineAdded;
+ do {
+ int breakPos = -1;
+ for (int i = firstIndex; i <= searchUntil; i++) {
+ Word *w = words->getRef(i);
+
+ if(word->content.type && core::Content::REAL_CONTENT) {
+ PRINTF (" %d (of %d): ", i, words->size ());
+
+ switch(w->content.type) {
+ case core::Content::TEXT:
+ PRINTF ("\"%s\"", w->content.text);
+ break;
+ case core::Content::WIDGET:
+ PRINTF ("<widget: %p>\n", w->content.widget);
+ break;
+ case core::Content::BREAK:
+ PRINTF ("<break>\n");
+ break;
+ default:
+ PRINTF ("<?>\n");
+ break;
+ }
+
+ PRINTF (" [%d / %d + %d - %d] => ",
+ w->size.width, w->origSpace, w->stretchability,
+ w->shrinkability);
+ w->badnessAndPenalty.print ();
+ PRINTF ("\n");
}
+
+
+ // TODO: is this condition needed:
+ // if(w->badnessAndPenalty.lineCanBeBroken ()) ?
+
+ if (breakPos == -1 ||
+ w->badnessAndPenalty.compareTo
+ (&words->getRef(breakPos)->badnessAndPenalty) <= 0)
+ // "<=" instead of "<" in the next lines tends to result in
+ // more words per line -- theoretically. Practically, the
+ // case "==" will never occur.
+ breakPos = i;
+ }
+
+ if (wrapAll && searchUntil == words->size () - 1) {
+ // Since no break and no space is added, the last word
+ // will have a penalty of inf. Actually, it should be -inf,
+ // since it is the last word. However, since more words may
+ // follow, the penalty is not changesd, but here, the search
+ // is corrected (maybe only temporary).
+ Word *lastWord = words->getRef (searchUntil);
+ BadnessAndPenalty correctedBap = lastWord->badnessAndPenalty;
+ correctedBap.setPenaltyForceBreak ();
+ if (correctedBap.compareTo
+ (&words->getRef(breakPos)->badnessAndPenalty) <= 0)
+ breakPos = searchUntil;
+ }
- PRINTF (" [%d / %d + %d - %d] => ",
- w->size.width, w->origSpace, w->stretchability,
- w->shrinkability);
- w->badnessAndPenalty.print ();
- PRINTF ("\n");
+ PRINTF ("breakPos = %d\n", breakPos);
+
+ int hyphenatedWord = -1;
+ Word *word1 = words->getRef(breakPos);
+ if (word1->badnessAndPenalty.lineTight () &&
+ word1->canBeHyphenated &&
+ word1->content.type == core::Content::TEXT &&
+ Hyphenator::isHyphenationCandidate (word1->content.text))
+ hyphenatedWord = breakPos;
+
+ if (word1->badnessAndPenalty.lineLoose () &&
+ breakPos + 1 < words->size ()) {
+ Word *word2 = words->getRef(breakPos + 1);
+ if (word2->canBeHyphenated &&
+ word2->content.type == core::Content::TEXT &&
+ Hyphenator::isHyphenationCandidate (word2->content.text))
+ hyphenatedWord = breakPos + 1;
+ }
+
+ if(hyphenatedWord == -1) {
+ PRINTF (" new line from %d to %d\n", firstIndex, breakPos);
+ addLine (firstIndex, breakPos, tempNewLine);
+ lineAdded = true;
+ PRINTF (" accumulating again from %d to %d\n",
+ breakPos + 1, wordIndex);
+ } else {
+ hyphenateWord (hyphenatedWord);
+ lineAdded = false;
}
+ for(int i = breakPos + 1; i <= wordIndex; i++)
+ accumulateWordData (i);
+
+ } while(!lineAdded);
+ }
+ } while (newLine);
+}
- // TODO: is this condition needed:
- // if(w->badnessAndPenalty.lineCanBeBroken ()) ?
+void Textblock::hyphenateWord (int wordIndex)
+{
+ Word *word = words->getRef(wordIndex);
+ printf (" considering to hyphenate word %d: '%s'\n",
+ wordIndex, word->content.text);
- if (breakPos == -1 ||
- w->badnessAndPenalty.compareTo
- (&words->getRef(breakPos)->badnessAndPenalty) <= 0)
- // "<=" instead of "<" in the next lines tends to result in more
- // words per line -- theoretically. Practically, the case "=="
- // will never occur.
- breakPos = i;
+ Hyphenator *hyphenator =
+ Hyphenator::getHyphenator (layout->getPlatform (), "de"); // TODO lang
+
+ // TODO Change interface of Hyphenator.
+ container::typed::Vector <object::String> *pieces =
+ hyphenator->hyphenateWord (word->content.text);
+ if (pieces->size () > 1) {
+ int numBreaks = pieces->size () - 1;
+ int breakPos[numBreaks];
+ for (int i = 0; i < numBreaks; i++)
+ breakPos[i] =
+ strlen (pieces->get(i)->chars()) + (i == 0 ? 0 : breakPos[i - 1]);
+
+ for (int i = 0; i < numBreaks; i++)
+ printf (" breakPos[%d]: %d\n", i, breakPos[i]);
+
+ // TODO unref also spaceStyle and hyphenStyle
+
+ const char *origText = word->content.text;
+ int lenOrigText = strlen (origText);
+ core::style::Style *origStyle = word->style;
+ core::Requisition wordSize[numBreaks + 1];
+
+ calcTextSizes (origText, lenOrigText, origStyle, numBreaks, breakPos,
+ wordSize);
+
+ printf (" ... %d words ...\n", words->size ());
+ words->insert (wordIndex, numBreaks);
+ printf (" ... -> %d words.\n", words->size ());
+
+ for (int i = 0; i < numBreaks + 1; i++) {
+ Word *w = words->getRef (wordIndex + i);
+
+ fillWord (w, wordSize[i].width, wordSize[i].ascent,
+ wordSize[i].descent, false, origStyle);
+
+ // TODO There should be a method fillText0.
+ w->content.type = core::Content::TEXT;
+
+ int start = (i == 0 ? 0 : breakPos[i - 1]);
+ int end = (i == numBreaks ? lenOrigText : breakPos[i]);
+ w->content.text =
+ layout->textZone->strndup(origText + start, end - start);
+ //printf (" '%s' from %d to %d => '%s'\n",
+ // origText, start, end, w->content.text);
+
+ printf (" [%d] -> '%s'\n", wordIndex + i, w->content.text);
+
+ if (i < numBreaks - 1) {
+ // TODO There should be a method fillHyphen.
+ w->badnessAndPenalty.setPenalty (HYPHEN_BREAK);
+ w->hyphenWidth = layout->textWidth (origStyle->font, "\xc2\xad", 2);
+ } else {
+ // TODO There should be a method fillSpace.
+ // TODO Add original space.
+#if 0
+ w->badnessAndPenalty.setPenalty (0);
+ w->content.space = true;
+ w->effSpace = word->origSpace = origStyle->font->spaceWidth +
+ origStyle->wordSpacing;
+ w->stretchability = w->origSpace / 2;
+ if(origStyle->textAlign == core::style::TEXT_ALIGN_JUSTIFY)
+ w->shrinkability = w->origSpace / 3;
+ else
+ w->shrinkability = 0;
+#endif
}
- if (wrapAll && searchUntil == words->size () - 1) {
- // Since no break and no space is added, the last word
- // will have a penalty of inf. Actually, it should be -inf,
- // since it is the last word. However, since more words may
- // follow, the penalty is not changesd, but here, the search
- // is corrected (maybe only temporary).
- Word *lastWord = words->getRef (searchUntil);
- BadnessAndPenalty correctedBap = lastWord->badnessAndPenalty;
- correctedBap.setPenaltyForceBreak ();
- if (correctedBap.compareTo
- (&words->getRef(breakPos)->badnessAndPenalty) <= 0)
- breakPos = searchUntil;
- }
+ accumulateWordData (wordIndex + i);
+ }
- PRINTF (" new line from %d to %d\n", firstIndex, breakPos);
- addLine (firstIndex, breakPos, tempNewLine);
- PRINTF (" accumulating again from %d to %d\n",
- breakPos + 1, wordIndex);
+ printf (" finished\n");
+
+ //delete origText; TODO: Via textZone?
+ origStyle->unref ();
+ } else
+ word->canBeHyphenated = false;
- for(int i = breakPos + 1; i <= wordIndex; i++)
- accumulateWordData (i);
- }
- } while (newLine);
+ delete pieces;
}
void Textblock::accumulateWordForLine (int lineIndex, int wordIndex)
diff --git a/lout/misc.hh b/lout/misc.hh
index 05b87602..1f558814 100644
--- a/lout/misc.hh
+++ b/lout/misc.hh
@@ -167,6 +167,15 @@ public:
this->resize ();
}
+ inline void insert(int index, int numInsert) {
+ // TODO "transparent delay", for hyphenation
+ assert (numInsert >= 0);
+ this->num += numInsert;
+ this->resize ();
+ for (int i = this->num - 1; i >= index + numInsert; i--)
+ array[i] = array[i - numInsert];
+ }
+
/**
* \brief Set the size explicitly and initialize new values.
*
diff --git a/test/liang.cc b/test/liang.cc
index 5dc5e2e8..e6cda15d 100644
--- a/test/liang.cc
+++ b/test/liang.cc
@@ -31,6 +31,8 @@ int main (int argc, char *argv[])
hyphenateWord (&p, "Ackermann");
hyphenateWord (&p, "Grundstücksverkehrsgenehmigungszuständigkeits"
"übertragungsverordnung");
+ hyphenateWord (&p, "„Grundstücksverkehrsgenehmigungszuständigkeits"
+ "übertragungsverordnung“");
return 0;
}