diff options
-rw-r--r-- | dw/hyphenator.cc | 13 | ||||
-rw-r--r-- | dw/hyphenator.hh | 1 | ||||
-rw-r--r-- | dw/textblock.cc | 55 | ||||
-rw-r--r-- | dw/textblock.hh | 12 | ||||
-rw-r--r-- | dw/textblock_linebreaking.cc | 24 |
5 files changed, 63 insertions, 42 deletions
diff --git a/dw/hyphenator.cc b/dw/hyphenator.cc index 8f73bc80..998b7975 100644 --- a/dw/hyphenator.cc +++ b/dw/hyphenator.cc @@ -117,6 +117,16 @@ void Hyphenator::insertPattern (char *s) } /** + * Simple test to avoid much costs. Passing it does not mean that the word + * can be hyphenated. + */ +bool Hyphenator::isHyphenationCandidate (const char *word) +{ + // Short words aren't hyphenated. + return (strlen (word) > 4); // TODO UTF-8? +} + +/** * Given a word, returns a list of pieces, broken at the possible * hyphenation points. */ @@ -124,8 +134,7 @@ Vector <String> *Hyphenator::hyphenateWord(const char *word) { Vector <String> *pieces = new Vector <String> (1, true); - // Short words aren't hyphenated. - if (strlen (word) <= 4) { // TODO UTF-8? + if (!isHyphenationCandidate (word) <= 4) { pieces->put (new String (word)); return pieces; } diff --git a/dw/hyphenator.hh b/dw/hyphenator.hh index 97de965f..839f6cc9 100644 --- a/dw/hyphenator.hh +++ b/dw/hyphenator.hh @@ -32,6 +32,7 @@ public: static Hyphenator *getHyphenator (core::Platform *platform, const char *language); + static bool isHyphenationCandidate (const char *word); lout::container::typed::Vector <lout::object::String> *hyphenateWord(const char *word); diff --git a/dw/textblock.cc b/dw/textblock.cc index 826b6648..b4a2b66c 100644 --- a/dw/textblock.cc +++ b/dw/textblock.cc @@ -1223,13 +1223,18 @@ void Textblock::draw (core::View *view, core::Rectangle *area) * Add a new word (text, widget etc.) to a page. */ Textblock::Word *Textblock::addWord (int width, int ascent, int descent, + bool canBeHyphenated, core::style::Style *style) { - Word *word; - words->increase (); + Word *word = words->getLastRef (); + fillWord (word, width, ascent, descent, canBeHyphenated, style); + return word; +} - word = words->getRef (words->size() - 1); +void Textblock::fillWord (Word *word, int width, int ascent, int descent, + bool canBeHyphenated, core::style::Style *style) +{ word->size.width = width; word->size.ascent = ascent; word->size.descent = descent; @@ -1238,19 +1243,7 @@ Textblock::Word *Textblock::addWord (int width, int ascent, int descent, word->hyphenWidth = 0; word->badnessAndPenalty.setPenaltyProhibitBreak (); word->content.space = false; - - //DBG_OBJ_ARRSET_NUM (this, "words.%d.size.width", words->size() - 1, - // word->size.width); - //DBG_OBJ_ARRSET_NUM (this, "words.%d.size.descent", words->size() - 1, - // word->size.descent); - //DBG_OBJ_ARRSET_NUM (this, "words.%d.size.ascent", words->size() - 1, - // word->size.ascent); - //DBG_OBJ_ARRSET_NUM (this, "words.%d.orig_space", words->size() - 1, - // word->orig_space); - //DBG_OBJ_ARRSET_NUM (this, "words.%d.effSpace", words->size() - 1, - // word->eff_space); - //DBG_OBJ_ARRSET_NUM (this, "words.%d.content.space", words->size() - 1, - // word->content.space); + word->canBeHyphenated = canBeHyphenated; word->style = style; word->spaceStyle = style; @@ -1258,8 +1251,6 @@ Textblock::Word *Textblock::addWord (int width, int ascent, int descent, style->ref (); style->ref (); style->ref (); - - return word; } /* @@ -1387,10 +1378,11 @@ void Textblock::addText (const char *text, size_t len, numHyphens++; if (numHyphens == 0) { - // Simple (and often) case: no soft hyphens. + // Simple (and often) case: no soft hyphens. May still be hyphenated + // automatically. core::Requisition size; calcTextSize (text, len, style, &size); - addText0 (text, len, style, &size); + addText0 (text, len, true, style, &size); } else { PRINTF("HYPHENATION: '"); for (size_t i = 0; i < len; i++) @@ -1454,7 +1446,8 @@ void Textblock::addText (const char *text, size_t len, for (int i = 0; i < numHyphens + 1; i++) { int start = (i == 0) ? 0 : hyphenPos[i - 1] + 2; int end = (i == numHyphens) ? len : hyphenPos[i]; - addText0 (text + start, end - start, style, &wordSize[i]); + // Do not anymore hyphen automatically. + addText0 (text + start, end - start, false, style, &wordSize[i]); PRINTF("H... [%d] '", i); for (int j = start; j < end; j++) @@ -1469,21 +1462,18 @@ void Textblock::addText (const char *text, size_t len, } } + /** * Add a word (without hyphens) to the page structure. */ -void Textblock::addText0 (const char *text, size_t len, +void Textblock::addText0 (const char *text, size_t len, bool canBeHyphenated, core::style::Style *style, core::Requisition *size) { - Word *word; - - word = addWord (size->width, size->ascent, size->descent, style); + Word *word = addWord (size->width, size->ascent, size->descent, + canBeHyphenated, style); word->content.type = core::Content::TEXT; word->content.text = layout->textZone->strndup(text, len); - //DBG_OBJ_ARRSET_STR (page, "words.%d.content.text", words->size() - 1, - // word->content.text); - wordWrap (words->size () - 1, false); } @@ -1507,7 +1497,7 @@ void Textblock::addWidget (core::Widget *widget, core::style::Style *style) widget->setStyle (style); calcWidgetSize (widget, &size); - word = addWord (size.width, size.ascent, size.descent, style); + word = addWord (size.width, size.ascent, size.descent, false, style); word->content.type = core::Content::WIDGET; word->content.widget = widget; @@ -1700,7 +1690,7 @@ void Textblock::addParbreak (int space, core::style::Style *style) return; } - word = addWord (0, 0, 0, style); + word = addWord (0, 0, 0, false, style); word->content.type = core::Content::BREAK; word->badnessAndPenalty.setPenaltyForceBreak (); word->content.breakSpace = space; @@ -1718,10 +1708,11 @@ void Textblock::addLinebreak (core::style::Style *style) words->getRef(words->size () - 1)->content.type == core::Content::BREAK) // An <BR> in an empty line gets the height of the current font // (why would someone else place it here?), ... - word = addWord (0, style->font->ascent, style->font->descent, style); + word = + addWord (0, style->font->ascent, style->font->descent, false, style); else // ... otherwise, it has no size (and does not enlarge the line). - word = addWord (0, 0, 0, style); + word = addWord (0, 0, 0, false, style); word->content.type = core::Content::BREAK; word->badnessAndPenalty.setPenaltyForceBreak (); diff --git a/dw/textblock.hh b/dw/textblock.hh index b301db7d..778d5b35 100644 --- a/dw/textblock.hh +++ b/dw/textblock.hh @@ -156,6 +156,7 @@ private: private: enum { TOO_LOOSE, TOO_TIGHT, BADNESS_VALUE } badnessState; enum { FORCE_BREAK, PROHIBIT_BREAK, PENALTY_VALUE } penaltyState; + int ratio; // ratio is only defined when badness is defined int badness, penalty; // for debugging: @@ -173,6 +174,8 @@ private: void setPenaltyProhibitBreak (); void setPenaltyForceBreak (); + bool lineLoose (); + bool lineTight (); bool lineTooTight (); bool lineMustBeBroken (); bool lineCanBeBroken (); @@ -227,6 +230,7 @@ protected: * "hyphenWidth > 0" is also used to decide * weather to draw a hyphen. */ core::Content content; + bool canBeHyphenated; // accumulated values, relative to the beginning of the line int totalWidth; /* The sum of all word widths; plus all @@ -356,8 +360,10 @@ protected: int findLineOfWord (int wordIndex); Word *findWord (int x, int y, bool *inSpace); - Word *addWord (int width, int ascent, int descent, + Word *addWord (int width, int ascent, int descent, bool canBeHyphenated, core::style::Style *style); + void fillWord (Word *word, int width, int ascent, int descent, + bool canBeHyphenated, core::style::Style *style); int textWidth (const char *text, int start, int len, core::style::Style *style); void calcTextSize (const char *text, size_t len, core::style::Style *style, @@ -455,8 +461,8 @@ protected: void removeChild (Widget *child); - void addText0 (const char *text, size_t len, core::style::Style *style, - core::Requisition *size); + void addText0 (const char *text, size_t len, bool canBeHyphenated, + core::style::Style *style, core::Requisition *size); public: static int CLASS_ID; diff --git a/dw/textblock_linebreaking.cc b/dw/textblock_linebreaking.cc index 5ca556c8..430f51aa 100644 --- a/dw/textblock_linebreaking.cc +++ b/dw/textblock_linebreaking.cc @@ -1,4 +1,5 @@ #include "textblock.hh" +#include "hyphenator.hh" #include "../lout/msg.h" #include "../lout/misc.hh" @@ -69,7 +70,7 @@ void Textblock::BadnessAndPenalty::calcBadness (int totalWidth, int idealWidth, if (totalStretchability == 0) badnessState = TOO_LOOSE; else { - int ratio = 100 * (idealWidth - totalWidth) / totalStretchability; + ratio = 100 * (idealWidth - totalWidth) / totalStretchability; if (ratio > 1024) badnessState = TOO_LOOSE; else { @@ -81,13 +82,13 @@ void Textblock::BadnessAndPenalty::calcBadness (int totalWidth, int idealWidth, if (totalShrinkability == 0) badnessState = TOO_TIGHT; else { - // Important: ratio is positive here. - int ratio = 100 * (totalWidth - idealWidth) / totalShrinkability; - if (ratio >= 100) + // ratio is negative here + ratio = 100 * (idealWidth - totalWidth) / totalShrinkability; + if (ratio <= - 100) badnessState = TOO_TIGHT; else { badnessState = BADNESS_VALUE; - badness = ratio * ratio * ratio; + badness = - ratio * ratio * ratio; } } } @@ -109,11 +110,24 @@ void Textblock::BadnessAndPenalty::setPenaltyForceBreak () penaltyState = FORCE_BREAK; } +bool Textblock::BadnessAndPenalty::lineLoose () +{ + return + badnessState == TOO_LOOSE || (badnessState == BADNESS_VALUE && ratio > 0); +} + +bool Textblock::BadnessAndPenalty::lineTight () +{ + return + badnessState == TOO_TIGHT || (badnessState == BADNESS_VALUE && ratio < 0); +} + bool Textblock::BadnessAndPenalty::lineTooTight () { return badnessState == TOO_TIGHT; } + bool Textblock::BadnessAndPenalty::lineMustBeBroken () { return penaltyState == FORCE_BREAK; |