aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Geerken <devnull@localhost>2012-11-13 22:59:02 +0100
committerSebastian Geerken <devnull@localhost>2012-11-13 22:59:02 +0100
commit3b53c5940970f002e2e77b347802f8e2c9684904 (patch)
tree930f69e45b19b8458af6060cf4e13c17062ae87b
parent0085643208798a991babbe9d0bce37d9193b245a (diff)
Introduced two penalties. (Not used yet.)
-rw-r--r--dw/textblock.cc41
-rw-r--r--dw/textblock.hh26
-rw-r--r--dw/textblock_linebreaking.cc100
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);