diff options
author | Sebastian Geerken <devnull@localhost> | 2014-09-01 00:30:01 +0200 |
---|---|---|
committer | Sebastian Geerken <devnull@localhost> | 2014-09-01 00:30:01 +0200 |
commit | a2cf34555c64fa87bd146071cf46bd381c695761 (patch) | |
tree | a49d40dd73dd486d0f0111e28dd7a7189ed60970 /dw/textblock.cc | |
parent | 9430132423d99689de9c02db79df60fd1b4a5703 (diff) |
Many changes: split up OutOfFlowMgr for floats, and absolutely and fixedly positioned elements; also with different containing blocks.
Diffstat (limited to 'dw/textblock.cc')
-rw-r--r-- | dw/textblock.cc | 356 |
1 files changed, 215 insertions, 141 deletions
diff --git a/dw/textblock.cc b/dw/textblock.cc index bfa59502..caf4b558 100644 --- a/dw/textblock.cc +++ b/dw/textblock.cc @@ -19,6 +19,9 @@ #include "textblock.hh" +#include "ooffloatsmgr.hh" +#include "oofposabsmgr.hh" +#include "oofposfixedmgr.hh" #include "../lout/msg.h" #include "../lout/misc.hh" #include "../lout/unicode.hh" @@ -227,7 +230,11 @@ Textblock::Textblock (bool limitTextWidth) registerName ("dw::Textblock", &CLASS_ID); setButtonSensitive(true); - containingBlock = NULL; + for (int i = 0; i < NUM_OOFM; i++) { + containingBlock[i] = NULL; + outOfFlowMgr[i] = NULL; + } + hasListitemValue = false; leftInnerPadding = 0; line1Offset = 0; @@ -252,7 +259,6 @@ Textblock::Textblock (bool limitTextWidth) nonTemporaryLines = 0; words = new misc::NotSoSimpleVector <Word> (1); anchors = new misc::SimpleVector <Anchor> (1); - outOfFlowMgr = NULL; wrapRefLines = wrapRefParagraphs = -1; @@ -304,14 +310,16 @@ Textblock::~Textblock () delete words; delete anchors; - if(outOfFlowMgr) { - // I feel more comfortable by letting the textblock delete these - // widgets, instead of doing this in ~OutOfFlowMgr. - - for (int i = 0; i < outOfFlowMgr->getNumWidgets (); i++) - delete outOfFlowMgr->getWidget (i); - - delete outOfFlowMgr; + for (int i = 0; i < NUM_OOFM; i++) { + if(outOfFlowMgr[i]) { + // I feel more comfortable by letting the textblock delete these + // widgets, instead of doing this in ~OutOfFlowMgr. + + for (int j = 0; j < outOfFlowMgr[i]->getNumWidgets (); j++) + delete outOfFlowMgr[i]->getWidget (j); + + delete outOfFlowMgr[i]; + } } /* Make sure we don't own widgets anymore. Necessary before call of @@ -406,24 +414,28 @@ void Textblock::sizeRequestImpl (core::Requisition *requisition) // Is this really what we want? An alternative could be that // OutOfFlowMgr::getSize honours CSS attributes an corrected sizes. - DBG_OBJ_MSGF ("resize", 1, "before considering OOF widgets: %d * (%d + %d)", - requisition->width, requisition->ascent, requisition->descent); - - if (outOfFlowMgr) { - int oofWidth, oofHeight; - outOfFlowMgr->getSize (requisition, &oofWidth, &oofHeight); - - // Floats must be within the *content* area, not the *margin* - // area (which is equivalent to the requisition / - // allocation). For this reason, boxRestWidth() and - // boxRestHeight() must be considered. - - if (oofWidth + boxRestWidth () > requisition->width) - requisition->width = oofWidth + boxRestWidth (); - if (oofHeight + boxRestHeight () - > requisition->ascent + requisition->descent) - requisition->descent = - oofHeight + boxRestHeight () - requisition->ascent; + for (int i = 0; i < NUM_OOFM; i++) { + if (outOfFlowMgr[i]) { + int oofWidth, oofHeight; + DBG_OBJ_MSGF ("resize", 1, + "before considering widgets by OOFM #%d: %d * (%d + %d)", + i, requisition->width, requisition->ascent, + requisition->descent); + + outOfFlowMgr[i]->getSize (requisition, &oofWidth, &oofHeight); + + // Widgets OOF must be within the *content* area, not the + // *margin* area (which is equivalent to the requisition / + // allocation). For this reason, boxRestWidth() and + // boxRestHeight() must be considered. + + if (oofWidth + boxRestWidth () > requisition->width) + requisition->width = oofWidth + boxRestWidth (); + if (oofHeight + boxRestHeight () + > requisition->ascent + requisition->descent) + requisition->descent = + oofHeight + boxRestHeight () - requisition->ascent; + } } DBG_OBJ_MSGF ("resize", 1, "final: %d * (%d + %d)", @@ -505,19 +517,21 @@ void Textblock::getExtremesImpl (core::Extremes *extremes) extremes->minWidth, extremes->minWidthIntrinsic, extremes->maxWidth, extremes->maxWidthIntrinsic); - if (outOfFlowMgr) { - int oofMinWidth, oofMaxWidth; - outOfFlowMgr->getExtremes (extremes, &oofMinWidth, &oofMaxWidth); - - DBG_OBJ_MSGF ("resize", 1, "OOFM correction: %d / %d", - oofMinWidth, oofMaxWidth); - - extremes->minWidth = misc::max (extremes->minWidth, oofMinWidth); - extremes->minWidthIntrinsic = - misc::max (extremes->minWidthIntrinsic, oofMinWidth); - extremes->maxWidth = misc::max (extremes->maxWidth, oofMaxWidth); - extremes->maxWidthIntrinsic = - misc::max (extremes->maxWidthIntrinsic, oofMinWidth); + for (int i = 0; i < NUM_OOFM; i++) { + if (outOfFlowMgr[i]) { + int oofMinWidth, oofMaxWidth; + outOfFlowMgr[i]->getExtremes (extremes, &oofMinWidth, &oofMaxWidth); + + DBG_OBJ_MSGF ("resize", 1, "OOFM (#%d) correction: %d / %d", + i, oofMinWidth, oofMaxWidth); + + extremes->minWidth = misc::max (extremes->minWidth, oofMinWidth); + extremes->minWidthIntrinsic = + misc::max (extremes->minWidthIntrinsic, oofMinWidth); + extremes->maxWidth = misc::max (extremes->maxWidth, oofMaxWidth); + extremes->maxWidthIntrinsic = + misc::max (extremes->maxWidthIntrinsic, oofMinWidth); + } } DBG_OBJ_MSGF ("resize", 0, @@ -578,8 +592,10 @@ void Textblock::sizeAllocateImpl (core::Allocation *allocation) DBG_OBJ_SET_NUM ("childBaseAllocation.ascent", childBaseAllocation.ascent); DBG_OBJ_SET_NUM ("childBaseAllocation.descent", childBaseAllocation.descent); - if (containingBlock->outOfFlowMgr) - containingBlock->outOfFlowMgr->sizeAllocateStart (this, allocation); + for (int i = 0; i < NUM_OOFM; i++) + if (containingBlock[i]->outOfFlowMgr[i]) + containingBlock[i]->outOfFlowMgr[i]->sizeAllocateStart (this, + allocation); int lineIndex, wordIndex; Line *line; @@ -707,9 +723,10 @@ void Textblock::sizeAllocateImpl (core::Allocation *allocation) DBG_OBJ_MSG_END (); - if (containingBlock->outOfFlowMgr) - containingBlock->outOfFlowMgr->sizeAllocateEnd (this); - + for (int i = 0; i < NUM_OOFM; i++) + if (containingBlock[i]->outOfFlowMgr[i]) + containingBlock[i]->outOfFlowMgr[i]->sizeAllocateEnd (this); + for (int i = 0; i < anchors->size(); i++) { Anchor *anchor = anchors->getRef(i); int y; @@ -736,8 +753,10 @@ int Textblock::getAvailWidthOfChild (Widget *child, bool forceValue) int width = Widget::getAvailWidthOfChild (child, forceValue); - if (outOfFlowMgr && outOfFlowMgr->dealingWithSizeOfChild (child)) - width = outOfFlowMgr->getAvailWidthOfChild (child, forceValue); + if (isWidgetOOF(child) && getWidgetOutOfFlowMgr(child) && + getWidgetOutOfFlowMgr(child)->dealingWithSizeOfChild (child)) + width = + getWidgetOutOfFlowMgr(child)->getAvailWidthOfChild (child, forceValue); else { if (forceValue && this == child->getContainer () && !mustBeWidenedToAvailWidth ()) { @@ -755,8 +774,10 @@ int Textblock::getAvailWidthOfChild (Widget *child, bool forceValue) int Textblock::getAvailHeightOfChild (core::Widget *child, bool forceValue) { - if (outOfFlowMgr && outOfFlowMgr->dealingWithSizeOfChild (child)) - return outOfFlowMgr->getAvailHeightOfChild (child, forceValue); + if (isWidgetOOF(child) && getWidgetOutOfFlowMgr(child) && + getWidgetOutOfFlowMgr(child)->dealingWithSizeOfChild (child)) + return getWidgetOutOfFlowMgr(child)->getAvailHeightOfChild (child, + forceValue); else return Widget::getAvailHeightOfChild (child, forceValue); } @@ -771,9 +792,10 @@ void Textblock::containerSizeChangedForChildren () word->content.widget->containerSizeChanged (); } - if (outOfFlowMgr) - outOfFlowMgr->containerSizeChangedForChildren (); - + for (int i = 0; i < NUM_OOFM; i++) + if (outOfFlowMgr[i]) + outOfFlowMgr[i]->containerSizeChangedForChildren (); + DBG_OBJ_LEAVE (); } @@ -825,13 +847,10 @@ void Textblock::markSizeChange (int ref) { DBG_OBJ_ENTER ("resize", 0, "markSizeChange", "%d", ref); - if (OutOfFlowMgr::isRefOutOfFlow (ref)) { - assert (outOfFlowMgr != NULL); - outOfFlowMgr->markSizeChange (ref); - } else { - PRINTF ("[%p] MARK_SIZE_CHANGE (%d): %d => ...\n", - this, ref, wrapRefLines); - + if (isParentRefOOF (ref)) + getParentRefOutOfFlowMgr(ref) + ->markSizeChange (getParentRefOOFSubRef (ref)); + else { /* 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 @@ -839,10 +858,9 @@ void Textblock::markSizeChange (int ref) now, but addLine(...) will do everything necessary. */ if (ref != -1) { if (wrapRefLines == -1) - wrapRefLines = OutOfFlowMgr::getLineNoFromRef (ref); + wrapRefLines = getParentRefLineNo (ref); else - wrapRefLines = misc::min (wrapRefLines, - OutOfFlowMgr::getLineNoFromRef (ref)); + wrapRefLines = misc::min (wrapRefLines, getParentRefLineNo (ref)); } DBG_OBJ_SET_NUM ("wrapRefLines", wrapRefLines); @@ -862,13 +880,10 @@ void Textblock::markExtremesChange (int ref) { DBG_OBJ_ENTER ("resize", 1, "markExtremesChange", "%d", ref); - if (OutOfFlowMgr::isRefOutOfFlow (ref)) { - assert (outOfFlowMgr != NULL); - outOfFlowMgr->markExtremesChange (ref); - } else { - PRINTF ("[%p] MARK_EXTREMES_CHANGE (%d): %d => ...\n", - this, ref, wrapRefParagraphs); - + if (isParentRefOOF (ref)) + getParentRefOutOfFlowMgr(ref) + ->markExtremesChange (getParentRefOOFSubRef (ref)); + else { /* 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 @@ -876,11 +891,10 @@ void Textblock::markExtremesChange (int ref) now, but addLine(...) will do everything necessary. */ if (ref != -1) { if (wrapRefParagraphs == -1) - wrapRefParagraphs = OutOfFlowMgr::getLineNoFromRef (ref); + wrapRefParagraphs = getParentRefLineNo (ref); else wrapRefParagraphs = - misc::min (wrapRefParagraphs, - OutOfFlowMgr::getLineNoFromRef (ref)); + misc::min (wrapRefParagraphs, getParentRefLineNo (ref)); } DBG_OBJ_SET_NUM ("wrapRefParagraphs", wrapRefParagraphs); @@ -891,52 +905,79 @@ void Textblock::markExtremesChange (int ref) void Textblock::notifySetAsTopLevel() { - PRINTF ("%p becomes toplevel\n", this); - containingBlock = this; - PRINTF ("-> %p is its own containing block\n", this); -} - -bool Textblock::isContainingBlock (Widget *widget) -{ - return - // Of course, only textblocks are considered as containing - // blocks. - widget->instanceOf (Textblock::CLASS_ID) && - // The second condition: that this block is "out of flow", in a - // wider sense. - (// The toplevel widget is "out of flow", since there is no - // parent, and so no context. - widget->getParent() == NULL || - // A similar reasoning applies to a widget with another parent - // than a textblock (typical example: a table cell (this is - // also a text block) within a table widget). - !widget->getParent()->instanceOf (Textblock::CLASS_ID) || - // Inline blocks are containing blocks, too. - widget->getStyle()->display == core::style::DISPLAY_INLINE_BLOCK || - // Finally, "out of flow" in a narrower sense: floats and - // absolute positions. - OutOfFlowMgr::isWidgetOutOfFlow (widget)); + containingBlock[OOFM_FLOATS] = containingBlock[OOFM_ABSOLUTE] + = containingBlock[OOFM_FIXED] = this; +} + +bool Textblock::isContainingBlock (Widget *widget, int oofmIndex) +{ + switch (oofmIndex) { + case OOFM_FLOATS: + return + // For floats, only textblocks are considered as containing + // blocks. + widget->instanceOf (Textblock::CLASS_ID) && + // The second condition: that this block is "out of flow", in a + // wider sense. + (// The toplevel widget is "out of flow", since there is no + // parent, and so no context. + widget->getParent() == NULL || + // A similar reasoning applies to a widget with another parent + // than a textblock (typical example: a table cell (this is + // also a text block) within a table widget). + !widget->getParent()->instanceOf (Textblock::CLASS_ID) || + // Inline blocks are containing blocks, too. + widget->getStyle()->display == core::style::DISPLAY_INLINE_BLOCK || + // Finally, "out of flow" in a narrower sense: floats; absolutely + // and fixedly positioned elements. + testWidgetOutOfFlow (widget)); + + case OOFM_ABSOLUTE: + // Only the toplevel widget (as for all) as well as absolutely + // and fixedly positioned elements constitute the containing + // block for absolutely positioned elements, but neither floats + // nor other elements like table cells. + // + // We also test whether this widget is a textblock: is this + // necessary? (What about other absolutely widgets containing + // children, like tables? TODO: Check CSS spec.) + + return widget->instanceOf (Textblock::CLASS_ID) && + (widget->getParent() == NULL || + testWidgetAbsolutelyPositioned (widget) || + testWidgetFixedPositioned (widget)); + + case OOFM_FIXED: + // The single container for fixedly positioned elements is the + // toplevel (canvas; actually the viewport). (The toplevel + // widget should always be a textblock; at least this is the + // case in dillo.) + return widget->getParent() == NULL; + + default: + // compiler happiness + lout::misc::assertNotReached (); + return false; + } } void Textblock::notifySetParent () { - PRINTF ("%p becomes a child of %p\n", this, getParent()); + // Search for containing blocks. + for (int oofmIndex = 0; oofmIndex < NUM_OOFM; oofmIndex++) { + containingBlock[oofmIndex] = NULL; - // Search for containing Box. - containingBlock = NULL; - - for (Widget *widget = this; widget != NULL && containingBlock == NULL; - widget = widget->getParent()) - if (isContainingBlock (widget)) { - containingBlock = (Textblock*)widget; - - if (containingBlock == this) { - PRINTF ("-> %p is its own containing block\n", this); - } else { - PRINTF ("-> %p becomes containing block of %p\n", - containingBlock, this); + for (Widget *widget = this; + widget != NULL && containingBlock[oofmIndex] == NULL; + widget = widget->getParent ()) + if (isContainingBlock (widget, oofmIndex)) { + assert (widget->instanceOf (Textblock::CLASS_ID)); + containingBlock[oofmIndex] = (Textblock*)widget; } - } + + DBG_OBJ_ARRSET_PTR ("containingBlock", oofmIndex, + containingBlock[oofmIndex]); + } assert (containingBlock != NULL); } @@ -1763,8 +1804,9 @@ void Textblock::draw (core::View *view, core::Rectangle *area) drawLine (line, view, area); } - if(outOfFlowMgr) - outOfFlowMgr->draw(view, area); + for (int i = 0; i < NUM_OOFM; i++) + if(outOfFlowMgr[i]) + outOfFlowMgr[i]->draw(view, area); DBG_OBJ_LEAVE (); } @@ -2310,6 +2352,31 @@ void Textblock::addText0 (const char *text, size_t len, short flags, DBG_OBJ_LEAVE (); } +void Textblock::initOutOfFlowMgrs () +{ + if (containingBlock[OOFM_FLOATS]->outOfFlowMgr[OOFM_FLOATS] == NULL) { + containingBlock[OOFM_FLOATS]->outOfFlowMgr[OOFM_FLOATS] = + new OOFFloatsMgr (containingBlock[OOFM_FLOATS]); + DBG_OBJ_ASSOC (containingBlock[OOFM_FLOATS], + containingBlock[OOFM_FLOATS]->outOfFlowMgr[OOFM_FLOATS]); + } + + if (containingBlock[OOFM_ABSOLUTE]->outOfFlowMgr[OOFM_ABSOLUTE] == NULL) { + containingBlock[OOFM_ABSOLUTE]->outOfFlowMgr[OOFM_ABSOLUTE] = + new OOFPosAbsMgr (containingBlock[OOFM_ABSOLUTE]); + DBG_OBJ_ASSOC (containingBlock[OOFM_ABSOLUTE], + containingBlock[OOFM_ABSOLUTE] + ->outOfFlowMgr[OOFM_ABSOLUTE]); + } + + if (containingBlock[OOFM_FIXED]->outOfFlowMgr[OOFM_FIXED] == NULL) { + containingBlock[OOFM_FIXED]->outOfFlowMgr[OOFM_FIXED] = + new OOFPosFixedMgr (containingBlock[OOFM_FIXED]); + DBG_OBJ_ASSOC (containingBlock[OOFM_FIXED], + containingBlock[OOFM_FIXED]->outOfFlowMgr[OOFM_FIXED]); + } +} + /** * Add a widget (word type) to the page. */ @@ -2325,21 +2392,26 @@ void Textblock::addWidget (core::Widget *widget, core::style::Style *style) widget->setStyle (style); - PRINTF ("adding the %s %p to %p (word %d) ...\n", - widget->getClassName(), widget, this, words->size()); - - if (containingBlock->outOfFlowMgr == NULL) { - containingBlock->outOfFlowMgr = new OutOfFlowMgr (containingBlock); - DBG_OBJ_ASSOC (containingBlock, containingBlock->outOfFlowMgr); - } + initOutOfFlowMgrs (); - if (OutOfFlowMgr::isWidgetHandledByOOFM (widget)) { - PRINTF (" -> out of flow.\n"); + if (testWidgetOutOfFlow (widget)) { + int oofmIndex = -1; + if (testWidgetFloat (widget)) + oofmIndex = OOFM_FLOATS; + else if (testWidgetAbsolutelyPositioned (widget)) + oofmIndex = OOFM_ABSOLUTE; + else if (testWidgetFixedPositioned (widget)) + oofmIndex = OOFM_FIXED; + else + lout::misc::assertNotReached (); - widget->setParent (containingBlock); + widget->setParent (containingBlock[oofmIndex]); widget->setGenerator (this); - containingBlock->outOfFlowMgr->addWidgetOOF (widget, this, - words->size ()); + int oofmSubRef = + containingBlock[oofmIndex]->outOfFlowMgr[oofmIndex] + ->addWidgetOOF (widget, this, words->size ()); + widget->parentRef = makeParentRefOOF (oofmIndex, oofmSubRef); + Word *word = addWord (0, 0, 0, 0, style); word->content.type = core::Content::WIDGET_OOF_REF; word->content.widget = widget; @@ -2348,14 +2420,14 @@ void Textblock::addWidget (core::Widget *widget, core::style::Style *style) // problems with breaking near float definitions.) setBreakOption (word, style, 0, 0, false); } else { - PRINTF (" -> within flow.\n"); - widget->setParent (this); // TODO Replace (perhaps) later "textblock" by "OOF aware widget". - if (widget->instanceOf (Textblock::CLASS_ID)) - containingBlock->outOfFlowMgr->addWidgetInFlow ((Textblock*)widget, - this, words->size ()); + if (widget->instanceOf (Textblock::CLASS_ID)) { + for (int i = 0; i < NUM_OOFM; i++) + containingBlock[i]->outOfFlowMgr[i] + ->addWidgetInFlow ((Textblock*)widget, this, words->size ()); + } core::Requisition size; calcWidgetSize (widget, &size); @@ -2593,7 +2665,7 @@ void Textblock::addParbreak (int space, core::style::Style *style) for (Widget *widget = this; widget->getParent() != NULL && widget->getParent()->instanceOf (Textblock::CLASS_ID) && - !OutOfFlowMgr::isRefOutOfFlow (widget->parentRef); + !isWidgetOOF (widget); widget = widget->getParent ()) { Textblock *textblock2 = (Textblock*)widget->getParent (); int index = textblock2->hasListitemValue ? 1 : 0; @@ -2604,7 +2676,7 @@ void Textblock::addParbreak (int space, core::style::Style *style) if (!isfirst) { /* The text block we searched for has been found. */ Word *word2; - int lineno = OutOfFlowMgr::getLineNoFromRef (widget->parentRef); + int lineno = getWidgetLineNo (widget); if (lineno > 0 && (word2 = @@ -2613,8 +2685,7 @@ void Textblock::addParbreak (int space, core::style::Style *style) word2->content.type == core::Content::BREAK) { if (word2->content.breakSpace < space) { word2->content.breakSpace = space; - textblock2->queueResize - (OutOfFlowMgr::createRefNormalFlow (lineno), false); + textblock2->queueResize (makeParentRefInFlow (lineno), false); textblock2->mustQueueResize = false; } } @@ -2738,10 +2809,13 @@ core::Widget *Textblock::getWidgetAtPoint(int x, int y, int level) // First, search for widgets out of flow, notably floats, since // there are cases where they overlap child textblocks. Should // later be refined using z-index. - Widget *oofWidget = - outOfFlowMgr ? outOfFlowMgr->getWidgetAtPoint (x, y, level) : NULL; - if (oofWidget) - return oofWidget; + for (int i = 0; i < NUM_OOFM; i++) { + Widget *oofWidget = + outOfFlowMgr[i] ? + outOfFlowMgr[i]->getWidgetAtPoint (x, y, level) : NULL; + if (oofWidget) + return oofWidget; + } lineIndex = findLineIndexWhenAllocated (y - allocation.y); @@ -3037,7 +3111,7 @@ void Textblock::borderChanged (int y, Widget *vloat) minWrapLineIndex, maxWrapLineIndex, vloat->getGenerator() == this ? "yes" : "no"); - queueResize (OutOfFlowMgr::createRefNormalFlow (realWrapLineIndex), true); + queueResize (makeParentRefInFlow (realWrapLineIndex), true); // Notice that the line no. realWrapLineIndex may not exist yet. if (realWrapLineIndex == 0) |