aboutsummaryrefslogtreecommitdiff
path: root/dw/textblock.cc
diff options
context:
space:
mode:
authorSebastian Geerken <devnull@localhost>2012-09-14 11:34:19 +0200
committerSebastian Geerken <devnull@localhost>2012-09-14 11:34:19 +0200
commite4367b16dc131f34936bbb8fd09557b5aa5acbd7 (patch)
tree487a35941bf20bbc95a3d0b1dee420b00771f5b6 /dw/textblock.cc
parentabd446c2eebe1f96764b6d95f1c6c61ae9bc40b2 (diff)
parent94e451ffa5ece79a3b071ee553650bf8bd869a46 (diff)
Merge of <http://hg.dillo.org/dillo>.
Diffstat (limited to 'dw/textblock.cc')
-rw-r--r--dw/textblock.cc1472
1 files changed, 685 insertions, 787 deletions
diff --git a/dw/textblock.cc b/dw/textblock.cc
index 6ded2413..6aa75a13 100644
--- a/dw/textblock.cc
+++ b/dw/textblock.cc
@@ -17,20 +17,21 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
#include "textblock.hh"
#include "table.hh" // Yes, this is ugly. -- SG
#include "../lout/msg.h"
#include "../lout/misc.hh"
#include <stdio.h>
-#include <math.h> // remove again
+#include <math.h> // remove again?
#include <limits.h>
/*
* Local variables
*/
- /* The tooltip under mouse pointer in current textblock. No ref. hold.
- * (having one per view looks not worth the extra clutter). */
+/* The tooltip under mouse pointer in current textblock. No ref. hold.
+ * (having one per view looks not worth the extra clutter). */
static dw::core::style::Tooltip *hoverTooltip = NULL;
@@ -51,7 +52,6 @@ Textblock::Textblock (bool limitTextWidth)
hasListitemValue = false;
innerPadding = 0;
line1Offset = 0;
- line1OffsetEff = 0;
ignoreLine1OffsetSometimes = false;
mustQueueResize = false;
redrawY = 0;
@@ -67,21 +67,19 @@ Textblock::Textblock (bool limitTextWidth)
* TODO: Some tests would be useful.
*/
lines = new misc::SimpleVector <Line> (1);
- words = new misc::SimpleVector <Word> (1);
- leftFloatSide = rightFloatSide = NULL;
+ nonTemporaryLines = 0;
+ words = new misc::NotSoSimpleVector <Word> (1);
anchors = new misc::SimpleVector <Anchor> (1);
+ leftFloatSide = rightFloatSide = NULL;
- //DBG_OBJ_SET_NUM(page, "num_lines", num_lines);
+ //DBG_OBJ_SET_NUM(this, "num_lines", num_lines);
- lastLineWidth = 0;
- lastLineParMin = 0;
- lastLineParMax = 0;
wrapRef = -1;
- //DBG_OBJ_SET_NUM(page, "last_line_width", last_line_width);
- //DBG_OBJ_SET_NUM(page, "last_line_par_min", last_line_par_min);
- //DBG_OBJ_SET_NUM(page, "last_line_par_max", last_line_par_max);
- //DBG_OBJ_SET_NUM(page, "wrap_ref", wrap_ref);
+ //DBG_OBJ_SET_NUM(this, "last_line_width", last_line_width);
+ //DBG_OBJ_SET_NUM(this, "last_line_par_min", last_line_par_min);
+ //DBG_OBJ_SET_NUM(this, "last_line_par_max", last_line_par_max);
+ //DBG_OBJ_SET_NUM(this, "wrap_ref", wrap_ref);
hoverLink = -1;
@@ -125,7 +123,7 @@ Textblock::~Textblock ()
delete lines;
delete words;
delete anchors;
-
+
if(leftFloatSide)
delete leftFloatSide;
if(rightFloatSide)
@@ -135,7 +133,7 @@ Textblock::~Textblock ()
parent class destructor. (???) */
words = NULL;
- //DBG_OBJ_SET_NUM(page, "num_lines", page->num_lines);
+ //DBG_OBJ_SET_NUM(this, "num_lines", lines->size ());
}
/**
@@ -145,12 +143,27 @@ Textblock::~Textblock ()
*/
void Textblock::sizeRequestImpl (core::Requisition *requisition)
{
+ PRINTF ("[%p] SIZE_REQUEST: ...\n", this);
+
rewrap ();
+ showMissingLines ();
if (lines->size () > 0) {
Line *lastLine = lines->getRef (lines->size () - 1);
- requisition->width =
- misc::max (lastLine->maxLineWidth, lastLineWidth);
+ requisition->width = lastLine->maxLineWidth;
+
+ PRINTF ("[%p] SIZE_REQUEST: lastLine->maxLineWidth = %d\n",
+ this, lastLine->maxLineWidth);
+
+ PRINTF ("[%p] SIZE_REQUEST: lines[0]->boxAscent = %d\n",
+ this, lines->getRef(0)->boxAscent);
+ PRINTF ("[%p] SIZE_REQUEST: lines[%d]->top = %d\n",
+ this, lines->size () - 1, lastLine->top);
+ PRINTF ("[%p] SIZE_REQUEST: lines[%d]->boxAscent = %d\n",
+ this, lines->size () - 1, lastLine->boxAscent);
+ PRINTF ("[%p] SIZE_REQUEST: lines[%d]->boxDescent = %d\n",
+ this, lines->size () - 1, lastLine->boxDescent);
+
/* Note: the breakSpace of the last line is ignored, so breaks
at the end of a textblock are not visible. */
requisition->ascent = lines->getRef(0)->boxAscent;
@@ -158,17 +171,23 @@ void Textblock::sizeRequestImpl (core::Requisition *requisition)
+ lastLine->boxAscent + lastLine->boxDescent -
lines->getRef(0)->boxAscent;
} else {
- requisition->width = lastLineWidth;
+ requisition->width = 0; // before: lastLineWidth;
requisition->ascent = 0;
requisition->descent = 0;
}
+ PRINTF ("[%p] SIZE_REQUEST: inner padding = %d, boxDiffWidth = %d\n",
+ this, innerPadding, getStyle()->boxDiffWidth ());
+
requisition->width += innerPadding + getStyle()->boxDiffWidth ();
requisition->ascent += getStyle()->boxOffsetY ();
requisition->descent += getStyle()->boxRestHeight ();
if (requisition->width < availWidth)
requisition->width = availWidth;
+
+ PRINTF ("[%p] SIZE_REQUEST: %d x %d + %d\n", this, requisition->width,
+ requisition->ascent, requisition->descent);
}
/**
@@ -206,147 +225,125 @@ void Textblock::getWordExtremes (Word *word, core::Extremes *extremes)
void Textblock::getExtremesImpl (core::Extremes *extremes)
{
- core::Extremes wordExtremes;
- Line *line;
- Word *word;
- int wordIndex, lineIndex;
- int parMin, parMax;
- bool nowrap;
+ PRINTF ("[%p] GET_EXTREMES: ...\n", this);
- //DBG_MSG (widget, "extremes", 0, "Dw_page_get_extremes");
- //DBG_MSG_START (widget);
+ showMissingLines ();
if (lines->size () == 0) {
/* empty page */
extremes->minWidth = 0;
extremes->maxWidth = 0;
+
+ PRINTF ("GET_EXTREMES: empty (but %d words)\n", words->size());
} else if (wrapRef == -1) {
/* no rewrap necessary -> values in lines are up to date */
- line = lines->getRef (lines->size () - 1);
- /* Historical note: The former distinction between lines with and without
- * words[first_word]->nowrap set is no longer necessary, since
- * Dw_page_real_word_wrap sets max_word_min to the correct value in any
- * case. */
- extremes->minWidth = line->maxWordMin;
- extremes->maxWidth = misc::max (line->maxParMax, lastLineParMax);
- //DBG_MSG (widget, "extremes", 0, "simple case");
+ Line *lastLine = lines->getRef (lines->size () - 1);
+ extremes->minWidth = lastLine->maxParMin;
+ Word *lastWord = words->getRef (lastLine->lastWord);
+ extremes->maxWidth =
+ misc::max (lastLine->maxParMax,
+ // parMax includes the last space, which we ignore here
+ lastLine->parMax - lastWord->origSpace
+ + lastWord->hyphenWidth);
+
+ PRINTF ("GET_EXTREMES: no rewrap => %d, %d\n",
+ lastLine->maxParMin, lastLine->maxParMax);
} else {
+ int parMax;
/* Calculate the extremes, based on the values in the line from
where a rewrap is necessary. */
- //DBG_MSG (widget, "extremes", 0, "complex case");
+
+ PRINTF ("GET_EXTREMES: complex case ...\n");
if (wrapRef == 0) {
extremes->minWidth = 0;
extremes->maxWidth = 0;
- parMin = 0;
parMax = 0;
} else {
- line = lines->getRef (wrapRef);
- extremes->minWidth = line->maxWordMin;
- extremes->maxWidth = line->maxParMax;
- parMin = line->parMin;
+ // Line [wrapRef - 1], not [wrapRef], because maxParMin and
+ // maxParMax include the respective values *in* any line
+ // (accumulated up to the *end*), but we start at line
+ // [wrapRef], so these are not needed.
+
+ Line *line = lines->getRef (wrapRef - 1);
+ Word *lastWord = words->getRef (line->lastWord);
+ extremes->minWidth = line->maxParMin;
+ // consider also accumulated next value of maxParMax: parMax
+ extremes->maxWidth =
+ misc::max (line->maxParMax,
+ // parMax includes the last space, which we ignore here
+ line->parMax - lastWord->origSpace
+ + lastWord->hyphenWidth);
parMax = line->parMax;
-
- //DBG_MSGF (widget, "extremes", 0, "parMin = %d", parMin);
}
- //_MSG ("*** parMin = %d\n", parMin);
-
- int prevWordSpace = 0;
- for (lineIndex = wrapRef; lineIndex < lines->size (); lineIndex++) {
- //DBG_MSGF (widget, "extremes", 0, "line %d", lineIndex);
- //DBG_MSG_START (widget);
- core::style::WhiteSpace ws;
-
- line = lines->getRef (lineIndex);
- ws = words->getRef(line->firstWord)->style->whiteSpace;
- nowrap = ws == core::style::WHITE_SPACE_PRE ||
- ws == core::style::WHITE_SPACE_NOWRAP;
-
- //DEBUG_MSG (DEBUG_SIZE_LEVEL, " line %d (of %d), nowrap = %d\n",
- // lineIndex, page->num_lines, nowrap);
-
- for (wordIndex = line->firstWord; wordIndex <= line->lastWord;
- wordIndex++) {
- word = words->getRef (wordIndex);
+ if (wrapRef < lines->size()) {
+ int parMin = 0;
+
+ for (int wordIndex = lines->getRef(wrapRef)->firstWord;
+ wordIndex < words->size(); wordIndex++) {
+ Word *word = words->getRef (wordIndex);
+ bool atLastWord = wordIndex == words->size() - 1;
+
+ //printf (" word: ");
+ //printWord (word);
+ //printf ("\n");
+
+ core::Extremes wordExtremes;
getWordExtremes (word, &wordExtremes);
-
if (wordIndex == 0) {
- wordExtremes.minWidth += line1OffsetEff;
- wordExtremes.maxWidth += line1OffsetEff;
- //DEBUG_MSG (DEBUG_SIZE_LEVEL + 1,
- // " (next plus %d)\n", page->line1_offset);
- }
-
- if (nowrap) {
- parMin += prevWordSpace + wordExtremes.minWidth;
- //DBG_MSGF (widget, "extremes", 0, "parMin = %d", parMin);
- } else {
- if (extremes->minWidth < wordExtremes.minWidth)
- extremes->minWidth = wordExtremes.minWidth;
+ wordExtremes.minWidth += line1Offset;
+ wordExtremes.maxWidth += line1Offset;
}
-
- _MSG("parMax = %d, wordMaxWidth=%d, prevWordSpace=%d\n",
- parMax, wordExtremes.maxWidth, prevWordSpace);
- if (word->content.type != core::Content::BREAK)
- parMax += prevWordSpace;
- parMax += wordExtremes.maxWidth;
- prevWordSpace = word->origSpace;
-
- //DEBUG_MSG (DEBUG_SIZE_LEVEL + 1,
- // " word %s: maxWidth = %d\n",
- // a_Dw_content_text (&word->content),
- // word_extremes.maxWidth);
+
+ // Minimum: between two *possible* breaks (or at the end).
+ if (word->badnessAndPenalty.lineCanBeBroken () || atLastWord) {
+ parMin += wordExtremes.minWidth + word->hyphenWidth;
+ extremes->minWidth = misc::max (extremes->minWidth, parMin);
+ parMin = 0;
+ } else
+ // Shrinkability could be considered, but really does not play a
+ // role.
+ parMin += wordExtremes.minWidth + word->origSpace;
+
+ // Maximum: between two *neccessary* breaks (or at the end).
+ if (word->badnessAndPenalty.lineMustBeBroken () || atLastWord) {
+ parMax += wordExtremes.maxWidth + word->hyphenWidth;
+ extremes->maxWidth = misc::max (extremes->maxWidth, parMax);
+ parMax = 0;
+ } else
+ parMax += wordExtremes.maxWidth + word->origSpace;
+
+ PRINTF (" => ... extremes = %d / %d, parMin = %d, parMax = %d\n",
+ extremes->minWidth, extremes->maxWidth, parMin, parMax);
}
-
- if ((words->getRef(line->lastWord)->content.type
- == core::Content::BREAK ) ||
- lineIndex == lines->size () - 1 ) {
-
- //DEBUG_MSG (DEBUG_SIZE_LEVEL + 2,
- // " parMax = %d, after word %d (%s)\n",
- // parMax, line->last_word - 1,
- // a_Dw_content_text (&word->content));
-
- if (extremes->maxWidth < parMax)
- extremes->maxWidth = parMax;
-
- if (nowrap) {
- //DBG_MSGF (widget, "extremes", 0, "parMin = %d", parMin);
- if (extremes->minWidth < parMin)
- extremes->minWidth = parMin;
-
- //DEBUG_MSG (DEBUG_SIZE_LEVEL + 2,
- // " parMin = %d, after word %d (%s)\n",
- // parMin, line->last_word - 1,
- // a_Dw_content_text (&word->content));
- }
-
- prevWordSpace = 0;
- parMin = 0;
- parMax = 0;
- }
-
- //DBG_MSG_END (widget);
}
-
- //DEBUG_MSG (DEBUG_SIZE_LEVEL + 3, " Result: %d, %d\n",
- // extremes->minWidth, extremes->maxWidth);
}
- //DBG_MSGF (widget, "extremes", 0, "width difference: %d + %d",
- // page->inner_padding, p_Dw_style_box_diff_width (widget->style));
-
int diff = innerPadding + getStyle()->boxDiffWidth ();
extremes->minWidth += diff;
extremes->maxWidth += diff;
- //DBG_MSG_END (widget);
+ //printf ("[%p] GET_EXTREMES, on textblock that ", this);
+ //if (words->size() == 0)
+ // printf ("is empty\n");
+ //else {
+ // printf ("starts with:\n ");
+ // printWord (words->getRef(0));
+ // printf ("\n");
+ //}
+ //printf ("=> %d / %d\n", extremes->minWidth, extremes->maxWidth);
}
void Textblock::sizeAllocateImpl (core::Allocation *allocation)
{
+ PRINTF ("[%p] SIZE_ALLOCATE: %d, %d, %d x %d + %d\n",
+ this, allocation->x, allocation->y, allocation->width,
+ allocation->ascent, allocation->descent);
+
+ showMissingLines ();
+
int lineIndex, wordIndex;
Line *line;
Word *word;
@@ -441,7 +438,7 @@ void Textblock::sizeAllocateImpl (core::Allocation *allocation)
xCursor += (word->size.width + word->effSpace);
}
}
-
+
if(leftFloatSide)
leftFloatSide->sizeAllocate(allocation);
if(rightFloatSide)
@@ -450,7 +447,7 @@ void Textblock::sizeAllocateImpl (core::Allocation *allocation)
for (int i = 0; i < anchors->size(); i++) {
Anchor *anchor = anchors->getRef(i);
int y;
-
+
if (anchor->wordIndex >= words->size()) {
y = allocation->y + allocation->ascent + allocation->descent;
} else {
@@ -490,14 +487,17 @@ void Textblock::markExtremesChange (int ref)
*/
void Textblock::markChange (int ref)
{
- printf("markChange(%d)\n", ref);
+ PRINTF ("[%p] MARK_CHANGE (%d): %d => ...\n", this, ref, wrapRef);
+
+ /* By the way: ref == -1 may have two different causes: (i) flush()
+ calls "queueResize (-1, true)", when no rewrapping is necessary;
+ and (ii) a word may have parentRef == -1 , when it is not yet
+ added to a line. In the latter case, nothing has to be done
+ now, but addLine(...) will do everything neccessary. */
int refEquiv = (ref == 0) ? 1 | (dw::core::style::FLOAT_NONE << 1) : ref;
if (refEquiv != -1 && (refEquiv & 1)) {
- //DBG_MSGF (page, "wrap", 0, "Dw_page_mark_size_change (ref = %d)", ref);
-
- // ABC
switch((refEquiv >> 1) & 3)
{
case dw::core::style::FLOAT_NONE:
@@ -518,11 +518,13 @@ void Textblock::markChange (int ref)
break;
}
}
+
+ PRINTF (" ... => %d\n", wrapRef);
}
void Textblock::notifySetAsTopLevel()
{
- containingBox = this;
+ containingBox = this;
}
void Textblock::notifySetParent()
@@ -532,21 +534,25 @@ void Textblock::notifySetParent()
containingBox = NULL;
Textblock *topmostTextblock = this;
- for(Widget *widget = getParent(); widget != NULL; widget = widget->getParent())
+ for(Widget *widget = getParent(); widget != NULL;
+ widget = widget->getParent())
{
if(widget->instanceOf(Textblock::CLASS_ID))
topmostTextblock = (Textblock*)widget;
}
- for(Widget *widget = getParent(); containingBox == NULL; widget = widget->getParent())
+ for(Widget *widget = getParent(); containingBox == NULL;
+ widget = widget->getParent())
{
if(widget->getParent() == NULL)
// No other widget left.
containingBox = topmostTextblock;
else if(widget->instanceOf(Textblock::CLASS_ID))
{
- if(widget->getParent()->instanceOf(Table::CLASS_ID) /* this widget is a table cell */ ||
- widget->getStyle()->vloat != dw::core::style::FLOAT_NONE /* this widget is a float */)
+ if(// this widget is a table cell
+ widget->getParent()->instanceOf(Table::CLASS_ID) ||
+ // this widget is a float
+ widget->getStyle()->vloat != dw::core::style::FLOAT_NONE)
containingBox = (Textblock*)widget;
}
}
@@ -554,13 +560,13 @@ void Textblock::notifySetParent()
void Textblock::setWidth (int width)
{
- /* If limitTextWidth is set to YES, a queue_resize may also be
+ /* If limitTextWidth is set to YES, a queueResize() may also be
* necessary. */
if (availWidth != width || limitTextWidth) {
//DEBUG_MSG(DEBUG_REWRAP_LEVEL,
- // "Dw_page_set_width: Calling p_Dw_widget_queue_resize, "
+ // "setWidth: Calling queueResize, "
// "in page with %d word(s)\n",
- // page->num_words);
+ // words->size());
availWidth = width;
//<<<<<<< textblock.cc
@@ -577,9 +583,9 @@ void Textblock::setAscent (int ascent)
{
if (availAscent != ascent) {
//DEBUG_MSG(DEBUG_REWRAP_LEVEL,
- // "Dw_page_set_ascent: Calling p_Dw_widget_queue_resize, "
+ // "setAscent: Calling queueResize, "
// "in page with %d word(s)\n",
- // page->num_words);
+ // words->size());
availAscent = ascent;
//<<<<<<< textblock.cc
@@ -595,9 +601,9 @@ void Textblock::setDescent (int descent)
{
if (availDescent != descent) {
//DEBUG_MSG(DEBUG_REWRAP_LEVEL,
- // "Dw_page_set_descent: Calling p_Dw_widget_queue_resize, "
+ // "setDescent: Calling queueResize, "
// "in page with %d word(s)\n",
- // page->num_words);
+ // words->size());
availDescent = descent;
//<<<<<<< textblock.cc
@@ -694,102 +700,113 @@ bool Textblock::sendSelectionEvent (core::SelectionState::EventType eventType,
core::MousePositionEvent *event)
{
core::Iterator *it;
- Line *line, *lastLine;
- int nextWordStartX, wordStartX, wordX, nextWordX, yFirst, yLast;
- int charPos = 0, link = -1, prevPos, wordIndex, lineIndex;
- Word *word;
- bool found, r;
+ int wordIndex;
+ int charPos = 0, link = -1;
+ bool r;
if (words->size () == 0) {
wordIndex = -1;
} else {
- lastLine = lines->getRef (lines->size () - 1);
- yFirst = lineYOffsetCanvasI (0);
- yLast = lineYOffsetCanvas (lastLine) + lastLine->boxAscent +
- lastLine->boxDescent;
+ Line *lastLine = lines->getRef (lines->size () - 1);
+ int yFirst = lineYOffsetCanvasI (0);
+ int yLast = lineYOffsetCanvas (lastLine) + lastLine->boxAscent +
+ lastLine->boxDescent;
if (event->yCanvas < yFirst) {
// Above the first line: take the first word.
wordIndex = 0;
- charPos = 0;
} else if (event->yCanvas >= yLast) {
// Below the last line: take the last word.
wordIndex = words->size () - 1;
- word = words->getRef (wordIndex);
- charPos = word->content.type == core::Content::TEXT ?
- strlen (word->content.text) : 0;
+ charPos = core::SelectionState::END_OF_WORD;
} else {
- lineIndex = findLineIndex (event->yWidget);
- line = lines->getRef (lineIndex);
+ Line *line = lines->getRef (findLineIndex (event->yWidget));
// Pointer within the break space?
if (event->yWidget >
(lineYOffsetWidget (line) + line->boxAscent + line->boxDescent)) {
// Choose this break.
wordIndex = line->lastWord;
- charPos = 0;
+ charPos = core::SelectionState::END_OF_WORD;
} else if (event->xWidget < lineXOffsetWidget (line)) {
// Left of the first word in the line.
wordIndex = line->firstWord;
- charPos = 0;
} else {
- nextWordStartX = lineXOffsetWidget (line);
- found = false;
+ int nextWordStartX = lineXOffsetWidget (line);
+
for (wordIndex = line->firstWord;
- !found && wordIndex <= line->lastWord;
+ wordIndex <= line->lastWord;
wordIndex++) {
- word = words->getRef (wordIndex);
- wordStartX = nextWordStartX;
+ Word *word = words->getRef (wordIndex);
+ int wordStartX = nextWordStartX;
+
nextWordStartX += word->size.width + word->effSpace;
if (event->xWidget >= wordStartX &&
event->xWidget < nextWordStartX) {
// We have found the word.
- if (word->content.type == core::Content::TEXT) {
- // Search the character the mouse pointer is in.
- // nextWordX is the right side of this character.
- charPos = 0;
- while ((nextWordX = wordStartX +
- layout->textWidth (word->style->font,
- word->content.text, charPos))
- <= event->xWidget)
- charPos = layout->nextGlyph (word->content.text,
- charPos);
- // The left side of this character.
- prevPos = layout->prevGlyph (word->content.text, charPos);
- wordX = wordStartX + layout->textWidth (word->style->font,
- word->content.text,
- prevPos);
-
- // If the mouse pointer is left from the middle, use the
- // left position, otherwise, use the right one.
- if (event->xWidget <= (wordX + nextWordX) / 2)
- charPos = prevPos;
+ int yWidgetBase = lineYOffsetWidget (line) + line->boxAscent;
+
+ if (event->xWidget >= nextWordStartX - word->effSpace) {
+ charPos = core::SelectionState::END_OF_WORD;
+ if (wordIndex < line->lastWord &&
+ (words->getRef(wordIndex + 1)->content.type !=
+ core::Content::BREAK) &&
+ (event->yWidget <=
+ yWidgetBase + word->spaceStyle->font->descent) &&
+ (event->yWidget >
+ yWidgetBase - word->spaceStyle->font->ascent)) {
+ link = word->spaceStyle->x_link;
+ }
} else {
- // Depends on whether the pointer is within the left or
- // right half of the (non-text) word.
- if (event->xWidget >=
- (wordStartX + nextWordStartX) / 2)
- charPos = core::SelectionState::END_OF_WORD;
- else
- charPos = 0;
+ if (event->yWidget <= yWidgetBase + word->size.descent &&
+ event->yWidget > yWidgetBase - word->size.ascent) {
+ link = word->style->x_link;
+ }
+ if (word->content.type == core::Content::TEXT) {
+ int glyphX = wordStartX;
+
+ while (1) {
+ int nextCharPos =
+ layout->nextGlyph (word->content.text, charPos);
+ int glyphWidth =
+ textWidth (word->content.text, charPos,
+ nextCharPos - charPos, word->style);
+ if (event->xWidget > glyphX + glyphWidth) {
+ glyphX += glyphWidth;
+ charPos = nextCharPos;
+ continue;
+ } else if (event->xWidget >= glyphX + glyphWidth/2){
+ // On the right half of a character;
+ // now just look for combining chars
+ charPos = nextCharPos;
+ while (word->content.text[charPos]) {
+ nextCharPos =
+ layout->nextGlyph (word->content.text,
+ charPos);
+ if (textWidth (word->content.text, charPos,
+ nextCharPos - charPos,
+ word->style))
+ break;
+ charPos = nextCharPos;
+ }
+ }
+ break;
+ }
+ } else {
+ // Depends on whether the pointer is within the left or
+ // right half of the (non-text) word.
+ if (event->xWidget >= (wordStartX + nextWordStartX) /2)
+ charPos = core::SelectionState::END_OF_WORD;
+ }
}
-
- found = true;
- link = word->style ? word->style->x_link : -1;
break;
}
}
-
- if (!found) {
+ if (wordIndex > line->lastWord) {
// No word found in this line (i.e. we are on the right side),
// take the last of this line.
wordIndex = line->lastWord;
- if (wordIndex >= words->size ())
- wordIndex--;
- word = words->getRef (wordIndex);
- charPos = word->content.type == core::Content::TEXT ?
- strlen (word->content.text) :
- (int)core::SelectionState::END_OF_WORD;
+ charPos = core::SelectionState::END_OF_WORD;
}
}
}
@@ -811,391 +828,6 @@ core::Iterator *Textblock::iterator (core::Content::Type mask, bool atEnd)
return new TextblockIterator (this, mask, atEnd);
}
-/*
- * ...
- *
- * availWidth is passed from wordWrap, to avoid calculating it twice.
- */
-void Textblock::justifyLine (Line *line, int availWidth)
-{
- /* To avoid rounding errors, the calculation is based on accumulated
- * values (*_cum). */
- int i;
- int origSpaceSum, origSpaceCum;
- int effSpaceDiffCum, lastEffSpaceDiffCum;
- int diff;
-
- diff = availWidth - lastLineWidth;
- if (diff > 0) {
- origSpaceSum = 0;
- for (i = line->firstWord; i < line->lastWord; i++)
- origSpaceSum += words->getRef(i)->origSpace;
-
- origSpaceCum = 0;
- lastEffSpaceDiffCum = 0;
- for (i = line->firstWord; i < line->lastWord; i++) {
- origSpaceCum += words->getRef(i)->origSpace;
-
- if (origSpaceCum == 0)
- effSpaceDiffCum = lastEffSpaceDiffCum;
- else
- effSpaceDiffCum = diff * origSpaceCum / origSpaceSum;
-
- words->getRef(i)->effSpace = words->getRef(i)->origSpace +
- (effSpaceDiffCum - lastEffSpaceDiffCum);
- //DBG_OBJ_ARRSET_NUM (page, "words.%d.eff_space", i,
- // page->words[i].eff_space);
-
- lastEffSpaceDiffCum = effSpaceDiffCum;
- }
- }
-}
-
-
-Textblock::Line *Textblock::addLine (int wordIndex, bool newPar)
-{
- Line *lastLine;
-
- //DBG_MSG (page, "wrap", 0, "Dw_page_add_line");
- //DBG_MSG_START (page);
-
- lines->increase ();
- //DBG_OBJ_SET_NUM(page, "num_lines", page->num_lines);
-
- //DEBUG_MSG (DEBUG_REWRAP_LEVEL, "--- new line %d in %p, with word %d of %d"
- // "\n", page->num_lines - 1, page, word_ind, page->num_words);
-
- lastLine = lines->getRef (lines->size () - 1);
-
- if (lines->size () == 1) {
- lastLine->top = 0;
- lastLine->maxLineWidth = line1OffsetEff;
- lastLine->maxWordMin = 0;
- lastLine->maxParMax = 0;
- } else {
- Line *prevLine = lines->getRef (lines->size () - 2);
-
- lastLine->top = prevLine->top + prevLine->boxAscent +
- prevLine->boxDescent + prevLine->breakSpace;
- lastLine->maxLineWidth = prevLine->maxLineWidth;
- lastLine->maxWordMin = prevLine->maxWordMin;
- lastLine->maxParMax = prevLine->maxParMax;
- }
-
- //DBG_OBJ_ARRSET_NUM (page, "lines.%d.top", page->num_lines - 1,
- // lastLine->top);
- //DBG_OBJ_ARRSET_NUM (page, "lines.%d.maxLineWidth", page->num_lines - 1,
- // lastLine->maxLineWidth);
- //DBG_OBJ_ARRSET_NUM (page, "lines.%d.maxWordMin", page->num_lines - 1,
- // lastLine->maxWordMin);
- //DBG_OBJ_ARRSET_NUM (page, "lines.%d.maxParMax", page->num_lines - 1,
- // lastLine->maxParMax);
- //DBG_OBJ_ARRSET_NUM (page, "lines.%d.parMin", page->num_lines - 1,
- // lastLine->parMin);
- //DBG_OBJ_ARRSET_NUM (page, "lines.%d.parMax", page->num_lines - 1,
- // lastLine->parMax);
-
- lastLine->firstWord = wordIndex;
- lastLine->boxAscent = lastLine->contentAscent = 0;
- lastLine->boxDescent = lastLine->contentDescent = 0;
- lastLine->marginDescent = 0;
- lastLine->breakSpace = 0;
- lastLine->leftOffset = 0;
- lastLine->boxLeft = 0;
- lastLine->boxRight = 0;
-
- //DBG_OBJ_ARRSET_NUM (page, "lines.%d.ascent", page->num_lines - 1,
- // lastLine->boxAscent);
- //DBG_OBJ_ARRSET_NUM (page, "lines.%d.descent", page->num_lines - 1,
- // lastLine->boxDescent);
-
- /* update values in line */
- lastLine->maxLineWidth = misc::max (lastLine->maxLineWidth, lastLineWidth);
-
- if (lines->size () > 1)
- lastLineWidth = 0;
- else
- lastLineWidth = line1OffsetEff;
-
- if (newPar) {
- lastLine->maxParMax = misc::max (lastLine->maxParMax, lastLineParMax);
- //DBG_OBJ_ARRSET_NUM (page, "lines.%d.maxParMax", page->num_lines - 1,
- // lastLine->maxParMax);
-
- /* The following code looks questionable (especially since the values
- * will be overwritten). In any case, line1OffsetEff is probably
- * supposed to go into lastLinePar*, not lastLine->par*.
- */
- if (lines->size () > 1) {
- lastLine->parMin = 0;
- lastLine->parMax = 0;
- } else {
- lastLine->parMin = line1OffsetEff;
- lastLine->parMax = line1OffsetEff;
- }
- lastLineParMin = 0;
- lastLineParMax = 0;
-
- //DBG_OBJ_SET_NUM(page, "lastLineParMin", page->lastLineParMin);
- //DBG_OBJ_SET_NUM(page, "lastLineParMax", page->lastLineParMax);
- }
-
- lastLine->parMin = lastLineParMin;
- lastLine->parMax = lastLineParMax;
-
- //DBG_OBJ_ARRSET_NUM (page, "lines.%d.parMin", page->num_lines - 1,
- // lastLine->parMin);
- //DBG_OBJ_ARRSET_NUM (page, "lines.%d.parMax", page->num_lines - 1,
- // lastLine->parMax);
-
- //DBG_MSG_END (page);
- return lastLine;
-}
-
-/*
- * This method is called in two cases: (i) when a word is added
- * (ii) when a page has to be (partially) rewrapped. It does word wrap,
- * and adds new lines if necessary.
- */
-void Textblock::wordWrap(int wordIndex)
-{
- Line *lastLine;
- Word *word;
- int availWidth, lastSpace, leftOffset, len;
- bool newLine = false, newPar = false;
- core::Extremes wordExtremes;
-
- //DBG_MSGF (page, "wrap", 0, "Dw_page_real_word_wrap (%d): %s, width = %d",
- // word_ind, a_Dw_content_html (&page->words[word_ind].content),
- // page->words[word_ind].size.width);
- //DBG_MSG_START (page);
-
- availWidth = this->availWidth - getStyle()->boxDiffWidth() - innerPadding;
- if (limitTextWidth &&
- layout->getUsesViewport () &&
- availWidth > layout->getWidthViewport () - 10)
- availWidth = layout->getWidthViewport () - 10;
-
- word = words->getRef (wordIndex);
- word->effSpace = word->origSpace;
-
- /* Test whether line1Offset can be used. */
- if (wordIndex == 0) {
- if (ignoreLine1OffsetSometimes &&
- line1Offset + word->size.width > availWidth) {
- line1OffsetEff = 0;
- } else {
- int indent = 0;
-
- if (word->content.type == core::Content::WIDGET &&
- word->content.widget->blockLevel() == true) {
- /* don't use text-indent when nesting blocks */
- } else {
- if (core::style::isPerLength(getStyle()->textIndent)) {
- indent = misc::roundInt(this->availWidth *
- core::style::perLengthVal (getStyle()->textIndent));
- } else {
- indent = core::style::absLengthVal (getStyle()->textIndent);
- }
- }
- line1OffsetEff = line1Offset + indent;
- }
- }
-
- if(word->content.type == dw::core::Content::FLOAT_REF)
- {
- Line *line = lines->size() > 0 ? lines->getRef(lines->size() - 1) : NULL;
- int y =
- allocation.y - containingBox->allocation.y + getStyle()->boxOffsetY() +
- (line ? line->top : 0);
- int lineHeight = line ? line->boxAscent + line->boxDescent : 0;
-
- containingBox->handleFloatInContainer(word->content.widget, misc::max(lines->size() - 1, 0), y, lastLineWidth, lineHeight);
- }
-
-
-
- if (lines->size () == 0) {
- //DBG_MSG (page, "wrap", 0, "first line");
- newLine = true;
- newPar = true;
- lastLine = NULL;
- } else {
- Word *prevWord = words->getRef (wordIndex - 1);
-
- lastLine = lines->getRef (lines->size () - 1);
-
- if (prevWord->content.type == core::Content::BREAK) {
- //DBG_MSG (page, "wrap", 0, "after a break");
- /* previous word is a break */
- newLine = true;
- newPar = true;
- } else if (word->style->whiteSpace == core::style::WHITE_SPACE_NOWRAP ||
- word->style->whiteSpace == core::style::WHITE_SPACE_PRE) {
- //DBG_MSGF (page, "wrap", 0, "no wrap (white_space = %d)",
- // word->style->white_space);
- newLine = false;
- newPar = false;
- } else if (lastLine->firstWord != wordIndex) {
- /* Does new word fit into the last line? */
- //DBG_MSGF (page, "wrap", 0,
- // "word %d (%s) fits? (%d + %d + %d &lt;= %d)...",
- // word_ind, a_Dw_content_html (&word->content),
- // page->lastLine_width, prevWord->orig_space,
- // word->size.width, availWidth);
- newLine = lastLineWidth + prevWord->origSpace + word->size.width >
- availWidth - (lastLine->boxLeft + lastLine->boxRight);
- //DBG_MSGF (page, "wrap", 0, "... %s.",
- // newLine ? "No" : "Yes");
- }
- }
-
- if (newLine) {
- if (word->style->textAlign == core::style::TEXT_ALIGN_JUSTIFY &&
- lastLine != NULL && !newPar) {
- justifyLine (lastLine, availWidth);
- }
- lastLine = addLine (wordIndex, newPar);
- }
-
- lastLine->lastWord = wordIndex;
- lastLine->boxAscent = misc::max (lastLine->boxAscent, word->size.ascent);
- lastLine->boxDescent = misc::max (lastLine->boxDescent, word->size.descent);
-
- len = word->style->font->ascent;
- if (word->style->valign == core::style::VALIGN_SUPER)
- len += len / 2;
- lastLine->contentAscent = misc::max (lastLine->contentAscent, len);
-
- len = word->style->font->descent;
- if (word->style->valign == core::style::VALIGN_SUB)
- len += word->style->font->ascent / 3;
- lastLine->contentDescent = misc::max (lastLine->contentDescent, len);
-
- //DBG_OBJ_ARRSET_NUM (page, "lines.%d.ascent", page->num_lines - 1,
- // lastLine->boxAscent);
- //DBG_OBJ_ARRSET_NUM (page, "lines.%d.descent", page->num_lines - 1,
- // lastLine->boxDescent);
-
- if (word->content.type == core::Content::WIDGET) {
- int collapseMarginTop = 0;
-
- lastLine->marginDescent =
- misc::max (lastLine->marginDescent,
- word->size.descent +
- word->content.widget->getStyle()->margin.bottom);
-
- if (lines->size () == 1 &&
- word->content.widget->blockLevel () &&
- getStyle ()->borderWidth.top == 0 &&
- getStyle ()->padding.top == 0) {
- // collapse top margin of parent element with top margin of first child
- // see: http://www.w3.org/TR/CSS21/box.html#collapsing-margins
- collapseMarginTop = getStyle ()->margin.top;
- }
-
- lastLine->boxAscent =
- misc::max (lastLine->boxAscent,
- word->size.ascent,
- word->size.ascent
- + word->content.widget->getStyle()->margin.top
- - collapseMarginTop);
-
- } else {
- lastLine->marginDescent =
- misc::max (lastLine->marginDescent, lastLine->boxDescent);
-
- if (word->content.type == core::Content::BREAK)
- lastLine->breakSpace =
- misc::max (word->content.breakSpace,
- lastLine->marginDescent - lastLine->boxDescent,
- lastLine->breakSpace);
- }
-
- lastSpace = (wordIndex > 0) ? words->getRef(wordIndex - 1)->origSpace : 0;
-
- if (!newLine)
- lastLineWidth += lastSpace;
- if (!newPar) {
- lastLineParMin += lastSpace;
- lastLineParMax += lastSpace;
- }
-
- lastLineWidth += word->size.width;
-
- getWordExtremes (word, &wordExtremes);
- lastLineParMin += wordExtremes.maxWidth; /* Why maxWidth? */
- lastLineParMax += wordExtremes.maxWidth;
-
- if (word->style->whiteSpace == core::style::WHITE_SPACE_NOWRAP ||
- word->style->whiteSpace == core::style::WHITE_SPACE_PRE) {
- lastLine->parMin += wordExtremes.minWidth + lastSpace;
- /* This may also increase the accumulated minimum word width. */
- lastLine->maxWordMin =
- misc::max (lastLine->maxWordMin, lastLine->parMin);
- /* NOTE: Most code relies on that all values of nowrap are equal for all
- * words within one line. */
- } else {
- lastLine->maxWordMin =
- misc::max (lastLine->maxWordMin, wordExtremes.minWidth);
- }
-
- //DBG_OBJ_SET_NUM(page, "lastLine_par_min", page->lastLine_par_min);
- //DBG_OBJ_SET_NUM(page, "lastLine_par_max", page->lastLine_par_max);
- //DBG_OBJ_ARRSET_NUM (page, "lines.%d.par_min", page->num_lines - 1,
- // lastLine->par_min);
- //DBG_OBJ_ARRSET_NUM (page, "lines.%d.par_max", page->num_lines - 1,
- // lastLine->par_max);
- //DBG_OBJ_ARRSET_NUM (page, "lines.%d.max_word_min", page->num_lines - 1,
- // lastLine->max_word_min);
-
- /* Align the line.
- * \todo Use block's style instead once paragraphs become proper blocks.
- */
- if (word->content.type != core::Content::BREAK) {
- switch (word->style->textAlign) {
- case core::style::TEXT_ALIGN_LEFT:
- case core::style::TEXT_ALIGN_JUSTIFY: /* see some lines above */
- case core::style::TEXT_ALIGN_STRING: /* handled elsewhere (in the
- * future) */
- leftOffset = 0;
- break;
- case core::style::TEXT_ALIGN_RIGHT:
- leftOffset = availWidth - lastLineWidth;
- break;
- case core::style::TEXT_ALIGN_CENTER:
- leftOffset = (availWidth - lastLineWidth) / 2;
- break;
- default:
- /* compiler happiness */
- leftOffset = 0;
- }
-
- /* For large lines (images etc), which do not fit into the viewport: */
- if (leftOffset < 0)
- leftOffset = 0;
-
- if (hasListitemValue && lastLine == lines->getRef (0)) {
- /* List item markers are always on the left. */
- lastLine->leftOffset = 0;
- words->getRef(0)->effSpace = words->getRef(0)->origSpace + leftOffset;
- //DBG_OBJ_ARRSET_NUM (page, "words.%d.eff_space", 0,
- // page->words[0].eff_space);
- } else {
- lastLine->leftOffset = leftOffset;
- }
-
- int y =
- allocation.y - containingBox->allocation.y +
- getStyle()->boxOffsetY () + lastLine->top;
- lastLine->boxLeft = calcLeftFloatBorder(y, this);
- lastLine->boxRight = calcRightFloatBorder(y, this);
- }
- mustQueueResize = true;
-
- //DBG_MSG_END (page);
-}
-
/**
* Calculate the size of a widget within the page.
@@ -1254,92 +886,6 @@ void Textblock::calcWidgetSize (core::Widget *widget, core::Requisition *size)
size->descent -= wstyle->margin.bottom;
}
-/**
- * Rewrap the page from the line from which this is necessary.
- * There are basically two times we'll want to do this:
- * either when the viewport is resized, or when the size changes on one
- * of the child widgets.
- */
-void Textblock::rewrap ()
-{
- int i, wordIndex;
- Word *word;
- Line *lastLine;
-
- if (wrapRef == -1)
- /* page does not have to be rewrapped */
- return;
-
- //DBG_MSGF (page, "wrap", 0,
- // "Dw_page_rewrap: page->wrap_ref = %d, in page with %d word(s)",
- // page->wrap_ref, page->num_words);
- //DBG_MSG_START (page);
-
- /* All lines up from page->wrap_ref will be rebuild from the word list,
- * the line list up from this position is rebuild. */
- lines->setSize (wrapRef);
- lastLineWidth = 0;
- //DBG_OBJ_SET_NUM(page, "num_lines", page->num_lines);
- //DBG_OBJ_SET_NUM(page, "lastLine_width", page->lastLine_width);
-
- /* In the word list, start at the last word plus one in the line before. */
- if (wrapRef > 0) {
- /* Note: In this case, Dw_page_real_word_wrap will immediately find
- * the need to rewrap the line, since we start with the last one (plus
- * one). This is also the reason, why page->lastLine_width is set
- * to the length of the line. */
- lastLine = lines->getRef (lines->size () - 1);
-
- lastLineParMin = lastLine->parMin;
- lastLineParMax = lastLine->parMax;
-
- wordIndex = lastLine->lastWord + 1;
- for (i = lastLine->firstWord; i < lastLine->lastWord; i++)
- lastLineWidth += (words->getRef(i)->size.width +
- words->getRef(i)->origSpace);
- lastLineWidth += words->getRef(lastLine->lastWord)->size.width;
- } else {
- lastLineParMin = 0;
- lastLineParMax = 0;
-
- wordIndex = 0;
- }
-
- for (; wordIndex < words->size (); wordIndex++) {
- word = words->getRef (wordIndex);
-
- if (word->content.type == core::Content::WIDGET)
- calcWidgetSize (word->content.widget, &word->size);
- wordWrap (wordIndex);
-
- if (word->content.type == core::Content::WIDGET) {
- // ABC
- word->content.widget->parentRef = 1 | (dw::core::style::FLOAT_NONE << 1) | ((lines->size () - 1) << 3);
- printf("parentRef = %d\n", word->content.widget->parentRef);
- //DBG_OBJ_SET_NUM (word->content.widget, "parent_ref",
- // word->content.widget->parent_ref);
- }
-
- //DEBUG_MSG(DEBUG_REWRAP_LEVEL,
- // "Assigning parent_ref = %d to rewrapped word %d, "
- // "in page with %d word(s)\n",
- // page->num_lines - 1, wordIndex, page->num_words);
-
- /* todo_refactoring:
- if (word->content.type == DW_CONTENT_ANCHOR)
- p_Dw_gtk_viewport_change_anchor
- (widget, word->content.anchor,
- Dw_page_line_total_y_offset (page,
- &page->lines[page->num_lines - 1]));
- */
- }
-
- /* Next time, the page will not have to be rewrapped. */
- wrapRef = -1;
-
- //DBG_MSG_END (page);
-}
-
/*
* Draw the decorations on a word.
*/
@@ -1366,14 +912,115 @@ void Textblock::decorateText(core::View *view, core::style::Style *style,
}
/*
- * Draw a word of text.
+ * Draw a string of text
*/
-void Textblock::drawText(int wordIndex, core::View *view,core::Rectangle *area,
- int xWidget, int yWidgetBase)
+void Textblock::drawText(core::View *view, core::style::Style *style,
+ core::style::Color::Shading shading, int x, int y,
+ const char *text, int start, int len)
+{
+ if (len > 0) {
+ char *str = NULL;
+
+ switch (style->textTransform) {
+ case core::style::TEXT_TRANSFORM_NONE:
+ default:
+ break;
+ case core::style::TEXT_TRANSFORM_UPPERCASE:
+ str = layout->textToUpper(text + start, len);
+ break;
+ case core::style::TEXT_TRANSFORM_LOWERCASE:
+ str = layout->textToLower(text + start, len);
+ break;
+ case core::style::TEXT_TRANSFORM_CAPITALIZE:
+ {
+ /* \bug No way to know about non-ASCII punctuation. */
+ bool initial_seen = false;
+
+ for (int i = 0; i < start; i++)
+ if (!ispunct(text[i]))
+ initial_seen = true;
+ if (initial_seen)
+ break;
+
+ int after = 0;
+ text += start;
+ while (ispunct(text[after]))
+ after++;
+ if (text[after])
+ after = layout->nextGlyph(text, after);
+ if (after > len)
+ after = len;
+
+ char *initial = layout->textToUpper(text, after);
+ int newlen = strlen(initial) + len-after;
+ str = (char *)malloc(newlen + 1);
+ strcpy(str, initial);
+ strncpy(str + strlen(str), text+after, len-after);
+ str[newlen] = '\0';
+ free(initial);
+ break;
+ }
+ }
+ view->drawText(style->font, style->color, shading, x, y,
+ str ? str : text + start, str ? strlen(str) : len);
+ if (str)
+ free(str);
+ }
+}
+
+/*
+ * Draw a word of text. TODO New description;
+ */
+void Textblock::drawWord (Line *line, int wordIndex1, int wordIndex2,
+ core::View *view, core::Rectangle *area,
+ int xWidget, int yWidgetBase)
+{
+ core::style::Style *style = words->getRef(wordIndex1)->style;
+ bool drawHyphen = wordIndex2 == line->lastWord
+ && words->getRef(wordIndex2)->hyphenWidth > 0;
+
+ if (wordIndex1 == wordIndex2 && !drawHyphen) {
+ // Simple case, where copying in one buffer is not needed.
+ Word *word = words->getRef (wordIndex1);
+ drawWord0 (wordIndex1, wordIndex2, word->content.text, word->size.width,
+ style, view, area, xWidget, yWidgetBase);
+ } else {
+ // Concaternate all words in a new buffer.
+ int l = 0, totalWidth = 0;
+ for (int i = wordIndex1; i <= wordIndex2; i++) {
+ Word *w = words->getRef (i);
+ l += strlen (w->content.text);
+ totalWidth += w->size.width;
+ }
+
+ char text[l + (drawHyphen ? 2 : 0) + 1];
+ int p = 0;
+ for (int i = wordIndex1; i <= wordIndex2; i++) {
+ const char * t = words->getRef(i)->content.text;
+ strcpy (text + p, t);
+ p += strlen (t);
+ }
+
+ if(drawHyphen) {
+ text[p++] = 0xc2;
+ text[p++] = 0xad;
+ text[p++] = 0;
+ }
+
+ drawWord0 (wordIndex1, wordIndex2, text, totalWidth,
+ style, view, area, xWidget, yWidgetBase);
+ }
+}
+
+/**
+ * TODO Comment
+ */
+void Textblock::drawWord0 (int wordIndex1, int wordIndex2,
+ const char *text, int totalWidth,
+ core::style::Style *style, core::View *view,
+ core::Rectangle *area, int xWidget, int yWidgetBase)
{
- Word *word = words->getRef(wordIndex);
int xWorld = allocation.x + xWidget;
- core::style::Style *style = word->style;
int yWorldBase;
/* Adjust the text baseline if the word is <SUP>-ed or <SUB>-ed. */
@@ -1384,38 +1031,55 @@ void Textblock::drawText(int wordIndex, core::View *view,core::Rectangle *area,
}
yWorldBase = yWidgetBase + allocation.y;
- view->drawText (style->font, style->color,
- core::style::Color::SHADING_NORMAL, xWorld, yWorldBase,
- word->content.text, strlen (word->content.text));
+ drawText (view, style, core::style::Color::SHADING_NORMAL, xWorld,
+ yWorldBase, text, 0, strlen (text));
if (style->textDecoration)
decorateText(view, style, core::style::Color::SHADING_NORMAL, xWorld,
- yWorldBase, word->size.width);
+ yWorldBase, totalWidth);
for (int layer = 0; layer < core::HIGHLIGHT_NUM_LAYERS; layer++) {
- if (hlStart[layer].index <= wordIndex &&
- hlEnd[layer].index >= wordIndex) {
- const int wordLen = strlen (word->content.text);
+ if (wordIndex1 <= hlEnd[layer].index &&
+ wordIndex2 >= hlStart[layer].index) {
+ const int wordLen = strlen (text);
int xStart, width;
- int firstCharIdx = 0;
- int lastCharIdx = wordLen;
-
- if (wordIndex == hlStart[layer].index)
- firstCharIdx = misc::min (hlStart[layer].nChar, wordLen);
+ int firstCharIdx;
+ int lastCharIdx;
+
+ if (hlStart[layer].index < wordIndex1)
+ firstCharIdx = 0;
+ else {
+ firstCharIdx =
+ misc::min (hlStart[layer].nChar,
+ (int)strlen (words->getRef(hlStart[layer].index)
+ ->content.text));
+ for (int i = wordIndex1; i < hlStart[layer].index; i++)
+ // It can be assumed that all words from wordIndex1 to
+ // wordIndex2 have content type TEXT.
+ firstCharIdx += strlen (words->getRef(i)->content.text);
+ }
- if (wordIndex == hlEnd[layer].index)
- lastCharIdx = misc::min (hlEnd[layer].nChar, wordLen);
+ if (hlEnd[layer].index > wordIndex2)
+ lastCharIdx = wordLen;
+ else {
+ lastCharIdx =
+ misc::min (hlEnd[layer].nChar,
+ (int)strlen (words->getRef(hlEnd[layer].index)
+ ->content.text));
+ for (int i = wordIndex1; i < hlEnd[layer].index; i++)
+ // It can be assumed that all words from wordIndex1 to
+ // wordIndex2 have content type TEXT.
+ lastCharIdx += strlen (words->getRef(i)->content.text);
+ }
xStart = xWorld;
if (firstCharIdx)
- xStart += layout->textWidth (style->font, word->content.text,
- firstCharIdx);
+ xStart += textWidth (text, 0, firstCharIdx, style);
if (firstCharIdx == 0 && lastCharIdx == wordLen)
- width = word->size.width;
+ width = totalWidth;
else
- width = layout->textWidth (style->font,
- word->content.text + firstCharIdx,
- lastCharIdx - firstCharIdx);
+ width = textWidth (text, firstCharIdx,
+ lastCharIdx - firstCharIdx, style);
if (width > 0) {
/* Highlight text */
core::style::Color *wordBgColor;
@@ -1430,10 +1094,9 @@ void Textblock::drawText(int wordIndex, core::View *view,core::Rectangle *area,
style->font->ascent + style->font->descent);
/* Highlight the text. */
- view->drawText (style->font, style->color,
- core::style::Color::SHADING_INVERSE, xStart,
- yWorldBase, word->content.text + firstCharIdx,
- lastCharIdx - firstCharIdx);
+ drawText (view, style, core::style::Color::SHADING_INVERSE, xStart,
+ yWorldBase, text, firstCharIdx,
+ lastCharIdx - firstCharIdx);
if (style->textDecoration)
decorateText(view, style, core::style::Color::SHADING_INVERSE,
@@ -1501,18 +1164,11 @@ void Textblock::drawLine (Line *line, core::View *view, core::Rectangle *area)
int xWidget = lineXOffsetWidget(line);
int yWidgetBase = lineYOffsetWidget (line) + line->boxAscent;
- /* Here's an idea on how to optimize this routine to minimize the number
- * of drawing calls:
- *
- * Copy the text from the words into a buffer, adding a new word
- * only if: the attributes match, and the spacing is either zero or
- * equal to the width of ' '. In the latter case, copy a " " into
- * the buffer. Then draw the buffer. */
-
for (int wordIndex = line->firstWord;
wordIndex <= line->lastWord && xWidget < area->x + area->width;
wordIndex++) {
Word *word = words->getRef(wordIndex);
+ int wordSize = word->size.width;
if (xWidget + word->size.width + word->effSpace >= area->x) {
if (word->content.type == core::Content::TEXT ||
@@ -1526,12 +1182,26 @@ void Textblock::drawLine (Line *line, core::View *view, core::Rectangle *area)
if (child->intersects (area, &childArea))
child->draw (view, &childArea);
} else {
+ /* TODO: include in drawWord:
if (word->style->hasBackground ()) {
drawBox (view, word->style, area, xWidget,
yWidgetBase - line->boxAscent, word->size.width,
line->boxAscent + line->boxDescent, false);
- }
- drawText(wordIndex, view, area, xWidget, yWidgetBase);
+ }*/
+ int wordIndex2 = wordIndex;
+ while (wordIndex2 < line->lastWord &&
+ words->getRef(wordIndex2)->hyphenWidth > 0 &&
+ word->style == words->getRef(wordIndex2 + 1)->style)
+ wordIndex2++;
+
+ drawWord(line, wordIndex, wordIndex2, view, area,
+ xWidget, yWidgetBase);
+ wordSize = 0;
+ for (int i = wordIndex; i <= wordIndex2; i++)
+ wordSize += words->getRef(i)->size.width;
+
+ wordIndex = wordIndex2;
+ word = words->getRef(wordIndex);
}
}
if (word->effSpace > 0 && wordIndex < line->lastWord &&
@@ -1539,16 +1209,16 @@ void Textblock::drawLine (Line *line, core::View *view, core::Rectangle *area)
core::Content::BREAK) {
if (word->spaceStyle->hasBackground ())
drawBox (view, word->spaceStyle, area,
- xWidget + word->size.width,
+ xWidget + wordSize,
yWidgetBase - line->boxAscent, word->effSpace,
line->boxAscent + line->boxDescent, false);
- drawSpace(wordIndex, view, area, xWidget + word->size.width,
+ drawSpace(wordIndex, view, area, xWidget + wordSize,
yWidgetBase);
}
}
}
- xWidget += word->size.width + word->effSpace;
+ xWidget += wordSize + word->effSpace;
}
}
@@ -1592,6 +1262,7 @@ int Textblock::findLineOfWord (int wordIndex)
{
int high = lines->size () - 1, index, low = 0;
+ // TODO regard also not-yet-existing lines?
if (wordIndex < 0 || wordIndex >= words->size ())
return -1;
@@ -1631,11 +1302,22 @@ Textblock::Word *Textblock::findWord (int x, int y, bool *inSpace)
word = words->getRef (wordIndex);
lastXCursor = xCursor;
xCursor += word->size.width + word->effSpace;
- if (lastXCursor <= x && xCursor > x &&
- y > yWidgetBase - word->size.ascent &&
- y <= yWidgetBase + word->size.descent) {
- *inSpace = x >= xCursor - word->effSpace;
- return word;
+ if (lastXCursor <= x && xCursor > x) {
+ if (x >= xCursor - word->effSpace) {
+ if (wordIndex < line->lastWord &&
+ (words->getRef(wordIndex + 1)->content.type !=
+ core::Content::BREAK) &&
+ y > yWidgetBase - word->spaceStyle->font->ascent &&
+ y <= yWidgetBase + word->spaceStyle->font->descent) {
+ *inSpace = true;
+ return word;
+ }
+ } else {
+ if (y > yWidgetBase - word->size.ascent &&
+ y <= yWidgetBase + word->size.descent)
+ return word;
+ }
+ break;
}
}
@@ -1644,6 +1326,9 @@ Textblock::Word *Textblock::findWord (int x, int y, bool *inSpace)
void Textblock::draw (core::View *view, core::Rectangle *area)
{
+ PRINTF ("DRAW: %d, %d, %d x %d\n",
+ area->x, area->y, area->width, area->height);
+
int lineIndex;
Line *line;
@@ -1669,39 +1354,89 @@ 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;
- word->origSpace = 0;
- word->effSpace = 0;
+ word->origSpace = word->effSpace = word->stretchability =
+ word->shrinkability = 0;
+ word->hyphenWidth = 0;
+ word->badnessAndPenalty.setPenaltyProhibitBreak ();
word->content.space = false;
-
- //DBG_OBJ_ARRSET_NUM (page, "words.%d.size.width", page->num_words - 1,
- // word->size.width);
- //DBG_OBJ_ARRSET_NUM (page, "words.%d.size.descent", page->num_words - 1,
- // word->size.descent);
- //DBG_OBJ_ARRSET_NUM (page, "words.%d.size.ascent", page->num_words - 1,
- // word->size.ascent);
- //DBG_OBJ_ARRSET_NUM (page, "words.%d.orig_space", page->num_words - 1,
- // word->orig_space);
- //DBG_OBJ_ARRSET_NUM (page, "words.%d.eff_space", page->num_words - 1,
- // word->eff_space);
- //DBG_OBJ_ARRSET_NUM (page, "words.%d.content.space", page->num_words - 1,
- // word->content.space);
+ word->canBeHyphenated = canBeHyphenated;
word->style = style;
word->spaceStyle = style;
style->ref ();
style->ref ();
+}
- return word;
+/*
+ * Get the width of a string of text.
+ */
+int Textblock::textWidth(const char *text, int start, int len,
+ core::style::Style *style)
+{
+ int ret = 0;
+
+ if (len > 0) {
+ char *str = NULL;
+
+ switch (style->textTransform) {
+ case core::style::TEXT_TRANSFORM_NONE:
+ default:
+ ret = layout->textWidth(style->font, text+start, len);
+ break;
+ case core::style::TEXT_TRANSFORM_UPPERCASE:
+ str = layout->textToUpper(text+start, len);
+ ret = layout->textWidth(style->font, str, strlen(str));
+ break;
+ case core::style::TEXT_TRANSFORM_LOWERCASE:
+ str = layout->textToLower(text+start, len);
+ ret = layout->textWidth(style->font, str, strlen(str));
+ break;
+ case core::style::TEXT_TRANSFORM_CAPITALIZE:
+ {
+ /* \bug No way to know about non-ASCII punctuation. */
+ bool initial_seen = false;
+
+ for (int i = 0; i < start; i++)
+ if (!ispunct(text[i]))
+ initial_seen = true;
+ if (initial_seen) {
+ ret = layout->textWidth(style->font, text+start, len);
+ } else {
+ int after = 0;
+
+ text += start;
+ while (ispunct(text[after]))
+ after++;
+ if (text[after])
+ after = layout->nextGlyph(text, after);
+ if (after > len)
+ after = len;
+ str = layout->textToUpper(text, after);
+ ret = layout->textWidth(style->font, str, strlen(str)) +
+ layout->textWidth(style->font, text+after, len-after);
+ }
+ break;
+ }
+ }
+ if (str)
+ free(str);
+ }
+ return ret;
}
/**
@@ -1711,7 +1446,7 @@ void Textblock::calcTextSize (const char *text, size_t len,
core::style::Style *style,
core::Requisition *size)
{
- size->width = layout->textWidth (style->font, text, len);
+ size->width = textWidth (text, 0, len, style);
size->ascent = style->font->ascent;
size->descent = style->font->descent;
@@ -1755,25 +1490,129 @@ void Textblock::calcTextSize (const char *text, size_t len,
size->ascent += (style->font->ascent / 2);
}
-
/**
- * Add a word to the page structure.
+ * Add a word to the page structure. If it contains soft hyphens, it is
+ * divided.
*/
void Textblock::addText (const char *text, size_t len,
core::style::Style *style)
{
- Word *word;
- core::Requisition size;
+ PRINTF ("[%p] ADD_TEXT (%d characters)\n", this, (int)len);
+
+ // Count hyphens.
+ int numHyphens = 0;
+ for (int i = 0; i < (int)len - 1; i++)
+ // (0xc2, 0xad) is the UTF-8 representation of a soft hyphen (Unicode
+ // 0xc2).
+ if((unsigned char)text[i] == 0xc2 && (unsigned char)text[i + 1] == 0xad)
+ numHyphens++;
+
+ if (numHyphens == 0) {
+ // Simple (and often) case: no soft hyphens. May still be hyphenated
+ // automatically.
+ core::Requisition size;
+ calcTextSize (text, len, style, &size);
+ addText0 (text, len, true, style, &size);
+ } else {
+ PRINTF("HYPHENATION: '");
+ for (size_t i = 0; i < len; i++)
+ PUTCHAR(text[i]);
+ PRINTF("', with %d hyphen(s)\n", numHyphens);
+
+ // Store hyphen positions.
+ int n = 0, hyphenPos[numHyphens], breakPos[numHyphens];
+ for (size_t i = 0; i < len - 1; i++)
+ if((unsigned char)text[i] == 0xc2 &&
+ (unsigned char)text[i + 1] == 0xad) {
+ hyphenPos[n] = i;
+ breakPos[n] = i - 2 * n;
+ n++;
+ }
+
+ // Get text without hyphens. (There are numHyphens + 1 parts in the word,
+ // and 2 * numHyphens bytes less, 2 for each hyphen, are needed.)
+ char textWithoutHyphens[len - 2 * numHyphens];
+ int start = 0; // related to "text"
+ for (int i = 0; i < numHyphens + 1; i++) {
+ int end = (i == numHyphens) ? len : hyphenPos[i];
+ memmove (textWithoutHyphens + start - 2 * i, text + start,
+ end - start);
+ start = end + 2;
+ }
- calcTextSize (text, len, style, &size);
- word = addWord (size.width, size.ascent, size.descent, style);
+ PRINTF("H... without hyphens: '");
+ for (size_t i = 0; i < len - 2 * numHyphens; i++)
+ PUTCHAR(textWithoutHyphens[i]);
+ PRINTF("'\n");
+
+ core::Requisition wordSize[numHyphens + 1];
+ calcTextSizes (textWithoutHyphens, len - 2 * numHyphens, style,
+ numHyphens, breakPos, wordSize);
+
+ // Finished!
+ for (int i = 0; i < numHyphens + 1; i++) {
+ int start = (i == 0) ? 0 : hyphenPos[i - 1] + 2;
+ int end = (i == numHyphens) ? len : hyphenPos[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++)
+ PUTCHAR(text[j]);
+ PRINTF("' added\n");
+
+ if(i < numHyphens) {
+ addHyphen ();
+ PRINTF("H... yphen added\n");
+ }
+ }
+ }
+}
+
+void Textblock::calcTextSizes (const char *text, size_t textLen,
+ core::style::Style *style,
+ int numBreaks, int *breakPos,
+ core::Requisition *wordSize)
+{
+ // The size of the last part is calculated in a simple way.
+ int lastStart = breakPos[numBreaks - 1];
+ calcTextSize (text + lastStart, textLen - lastStart, style,
+ &wordSize[numBreaks]);
+
+ PRINTF("H... [%d] '", numBreaks);
+ for (size_t i = 0; i < textLen - lastStart; i++)
+ PUTCHAR(text[i + lastStart]);
+ PRINTF("' -> %d\n", wordSize[numBreaks].width);
+
+ // The rest is more complicated. TODO Documentation.
+ for (int i = numBreaks - 1; i >= 0; i--) {
+ int start = (i == 0) ? 0 : breakPos[i - 1];
+ calcTextSize (text + start, textLen - start, style, &wordSize[i]);
+
+ PRINTF("H... [%d] '", i);
+ for (size_t j = 0; j < textLen - start; j++)
+ PUTCHAR(text[j + start]);
+ PRINTF("' -> %d\n", wordSize[i].width);
+
+ for (int j = i + 1; j < numBreaks + 1; j++) {
+ wordSize[i].width -= wordSize[j].width;
+ PRINTF("H... - %d = %d\n", wordSize[j].width, wordSize[i].width);
+ }
+ }
+}
+
+/**
+ * Add a word (without hyphens) to the page structure.
+ */
+void Textblock::addText0 (const char *text, size_t len, bool canBeHyphenated,
+ core::style::Style *style, core::Requisition *size)
+{
+ 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", page->num_words - 1,
- // word->content.text);
-
- wordWrap (words->size () - 1);
+ wordWrap (words->size () - 1, false);
}
/**
@@ -1790,19 +1629,21 @@ void Textblock::addWidget (core::Widget *widget, core::style::Style *style)
* end of this function, the correct value is assigned. */
widget->parentRef = -1;
+ PRINTF ("%p becomes child of %p\n", widget, this);
+
widget->setParent (this);
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;
- //DBG_OBJ_ARRSET_PTR (page, "words.%d.content.widget", page->num_words - 1,
+ //DBG_OBJ_ARRSET_PTR (page, "words.%d.content.widget", words->size() - 1,
// word->content.widget);
- wordWrap (words->size () - 1);
+ wordWrap (words->size () - 1, false);
// ABC
word->content.widget->parentRef = 1 | (dw::core::style::FLOAT_NONE << 1) | ((lines->size () - 1) << 3);
printf("parentRef = %d\n", word->content.widget->parentRef);
@@ -1812,10 +1653,9 @@ void Textblock::addWidget (core::Widget *widget, core::style::Style *style)
//DEBUG_MSG(DEBUG_REWRAP_LEVEL,
// "Assigning parent_ref = %d to added word %d, "
// "in page with %d word(s)\n",
- // page->num_lines - 1, page->num_words - 1, page->num_words);
+ // lines->size () - 1, words->size() - 1, words->size());
}
-
/**
* Add an anchor to the page. "name" is copied, so no strdup is necessary for
* the caller.
@@ -1863,29 +1703,84 @@ bool Textblock::addAnchor (const char *name, core::style::Style *style)
void Textblock::addSpace (core::style::Style *style)
{
int wordIndex = words->size () - 1;
+ if (wordIndex >= 0) {
+ fillSpace (words->getRef(wordIndex), style);
+ accumulateWordData (wordIndex);
+ }
+}
+
+void Textblock::fillSpace (Word *word, core::style::Style *style)
+{
+ // Old comment:
+ //
+ // According to
+ // http://www.w3.org/TR/CSS2/text.html#white-space-model: "line
+ // breaking opportunities are determined based on the text
+ // prior to the white space collapsing steps".
+ //
+ // So we call addBreakOption () for each Textblock::addSpace ()
+ // call. This is important e.g. to be able to break between
+ // foo and bar in: <span style="white-space:nowrap">foo </span>
+ // bar
+ //
+ // TODO: Re-evaluate again.
+
+ // TODO: This line does not work: addBreakOption (word, style);
+
+ if (!word->content.space) {
+ // Do not override a previously set break penalty.
+ if (!word->badnessAndPenalty.lineMustBeBroken()) {
+ switch (style->whiteSpace) {
+ case core::style::WHITE_SPACE_NORMAL:
+ case core::style::WHITE_SPACE_PRE_LINE:
+ word->badnessAndPenalty.setPenalty (0);
+ break;
+
+ case core::style::WHITE_SPACE_PRE:
+ case core::style::WHITE_SPACE_NOWRAP:
+ case core::style::WHITE_SPACE_PRE_WRAP:
+ word->badnessAndPenalty.setPenaltyProhibitBreak ();
+ break;
+ }
+ }
+
+ word->content.space = true;
+ word->effSpace = word->origSpace = style->font->spaceWidth +
+ style->wordSpacing;
+ word->stretchability = word->origSpace / 2;
+ if(style->textAlign == core::style::TEXT_ALIGN_JUSTIFY)
+ word->shrinkability = word->origSpace / 3;
+ else
+ word->shrinkability = 0;
+
+ //DBG_OBJ_ARRSET_NUM (this, "words.%d.origSpace", wordIndex,
+ // word->origSpace);
+ //DBG_OBJ_ARRSET_NUM (this, "words.%d.effSpace", wordIndex,
+ // word->effSpace);
+ //DBG_OBJ_ARRSET_NUM (this, "words.%d.content.space", wordIndex,
+ // word->content.space);
+
+ word->spaceStyle->unref ();
+ word->spaceStyle = style;
+ style->ref ();
+ }
+}
+
+void Textblock::addHyphen ()
+{
+ int wordIndex = words->size () - 1;
if (wordIndex >= 0) {
Word *word = words->getRef(wordIndex);
+
+ word->badnessAndPenalty.setPenalty (HYPHEN_BREAK);
+ // TODO Optimize? Like spaces?
+ word->hyphenWidth = layout->textWidth (word->style->font, "\xc2\xad", 2);
- if (!word->content.space) {
- word->content.space = true;
- word->effSpace = word->origSpace = style->font->spaceWidth +
- style->wordSpacing;
-
- //DBG_OBJ_ARRSET_NUM (page, "words.%d.orig_space", nw,
- // page->words[nw].orig_space);
- //DBG_OBJ_ARRSET_NUM (page, "words.%d.eff_space", nw,
- // page->words[nw].eff_space);
- //DBG_OBJ_ARRSET_NUM (page, "words.%d.content.space", nw,
- // page->words[nw].content.space);
- word->spaceStyle->unref ();
- word->spaceStyle = style;
- style->ref ();
- }
+ accumulateWordData (wordIndex);
}
}
-
/**
* Cause a paragraph break
*/
@@ -1959,10 +1854,11 @@ 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;
- wordWrap (words->size () - 1);
+ wordWrap (words->size () - 1, false);
}
/*
@@ -1976,14 +1872,16 @@ 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 ();
word->content.breakSpace = 0;
- wordWrap (words->size () - 1);
+ wordWrap (words->size () - 1, false);
}
/** \todo This MUST be commented! */
@@ -1994,12 +1892,12 @@ void Textblock::addFloatIntoGenerator (core::Widget *widget, core::style::Style
widget->setStyle (style);
containingBox->addFloatIntoContainer(widget, this);
- word = addWord (0, 0, 0, style);
+ word = addWord (0, 0, 0, false, style);
word->content.type = core::Content::FLOAT_REF;
word->content.breakSpace = 0;
word->content.widget = widget;
word->style = style;
- wordWrap (words->size () - 1);
+ wordWrap (words->size () - 1, false);
}
@@ -2065,9 +1963,9 @@ void Textblock::handOverBreak (core::style::Style *style)
}
/*
- * Any words added by a_Dw_page_add_... are not immediately (queued to
+ * Any words added by addWord() are not immediately (queued to
* be) drawn, instead, this function must be called. This saves some
- * calls to p_Dw_widget_queue_resize.
+ * calls to queueResize().
*
*/
void Textblock::flush ()
@@ -2077,9 +1975,11 @@ void Textblock::flush ()
// printf("queueResize(%s, -1, true)\n", asap ? "true" : "false");
// queueResize (asap, -1, true);
//=======
+ PRINTF ("[%p] FLUSH => %s (parentRef = %d)\n",
+ this, mustQueueResize ? "true" : "false", parentRef);
+
if (mustQueueResize) {
queueResize (-1, true);
-//>>>>>>> 1.24
mustQueueResize = false;
}
}
@@ -2522,9 +2422,8 @@ void Textblock::TextblockIterator::getAllocation (int start, int end,
allocation->x += w->size.width + w->effSpace;
}
if (start > 0 && word->content.type == core::Content::TEXT) {
- allocation->x += textblock->layout->textWidth (word->style->font,
- word->content.text,
- start);
+ allocation->x += textblock->textWidth (word->content.text, 0, start,
+ word->style);
}
allocation->y = textblock->lineYOffsetCanvas (line) + line->boxAscent -
word->size.ascent;
@@ -2536,9 +2435,8 @@ void Textblock::TextblockIterator::getAllocation (int start, int end,
if (start > 0 || end < wordEnd) {
end = misc::min(end, wordEnd); /* end could be INT_MAX */
allocation->width =
- textblock->layout->textWidth (word->style->font,
- word->content.text + start,
- end - start);
+ textblock->textWidth (word->content.text, start, end - start,
+ word->style);
}
}
allocation->ascent = word->size.ascent;