diff options
author | Sebastian Geerken <devnull@localhost> | 2012-11-13 22:59:02 +0100 |
---|---|---|
committer | Sebastian Geerken <devnull@localhost> | 2012-11-13 22:59:02 +0100 |
commit | 3b53c5940970f002e2e77b347802f8e2c9684904 (patch) | |
tree | 930f69e45b19b8458af6060cf4e13c17062ae87b | |
parent | 0085643208798a991babbe9d0bce37d9193b245a (diff) |
Introduced two penalties. (Not used yet.)
-rw-r--r-- | dw/textblock.cc | 41 | ||||
-rw-r--r-- | dw/textblock.hh | 26 | ||||
-rw-r--r-- | dw/textblock_linebreaking.cc | 100 |
3 files changed, 102 insertions, 65 deletions
diff --git a/dw/textblock.cc b/dw/textblock.cc index 1eba5036..9adc4aee 100644 --- a/dw/textblock.cc +++ b/dw/textblock.cc @@ -297,7 +297,8 @@ void Textblock::getExtremesImpl (core::Extremes *extremes) } // Minimum: between two *possible* breaks (or at the end). - if (word->badnessAndPenalty.lineCanBeBroken () || atLastWord) { + // TODO: Explain why index 1 is used in lineCanBeBroken(). + if (word->badnessAndPenalty.lineCanBeBroken (1) || atLastWord) { parMin += wordExtremes.minWidth + word->hyphenWidth; extremes->minWidth = misc::max (extremes->minWidth, parMin); parMin = 0; @@ -307,7 +308,9 @@ void Textblock::getExtremesImpl (core::Extremes *extremes) parMin += wordExtremes.minWidth + word->origSpace; // Maximum: between two *necessary* breaks (or at the end). - if (word->badnessAndPenalty.lineMustBeBroken () || atLastWord) { + // TODO: lineMustBeBroken should be independent of the + // penalty index? + if (word->badnessAndPenalty.lineMustBeBroken (1) || atLastWord) { parMax += wordExtremes.maxWidth + word->hyphenWidth; extremes->maxWidth = misc::max (extremes->maxWidth, parMax); parMax = 0; @@ -1310,7 +1313,7 @@ void Textblock::fillWord (Word *word, int width, int ascent, int descent, word->origSpace = word->effSpace = word->stretchability = word->shrinkability = 0; word->hyphenWidth = 0; - word->badnessAndPenalty.setPenaltyProhibitBreak (); + word->badnessAndPenalty.setBothPenaltiesProhibitBreak (); word->content.space = false; word->flags = canBeHyphenated ? Word::CAN_BE_HYPHENATED : 0; @@ -1473,7 +1476,8 @@ void Textblock::addText (const char *text, size_t len, // Store hyphen positions. int n = 0, totalLenSignRemoved = 0; - int partPenalty[numParts - 1], partStart[numParts], partEnd[numParts]; + int partPenaltyIndex[numParts - 1]; + int partStart[numParts], partEnd[numParts]; bool signRemoved[numParts - 1], canBeHyphenated[numParts + 1]; canBeHyphenated[0] = canBeHyphenated[numParts] = true; partStart[0] = 0; @@ -1497,8 +1501,7 @@ void Textblock::addText (const char *text, size_t len, assert (divChars[foundDiv].penaltyIndexLeft != -1); assert (divChars[foundDiv].penaltyIndexRight == -1); - partPenalty[n] = - penalties[divChars[foundDiv].penaltyIndexLeft][0]; + partPenaltyIndex[n] = divChars[foundDiv].penaltyIndexLeft; signRemoved[n] = true; canBeHyphenated[n + 1] = divChars[foundDiv].canBeHyphenated; partEnd[n] = i; @@ -1510,8 +1513,7 @@ void Textblock::addText (const char *text, size_t len, divChars[foundDiv].penaltyIndexRight != -1); if (divChars[foundDiv].penaltyIndexLeft != -1) { - partPenalty[n] = - penalties[divChars[foundDiv].penaltyIndexLeft][0]; + partPenaltyIndex[n] = divChars[foundDiv].penaltyIndexLeft; signRemoved[n] = false; canBeHyphenated[n + 1] = divChars[foundDiv].canBeHyphenated; partEnd[n] = i; @@ -1520,8 +1522,7 @@ void Textblock::addText (const char *text, size_t len, } if (divChars[foundDiv].penaltyIndexRight != -1) { - partPenalty[n] = - penalties[divChars[foundDiv].penaltyIndexRight][0]; + partPenaltyIndex[n] = divChars[foundDiv].penaltyIndexRight; signRemoved[n] = false; canBeHyphenated[n + 1] = divChars[foundDiv].canBeHyphenated; partEnd[n] = i + lDiv; @@ -1585,7 +1586,12 @@ void Textblock::addText (const char *text, size_t len, if(i < numParts - 1) { Word *word = words->getLastRef(); - word->badnessAndPenalty.setPenalty (partPenalty[i]); + + word->badnessAndPenalty + .setPenalty (0, penalties[partPenaltyIndex[i]][0]); + word->badnessAndPenalty + .setPenalty (1, penalties[partPenaltyIndex[i]][1]); + if (signRemoved[i]) { // Currently, only soft hyphens (UTF-8: "\xc2\xad") can // be used. See also drawWord, last section "if @@ -1596,6 +1602,7 @@ void Textblock::addText (const char *text, size_t len, layout->textWidth (word->style->font, "\xc2\xad", 2); word->flags |= Word::DIV_CHAR_AT_EOL; } + word->flags |= Word::DRAW_AS_ONE_TEXT; accumulateWordData (words->size() - 1); } @@ -1797,17 +1804,19 @@ void Textblock::fillSpace (Word *word, core::style::Style *style) */ void Textblock::setBreakOption (Word *word, core::style::Style *style) { - if (!word->badnessAndPenalty.lineMustBeBroken()) { + // TODO: lineMustBeBroken should be independent of the penalty + // index? Otherwise, examine the last line. + if (!word->badnessAndPenalty.lineMustBeBroken(0)) { switch (style->whiteSpace) { case core::style::WHITE_SPACE_NORMAL: case core::style::WHITE_SPACE_PRE_LINE: case core::style::WHITE_SPACE_PRE_WRAP: - word->badnessAndPenalty.setPenalty (0); + word->badnessAndPenalty.setBothPenalties (0); break; case core::style::WHITE_SPACE_PRE: case core::style::WHITE_SPACE_NOWRAP: - word->badnessAndPenalty.setPenaltyProhibitBreak (); + word->badnessAndPenalty.setBothPenaltiesProhibitBreak (); break; } } @@ -1885,7 +1894,7 @@ void Textblock::addParbreak (int space, core::style::Style *style) word = addWord (0, 0, 0, false, style); word->content.type = core::Content::BREAK; - word->badnessAndPenalty.setPenaltyForceBreak (); + word->badnessAndPenalty.setBothPenaltiesForceBreak (); word->content.breakSpace = space; wordWrap (words->size () - 1, false); } @@ -1908,7 +1917,7 @@ void Textblock::addLinebreak (core::style::Style *style) word = addWord (0, 0, 0, false, style); word->content.type = core::Content::BREAK; - word->badnessAndPenalty.setPenaltyForceBreak (); + word->badnessAndPenalty.setBothPenaltiesForceBreak (); word->content.breakSpace = 0; wordWrap (words->size () - 1, false); } diff --git a/dw/textblock.hh b/dw/textblock.hh index 9605ac85..99d1e713 100644 --- a/dw/textblock.hh +++ b/dw/textblock.hh @@ -157,9 +157,9 @@ private: private: enum { NOT_STRETCHABLE, QUITE_LOOSE, BADNESS_VALUE, TOO_TIGHT } badnessState; - enum { FORCE_BREAK, PROHIBIT_BREAK, PENALTY_VALUE } penaltyState; + enum { FORCE_BREAK, PROHIBIT_BREAK, PENALTY_VALUE } penaltyState[2]; int ratio; // ratio is only defined when badness is defined - int badness, penalty; + int badness, penalty[2]; // For debugging: define DEBUG for more informations in print(). #ifdef DEBUG @@ -192,21 +192,28 @@ private: }; int badnessValue (int infLevel); - int penaltyValue (int infLevel); + int penaltyValue (int index, int infLevel); public: void calcBadness (int totalWidth, int idealWidth, int totalStretchability, int totalShrinkability); - void setPenalty (int penalty); - void setPenaltyProhibitBreak (); - void setPenaltyForceBreak (); + void setPenalty (int index, int penalty); + inline void setBothPenalties (int penalty) { + setPenalty (0, penalty); setPenalty (1, penalty); } + + void setPenaltyProhibitBreak (int index); + void setPenaltyForceBreak (int index); + inline void setBothPenaltiesProhibitBreak () { + setPenaltyProhibitBreak (0); setPenaltyProhibitBreak (1); } + inline void setBothPenaltiesForceBreak () { + setPenaltyForceBreak (0); setPenaltyForceBreak (1); } bool lineLoose (); bool lineTight (); bool lineTooTight (); - bool lineMustBeBroken (); - bool lineCanBeBroken (); - int compareTo (BadnessAndPenalty *other); + bool lineMustBeBroken (int penaltyIndex); + bool lineCanBeBroken (int penaltyIndex); + int compareTo (int penaltyIndex, BadnessAndPenalty *other); void print (); }; @@ -298,6 +305,7 @@ protected: * "hyphenWidth > 0" is also used to decide * whether to draw a hyphen. */ short flags; + short penaltyIndex; core::Content content; // accumulated values, relative to the beginning of the line diff --git a/dw/textblock_linebreaking.cc b/dw/textblock_linebreaking.cc index a980e38a..c98596c6 100644 --- a/dw/textblock_linebreaking.cc +++ b/dw/textblock_linebreaking.cc @@ -31,9 +31,9 @@ int Textblock::BadnessAndPenalty::badnessValue (int infLevel) return 0; } -int Textblock::BadnessAndPenalty::penaltyValue (int infLevel) +int Textblock::BadnessAndPenalty::penaltyValue (int index, int infLevel) { - switch (penaltyState) { + switch (penaltyState[index]) { case FORCE_BREAK: return infLevel == INF_PENALTIES ? -1 : 0; @@ -41,7 +41,7 @@ int Textblock::BadnessAndPenalty::penaltyValue (int infLevel) return infLevel == INF_PENALTIES ? 1 : 0; case PENALTY_VALUE: - return infLevel == INF_VALUE ? penalty : 0; + return infLevel == INF_VALUE ? penalty[index] : 0; } // compiler happiness @@ -109,12 +109,12 @@ void Textblock::BadnessAndPenalty::calcBadness (int totalWidth, int idealWidth, * are extended by exactly the stretchability, as well as a line, where * all spaces are reduced by the shrinkability, have a badness of 1. */ -void Textblock::BadnessAndPenalty::setPenalty (int penalty) +void Textblock::BadnessAndPenalty::setPenalty (int index, int penalty) { if (penalty == INT_MAX) - setPenaltyProhibitBreak (); + setPenaltyProhibitBreak (index); else if (penalty == INT_MIN) - setPenaltyForceBreak (); + setPenaltyForceBreak (index); else { // This factor consists of: (i) 100^3, since in calcBadness(), the // ratio is multiplied with 100 (again, to use integer numbers for @@ -122,19 +122,19 @@ void Textblock::BadnessAndPenalty::setPenalty (int penalty) // to the penalty!) is the third power or it; (ii) the denominator // 100, of course, since 100 times the penalty is passed to this // method. - this->penalty = penalty * (100 * 100 * 100 / 100); - penaltyState = PENALTY_VALUE; + this->penalty[index] = penalty * (100 * 100 * 100 / 100); + penaltyState[index] = PENALTY_VALUE; } } -void Textblock::BadnessAndPenalty::setPenaltyProhibitBreak () +void Textblock::BadnessAndPenalty::setPenaltyProhibitBreak (int index) { - penaltyState = PROHIBIT_BREAK; + penaltyState[index] = PROHIBIT_BREAK; } -void Textblock::BadnessAndPenalty::setPenaltyForceBreak () +void Textblock::BadnessAndPenalty::setPenaltyForceBreak (int index) { - penaltyState = FORCE_BREAK; + penaltyState[index] = FORCE_BREAK; } bool Textblock::BadnessAndPenalty::lineLoose () @@ -156,21 +156,23 @@ bool Textblock::BadnessAndPenalty::lineTooTight () } -bool Textblock::BadnessAndPenalty::lineMustBeBroken () +bool Textblock::BadnessAndPenalty::lineMustBeBroken (int penaltyIndex) { - return penaltyState == FORCE_BREAK; + return penaltyState[penaltyIndex] == FORCE_BREAK; } -bool Textblock::BadnessAndPenalty::lineCanBeBroken () +bool Textblock::BadnessAndPenalty::lineCanBeBroken (int penaltyIndex) { - return penaltyState != PROHIBIT_BREAK; + return penaltyState[penaltyIndex] != PROHIBIT_BREAK; } -int Textblock::BadnessAndPenalty::compareTo (BadnessAndPenalty *other) +int Textblock::BadnessAndPenalty::compareTo (int penaltyIndex, + BadnessAndPenalty *other) { for (int l = INF_MAX; l >= 0; l--) { - int thisValue = badnessValue (l) + penaltyValue (l); - int otherValue = other->badnessValue (l) + other->penaltyValue (l); + int thisValue = badnessValue (l) + penaltyValue (penaltyIndex, l); + int otherValue = + other->badnessValue (l) + other->penaltyValue (penaltyIndex, l); if (thisValue != otherValue) return thisValue - otherValue; @@ -206,19 +208,25 @@ void Textblock::BadnessAndPenalty::print () printf (" <no debug> + "); #endif - switch (penaltyState) { - case FORCE_BREAK: - printf ("-inf"); - break; - - case PROHIBIT_BREAK: - printf ("inf"); - break; - - case PENALTY_VALUE: - printf ("%d", penalty); - break; + printf ("("); + for (int i = 0; i < 2; i++) { + switch (penaltyState[i]) { + case FORCE_BREAK: + printf ("-inf"); + break; + + case PROHIBIT_BREAK: + printf ("inf"); + break; + + case PENALTY_VALUE: + printf ("%d", penalty[i]); + break; + } + if (i == 0) + printf (", "); } + printf (")"); } void Textblock::printWord (Word *word) @@ -365,7 +373,9 @@ Textblock::Line *Textblock::addLine (int firstWord, int lastWord, line->maxParMin = misc::max (maxOfMinWidth, prevLine->maxParMin); Word *lastWordOfPrevLine = words->getRef (prevLine->lastWord); - if (lastWordOfPrevLine->badnessAndPenalty.lineMustBeBroken ()) + // TODO: lineMustBeBroken should be independent of the penalty + // index? Otherwise, examine the last line. + if (lastWordOfPrevLine->badnessAndPenalty.lineMustBeBroken (0)) // This line starts a new paragraph. line->parMax = sumOfMaxWidth; else @@ -378,7 +388,9 @@ Textblock::Line *Textblock::addLine (int firstWord, int lastWord, // "maxParMax" is only set, when this line is the last line of the // paragraph. Word *lastWordOfThisLine = words->getRef (line->lastWord); - if (lastWordOfThisLine->badnessAndPenalty.lineMustBeBroken ()) + // TODO: lineMustBeBroken should be independent of the penalty + // index? Otherwise, examine the last line. + if (lastWordOfThisLine->badnessAndPenalty.lineMustBeBroken (0)) // Paragraph ends here. line->maxParMax = misc::max (lastMaxParMax, @@ -429,7 +441,8 @@ void Textblock::accumulateWordExtremes (int firstWord, int lastWord, // Minimum: between two *possible* breaks (or at the end). // TODO This is redundant to getExtremesImpl(). - if (word->badnessAndPenalty.lineCanBeBroken () || atLastWord) { + // TODO Again, index 1 is used for lineCanBeBroken(). See getExtremes(). + if (word->badnessAndPenalty.lineCanBeBroken (1) || atLastWord) { parMin += extremes.minWidth + word->hyphenWidth; *maxOfMinWidth = misc::max (*maxOfMinWidth, parMin); parMin = 0; @@ -474,6 +487,8 @@ void Textblock::wordWrap (int wordIndex, bool wrapAll) accumulateWordData (wordIndex); + int penaltyIndex = 0; + bool newLine; do { bool tempNewLine = false; @@ -487,14 +502,16 @@ void Textblock::wordWrap (int wordIndex, bool wrapAll) tempNewLine = true; PRINTF (" NEW LINE: last word\n"); } else if (wordIndex >= firstIndex && - word->badnessAndPenalty.lineMustBeBroken ()) { + // TODO: lineMustBeBroken should be independent of + // the penalty index? + word->badnessAndPenalty.lineMustBeBroken (penaltyIndex)) { newLine = true; searchUntil = wordIndex; PRINTF (" NEW LINE: forced break\n"); } else if (wordIndex > firstIndex && word->badnessAndPenalty.lineTooTight () && words->getRef(wordIndex- 1) - ->badnessAndPenalty.lineCanBeBroken ()) { + ->badnessAndPenalty.lineCanBeBroken (penaltyIndex)) { // TODO Comment the last condition (also below where the minimum is // searched for) newLine = true; @@ -533,7 +550,8 @@ void Textblock::wordWrap (int wordIndex, bool wrapAll) if (breakPos == -1 || w->badnessAndPenalty.compareTo - (&words->getRef(breakPos)->badnessAndPenalty) <= 0) + (penaltyIndex, + &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. @@ -555,9 +573,10 @@ void Textblock::wordWrap (int wordIndex, bool wrapAll) // work.) Word *lastWord = words->getRef (searchUntil); BadnessAndPenalty correctedBap = lastWord->badnessAndPenalty; - correctedBap.setPenalty (0); + correctedBap.setBothPenalties (0); if (correctedBap.compareTo - (&words->getRef(breakPos)->badnessAndPenalty) <= 0) { + (penaltyIndex, + &words->getRef(breakPos)->badnessAndPenalty) <= 0) { breakPos = searchUntil; PRINTF (" corrected: breakPos = %d\n", breakPos); } @@ -699,7 +718,8 @@ int Textblock::hyphenateWord (int wordIndex) // Note: there are numBreaks + 1 word parts. if (i < numBreaks) { // TODO There should be a method fillHyphen. - w->badnessAndPenalty.setPenalty (penalties[PENALTY_HYPHEN][0]); + w->badnessAndPenalty.setPenalty (0, penalties[PENALTY_HYPHEN][0]); + w->badnessAndPenalty.setPenalty (1, penalties[PENALTY_HYPHEN][1]); w->hyphenWidth = layout->textWidth (origWord.style->font, "\xc2\xad", 2); w->flags |= (Word::DRAW_AS_ONE_TEXT | Word::DIV_CHAR_AT_EOL); |