diff options
-rw-r--r-- | dw/textblock.hh | 30 | ||||
-rw-r--r-- | dw/textblock_linebreaking.cc | 86 |
2 files changed, 48 insertions, 68 deletions
diff --git a/dw/textblock.hh b/dw/textblock.hh index eb6dfddd..d70721a0 100644 --- a/dw/textblock.hh +++ b/dw/textblock.hh @@ -155,7 +155,8 @@ private: class BadnessAndPenalty { private: - enum { TOO_LOOSE, QUITE_LOOSE, BADNESS_VALUE, TOO_TIGHT } badnessState; + enum { NOT_STRETCHABLE, QUITE_LOOSE, BADNESS_VALUE, TOO_TIGHT } + badnessState; enum { FORCE_BREAK, PROHIBIT_BREAK, PENALTY_VALUE } penaltyState; int ratio; // ratio is only defined when badness is defined int badness, penalty; @@ -163,12 +164,27 @@ private: // for debugging: int totalWidth, idealWidth, totalStretchability, totalShrinkability; - int badnessInffinities (); - int penaltyInffinities (); - int badnessInfinities (); - int penaltyInfinities (); - int badnessValue (); - int penaltyValue (); + // "Infinity levels" are used to represent very large numbers, + // including "quasi-infinite" numbers. A couple of infinity + // level and number can be mathematically represented as + // + // number * N ^ (infinity level) + // + // where N is a number which is large enough. Practically, + // infinity levels are used to circumvent limited ranges for + // integer numbers. + + // Here, all infinity levels have got special meanings. + enum { + INF_VALUE = 0, // simple values + INF_LARGE, // large values, like QUITE_LOOSE + INF_NOT_STRETCHABLE, // reserved for NOT_STRECTHABLE + INF_INFINITE, // "really" infinite + INF_MAX = INF_INFINITE + }; + + int badnessValue (int infLevel); + int penaltyValue (int infLevel); public: void calcBadness (int totalWidth, int idealWidth, diff --git a/dw/textblock_linebreaking.cc b/dw/textblock_linebreaking.cc index f2175803..80e41945 100644 --- a/dw/textblock_linebreaking.cc +++ b/dw/textblock_linebreaking.cc @@ -10,16 +10,20 @@ using namespace lout; namespace dw { -int Textblock::BadnessAndPenalty::badnessInffinities () +int Textblock::BadnessAndPenalty::badnessValue (int infLevel) { switch (badnessState) { - case TOO_LOOSE: - case TOO_TIGHT: - return 1; + case NOT_STRETCHABLE: + return infLevel == INF_NOT_STRETCHABLE ? 1 : 0; case QUITE_LOOSE: + return infLevel == INF_LARGE ? 1 : 0; + case BADNESS_VALUE: - return 0; + return infLevel == INF_VALUE ? badness : 0; + + case TOO_TIGHT: + return infLevel == INF_INFINITE ? 1 : 0; } // compiler happiness @@ -27,17 +31,17 @@ int Textblock::BadnessAndPenalty::badnessInffinities () return 0; } -int Textblock::BadnessAndPenalty::penaltyInffinities () +int Textblock::BadnessAndPenalty::penaltyValue (int infLevel) { switch (penaltyState) { case FORCE_BREAK: - return -1; + return infLevel == INF_INFINITE ? -1 : 0; case PROHIBIT_BREAK: - return 1; + return infLevel == INF_INFINITE ? 1 : 0; case PENALTY_VALUE: - return 0; + return infLevel == INF_VALUE ? penalty : 0; } // compiler happiness @@ -45,26 +49,6 @@ int Textblock::BadnessAndPenalty::penaltyInffinities () return 0; } -int Textblock::BadnessAndPenalty::badnessInfinities () -{ - return badnessState == QUITE_LOOSE ? ratio : 0; -} - -int Textblock::BadnessAndPenalty::penaltyInfinities () -{ - return 0; -} - -int Textblock::BadnessAndPenalty::badnessValue () -{ - return badnessState == BADNESS_VALUE ? badness : 0; -} - -int Textblock::BadnessAndPenalty::penaltyValue () -{ - return penaltyState == PENALTY_VALUE ? penalty : 0; -} - void Textblock::BadnessAndPenalty::calcBadness (int totalWidth, int idealWidth, int totalStretchability, int totalShrinkability) @@ -81,7 +65,7 @@ void Textblock::BadnessAndPenalty::calcBadness (int totalWidth, int idealWidth, badness = 0; } else if (totalWidth < idealWidth) { if (totalStretchability == 0) - badnessState = TOO_LOOSE; + badnessState = NOT_STRETCHABLE; else { ratio = 100 * (idealWidth - totalWidth) / totalStretchability; if (ratio > 1024) @@ -126,7 +110,7 @@ void Textblock::BadnessAndPenalty::setPenaltyForceBreak () bool Textblock::BadnessAndPenalty::lineLoose () { return - badnessState == TOO_LOOSE || badnessState == QUITE_LOOSE || + badnessState == NOT_STRETCHABLE || badnessState == QUITE_LOOSE || (badnessState == BADNESS_VALUE && ratio > 0); } @@ -154,42 +138,22 @@ bool Textblock::BadnessAndPenalty::lineCanBeBroken () int Textblock::BadnessAndPenalty::compareTo (BadnessAndPenalty *other) { - // First, a special condition: if a line is too tight, it will - // always be regarded as worse than a line, which is not too - // tight. Especially, lines too tight are worse than lines too - // loose. See test/table-1.html as a text case: the first line, - // which contains only the word "Short,", is too loose, but not - // breaking here would make the line too tight, making the text - // overwrap the available space. - - if (lineTooTight() && !other->lineTooTight()) - return 1; - if (!lineTooTight() && other->lineTooTight()) - return -1; - - int thisNumInffinities = badnessInffinities () + penaltyInffinities (); - int otherNumInffinities = - other->badnessInffinities () + other->penaltyInffinities (); - int thisNumInfinities = badnessInfinities () + penaltyInfinities (); - int otherNumInfinities = - other->badnessInfinities () + other->penaltyInfinities (); - int thisValue = badnessValue () + penaltyValue (); - int otherValue = other->badnessValue () + other->penaltyValue (); - - if (thisNumInffinities == otherNumInffinities) { - if (thisNumInfinities == otherNumInfinities) + for (int l = INF_MAX; l >= 0; l--) { + int thisValue = badnessValue (l) + penaltyValue (l); + int otherValue = other->badnessValue (l) + other->penaltyValue (l); + + if (thisValue != otherValue) return thisValue - otherValue; - else - return thisNumInfinities - otherNumInfinities; - } else - return thisNumInffinities - otherNumInffinities; + } + + return 0; } void Textblock::BadnessAndPenalty::print () { switch (badnessState) { - case TOO_LOOSE: - printf ("too loose"); + case NOT_STRETCHABLE: + printf ("not stretchable"); break; case TOO_TIGHT: |