diff options
-rw-r--r-- | dw/Makefile.am | 2 | ||||
-rw-r--r-- | dw/oofawarewidget.cc | 49 | ||||
-rw-r--r-- | dw/oofawarewidget.hh | 14 | ||||
-rw-r--r-- | dw/ooffloatsmgr.cc | 9 | ||||
-rw-r--r-- | dw/ooffloatsmgr.hh | 1 | ||||
-rw-r--r-- | dw/oofpositionedmgr.cc | 18 | ||||
-rw-r--r-- | dw/oofpositionedmgr.hh | 8 | ||||
-rw-r--r-- | dw/oofposrelmgr.cc | 96 | ||||
-rw-r--r-- | dw/oofposrelmgr.hh | 32 | ||||
-rw-r--r-- | dw/outofflowmgr.hh | 2 | ||||
-rw-r--r-- | dw/textblock.cc | 27 | ||||
-rw-r--r-- | dw/textblock.hh | 9 | ||||
-rw-r--r-- | dw/textblock_linebreaking.cc | 16 | ||||
-rw-r--r-- | src/html.cc | 6 |
14 files changed, 254 insertions, 35 deletions
diff --git a/dw/Makefile.am b/dw/Makefile.am index ba0c7539..0f743114 100644 --- a/dw/Makefile.am +++ b/dw/Makefile.am @@ -82,6 +82,8 @@ libDw_widgets_a_SOURCES = \ oofposfixedmgr.hh \ oofpositionedmgr.cc \ oofpositionedmgr.hh \ + oofposrelmgr.cc \ + oofposrelmgr.hh \ outofflowmgr.cc \ outofflowmgr.hh \ regardingborder.cc \ diff --git a/dw/oofawarewidget.cc b/dw/oofawarewidget.cc index 4f7f4bc8..3e51600f 100644 --- a/dw/oofawarewidget.cc +++ b/dw/oofawarewidget.cc @@ -20,6 +20,7 @@ #include "oofawarewidget.hh" #include "ooffloatsmgr.hh" #include "oofposabsmgr.hh" +#include "oofposrelmgr.hh" #include "oofposfixedmgr.hh" using namespace dw; @@ -34,7 +35,7 @@ namespace dw { namespace oof { const char *OOFAwareWidget::OOFM_NAME[NUM_OOFM] = { - "FLOATS", "ABSOLUTE", "FIXED" + "FLOATS", "ABSOLUTE", "RELATIVE", "FIXED" }; int OOFAwareWidget::CLASS_ID = -1; @@ -90,18 +91,37 @@ void OOFAwareWidget::notifySetAsTopLevel () } } -bool OOFAwareWidget::getOOFMIndex (Widget *widget) +int OOFAwareWidget::getOOFMIndex (Widget *widget) { + DBG_OBJ_ENTER_O ("construct", 0, NULL, "getOOFMIndex", "%p", widget); + DBG_OBJ_MSGF_O ("construct", 1, NULL, "position = %s, float = %s", + widget->getStyle()->position + == style::POSITION_STATIC ? "static" : + (widget->getStyle()->position + == style::POSITION_RELATIVE ? "relative" : + (widget->getStyle()->position + == style::POSITION_ABSOLUTE ? "absolute" : + (widget->getStyle()->position + == style::POSITION_FIXED ? "fixed" : "???"))), + widget->getStyle()->vloat == style::FLOAT_NONE ? "none" : + (widget->getStyle()->vloat == style::FLOAT_LEFT ? "left" : + (widget->getStyle()->vloat == style::FLOAT_RIGHT ? + "right" : "???"))); + + int index = -1; if (testWidgetFloat (widget)) - return OOFM_FLOATS; + index = OOFM_FLOATS; else if (testWidgetAbsolutelyPositioned (widget)) - return OOFM_ABSOLUTE; + index = OOFM_ABSOLUTE; + else if (testWidgetRelativelyPositioned (widget)) + index = OOFM_RELATIVE; else if (testWidgetFixedlyPositioned (widget)) - return OOFM_FIXED; - else { + index = OOFM_FIXED; + else lout::misc::assertNotReached (); - return -1; - } + + DBG_OBJ_LEAVE_VAL_O (NULL, "%d (%s)", index, OOFM_NAME[index]); + return index; } bool OOFAwareWidget::isOOFContainer (Widget *widget, int oofmIndex) @@ -141,6 +161,7 @@ bool OOFAwareWidget::isOOFContainer (Widget *widget, int oofmIndex) // process" in "dw-stacking-context.doc". testWidgetOutOfFlow (widget))); + case OOFM_RELATIVE: // TODO Correct? case OOFM_ABSOLUTE: // We use the toplevel widget as container, i. e. parent widget. // See also OOFPosAbsMgr::isReference for the definition of the @@ -203,6 +224,13 @@ void OOFAwareWidget::initOutOfFlowMgrs () oofContainer[OOFM_ABSOLUTE]->outOfFlowMgr[OOFM_ABSOLUTE]); } + if (oofContainer[OOFM_RELATIVE]->outOfFlowMgr[OOFM_RELATIVE] == NULL) { + oofContainer[OOFM_RELATIVE]->outOfFlowMgr[OOFM_RELATIVE] = + new OOFPosRelMgr (oofContainer[OOFM_RELATIVE]); + DBG_OBJ_ASSOC (oofContainer[OOFM_RELATIVE], + oofContainer[OOFM_RELATIVE]->outOfFlowMgr[OOFM_RELATIVE]); + } + if (oofContainer[OOFM_FIXED]->outOfFlowMgr[OOFM_FIXED] == NULL) { oofContainer[OOFM_FIXED]->outOfFlowMgr[OOFM_FIXED] = new OOFPosFixedMgr (oofContainer[OOFM_FIXED]); @@ -526,6 +554,11 @@ void OOFAwareWidget::borderChanged (int y, Widget *vloat) assertNotReached (); } +void OOFAwareWidget::widgetRefSizeChanged (int externalIndex) +{ + assertNotReached (); +} + void OOFAwareWidget::clearPositionChanged () { assertNotReached (); diff --git a/dw/oofawarewidget.hh b/dw/oofawarewidget.hh index 3d78d69a..249dfe9a 100644 --- a/dw/oofawarewidget.hh +++ b/dw/oofawarewidget.hh @@ -67,9 +67,9 @@ namespace oof { class OOFAwareWidget: public core::Widget { protected: - enum { OOFM_FLOATS, OOFM_ABSOLUTE, OOFM_FIXED, NUM_OOFM }; + enum { OOFM_FLOATS, OOFM_ABSOLUTE, OOFM_RELATIVE, OOFM_FIXED, NUM_OOFM }; static const char *OOFM_NAME[NUM_OOFM]; - enum { PARENT_REF_OOFM_BITS = 2, + enum { PARENT_REF_OOFM_BITS = 3, PARENT_REF_OOFM_MASK = (1 << PARENT_REF_OOFM_BITS) - 1 }; class OOFAwareWidgetIterator: public core::Iterator @@ -147,7 +147,7 @@ protected: { return oofContainer[oofmIndex] ? oofContainer[oofmIndex]->outOfFlowMgr[oofmIndex] : NULL; } - static bool getOOFMIndex (Widget *widget); + static int getOOFMIndex (Widget *widget); void initOutOfFlowMgrs (); void correctRequisitionByOOF (core::Requisition *requisition, @@ -209,9 +209,12 @@ public: testStyleFixedlyPositioned (style); } static inline bool testStyleOutOfFlow (core::style::Style *style) - { return testStyleFloat (style) || testStyleAbsolutelyPositioned (style) + { // Second part is equivalent to testStylePositioned(), but we still keep + // the two seperately. + return testStyleFloat (style) || testStyleAbsolutelyPositioned (style) + || testStyleRelativelyPositioned (style) || testStyleFixedlyPositioned (style); } - + static inline bool testWidgetFloat (Widget *widget) { return testStyleFloat (widget->getStyle ()); } @@ -235,6 +238,7 @@ public: virtual bool mustBeWidenedToAvailWidth (); virtual void borderChanged (int y, core::Widget *vloat); + virtual void widgetRefSizeChanged (int externalIndex); virtual void clearPositionChanged (); virtual void oofSizeChanged (bool extremesChanged); virtual int getLineBreakWidth (); // Should perhaps be renamed. diff --git a/dw/ooffloatsmgr.cc b/dw/ooffloatsmgr.cc index 5b6c8755..c509af8d 100644 --- a/dw/ooffloatsmgr.cc +++ b/dw/ooffloatsmgr.cc @@ -1421,6 +1421,11 @@ int OOFFloatsMgr::addWidgetOOF (Widget *widget, OOFAwareWidget *generatingBlock, return subRef; } +void OOFFloatsMgr::calcWidgetRefSize (Widget *widget, Requisition *size) +{ + size->width = size->ascent = size->descent = 0; +} + void OOFFloatsMgr::moveExternalIndices (OOFAwareWidget *generatingBlock, int oldStartIndex, int diff) { @@ -1434,8 +1439,8 @@ void OOFFloatsMgr::moveExternalIndices (SortedFloatsVector *list, { // Could be faster with binary search, but the GB (not CB!) lists // should be rather small. - for (int i = 0; i < list->size(); i++) { - Float *vloat = list->get(i); + for (int i = 0; i < list->size (); i++) { + Float *vloat = list->get (i); if (vloat->externalIndex >= oldStartIndex) { vloat->externalIndex += diff; DBG_OBJ_SET_NUM_O (vloat->getWidget (), "<Float>.externalIndex", diff --git a/dw/ooffloatsmgr.hh b/dw/ooffloatsmgr.hh index 430f383f..94a67fea 100644 --- a/dw/ooffloatsmgr.hh +++ b/dw/ooffloatsmgr.hh @@ -354,6 +354,7 @@ public: int externalIndex); int addWidgetOOF (core::Widget *widget, OOFAwareWidget *generatingBlock, int externalIndex); + void calcWidgetRefSize (core::Widget *widget,core::Requisition *size); void moveExternalIndices (OOFAwareWidget *generatingBlock, int oldStartIndex, int diff); diff --git a/dw/oofpositionedmgr.cc b/dw/oofpositionedmgr.cc index 9a248cf5..270e8c84 100644 --- a/dw/oofpositionedmgr.cc +++ b/dw/oofpositionedmgr.cc @@ -254,7 +254,7 @@ int OOFPositionedMgr::addWidgetOOF (Widget *widget, OOFAwareWidget *generator, if (reference == NULL) reference = container; - Child *child = new Child (widget, generator, reference); + Child *child = new Child (widget, generator, reference, externalIndex); children->put (child); childrenByWidget->put (new TypedPointer<Widget> (widget), child); @@ -264,15 +264,29 @@ int OOFPositionedMgr::addWidgetOOF (Widget *widget, OOFAwareWidget *generator, DBG_OBJ_SET_PTR_O (widget, "<Positioned>.generator", generator); DBG_OBJ_SET_PTR_O (widget, "<Positioned>.reference", reference); + DBG_OBJ_SET_NUM_O (widget, "<Positioned>.externalIndex", externalIndex); DBG_OBJ_MSGF ("construct.oofm", 1, "=> %d", subRef); DBG_OBJ_LEAVE (); return subRef; } +void OOFPositionedMgr::calcWidgetRefSize (Widget *widget, Requisition *size) +{ + size->width = size->ascent = size->descent = 0; +} + void OOFPositionedMgr::moveExternalIndices (OOFAwareWidget *generator, int oldStartIndex, int diff) { + for (int i = 0; i < children->size (); i++) { + Child *child = children->get (i); + if (child->externalIndex >= oldStartIndex) { + child->externalIndex += diff; + DBG_OBJ_SET_NUM_O (child->widget, "<Positioned>.externalIndex", + child->externalIndex); + } + } } void OOFPositionedMgr::markSizeChange (int ref) @@ -630,7 +644,7 @@ void OOFPositionedMgr::calcPosAndSizeChildOfChild (Child *child, int refWidth, // *xPtr and *yPtr refer to reference area; caller must adjust them. DBG_OBJ_ENTER ("resize.oofm", 0, "calcPosAndSizeChildOfChild", - "%p, %d, %d, ...", child, refWidth, refHeight); + "[%p], %d, %d, ...", child->widget, refWidth, refHeight); // TODO (i) Consider {min|max}-{width|heigt}. (ii) Height is always // apportioned to descent (ascent is preserved), which makes sense diff --git a/dw/oofpositionedmgr.hh b/dw/oofpositionedmgr.hh index 9b99f3cd..9fa80cf5 100644 --- a/dw/oofpositionedmgr.hh +++ b/dw/oofpositionedmgr.hh @@ -15,12 +15,13 @@ protected: public: core::Widget *widget, *reference; OOFAwareWidget *generator; - int x, y; + int externalIndex, x, y; inline Child (core::Widget *widget, OOFAwareWidget *generator, - core::Widget *reference) + core::Widget *reference, int externalIndex) { this->widget = widget; this->generator = generator; - this->reference = reference; x = y = 0; } + this->reference = reference; this->externalIndex = externalIndex; + x = y = 0; } }; virtual bool isReference (core::Widget *widget) = 0; @@ -98,6 +99,7 @@ public: int externalIndex); int addWidgetOOF (core::Widget *widget, OOFAwareWidget *generator, int externalIndex); + void calcWidgetRefSize (core::Widget *widget, core::Requisition *size); void moveExternalIndices (OOFAwareWidget *generator, int oldStartIndex, int diff); diff --git a/dw/oofposrelmgr.cc b/dw/oofposrelmgr.cc new file mode 100644 index 00000000..ecb47ba4 --- /dev/null +++ b/dw/oofposrelmgr.cc @@ -0,0 +1,96 @@ +/* + * Dillo Widget + * + * Copyright 2015 Sebastian Geerken <sgeerken@dillo.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "oofposrelmgr.hh" +#include "oofawarewidget.hh" + +namespace dw { + +namespace oof { + +OOFPosRelMgr::OOFPosRelMgr (OOFAwareWidget *container) : + OOFPositionedMgr (container) +{ + DBG_OBJ_CREATE ("dw::OOFPosRelMgr"); +} + +OOFPosRelMgr::~OOFPosRelMgr () +{ + DBG_OBJ_DELETE (); +} + + +void OOFPosRelMgr::markSizeChange (int ref) +{ + DBG_OBJ_ENTER ("resize.oofm", 0, "markSizeChange", "%d", ref); + Child *child = children->get(ref); + DBG_OBJ_MSGF ("resize.oofm", 1, "generator = %p, externalIndex = %d", + child->generator, child->externalIndex); + child->generator->widgetRefSizeChanged (child->externalIndex); + DBG_OBJ_LEAVE (); +} + +void OOFPosRelMgr::markExtremesChange (int ref) +{ +} + +void OOFPosRelMgr::calcWidgetRefSize (core::Widget *widget, + core::Requisition *size) +{ + DBG_OBJ_ENTER ("resize.oofm", 0, "calcWidgetRefSize", "%p", widget); + widget->sizeRequest (size); + DBG_OBJ_LEAVE_VAL ("%d * (%d + %d)", + size->width, size->ascent, size->descent); +} + +bool OOFPosRelMgr::isReference (core::Widget *widget) +{ + // TODO Remove soon. This implementation will imply reference = container. + return false; +} + +// TODO: Check all containerBox* implementations. + +int OOFPosRelMgr::containerBoxOffsetX () +{ + return container->getParent () ? + container->boxOffsetX () - container->getStyle()->padding.left : 0; +} + +int OOFPosRelMgr::containerBoxOffsetY () +{ + return container->getParent () ? + container->boxOffsetY () - container->getStyle()->padding.top : 0; +} + +int OOFPosRelMgr::containerBoxRestWidth () +{ + return container->getParent () ? + container->boxRestWidth () - container->getStyle()->padding.right : 0; +} + +int OOFPosRelMgr::containerBoxRestHeight () +{ + return container->getParent () ? + container->boxRestHeight () - container->getStyle()->padding.bottom : 0; +} + +} // namespace oof + +} // namespace dw diff --git a/dw/oofposrelmgr.hh b/dw/oofposrelmgr.hh new file mode 100644 index 00000000..6f712a84 --- /dev/null +++ b/dw/oofposrelmgr.hh @@ -0,0 +1,32 @@ +#ifndef __DW_OOFPOSRELMGR_HH__ +#define __DW_OOFPOSRELMGR_HH__ + +#include "oofpositionedmgr.hh" + +namespace dw { + +namespace oof { + +class OOFPosRelMgr: public OOFPositionedMgr +{ +protected: + bool isReference (core::Widget *widget); + int containerBoxOffsetX (); + int containerBoxOffsetY (); + int containerBoxRestWidth (); + int containerBoxRestHeight (); + +public: + OOFPosRelMgr (OOFAwareWidget *container); + ~OOFPosRelMgr (); + + void markSizeChange (int ref); + void markExtremesChange (int ref); + void calcWidgetRefSize (core::Widget *widget, core::Requisition *size); +}; + +} // namespace oof + +} // namespace dw + +#endif // __DW_OOFPOSRELMGR_HH__ diff --git a/dw/outofflowmgr.hh b/dw/outofflowmgr.hh index 0ca19ee6..1632499e 100644 --- a/dw/outofflowmgr.hh +++ b/dw/outofflowmgr.hh @@ -38,6 +38,8 @@ public: OOFAwareWidget *parent, int externalIndex) = 0; virtual int addWidgetOOF (core::Widget *widget, OOFAwareWidget *generator, int externalIndex) = 0; + virtual void calcWidgetRefSize (core::Widget *widget, + core::Requisition *size) = 0; virtual void moveExternalIndices (OOFAwareWidget *generator, int oldStartIndex, int diff) = 0; diff --git a/dw/textblock.cc b/dw/textblock.cc index 40eb4014..ab5c44e8 100644 --- a/dw/textblock.cc +++ b/dw/textblock.cc @@ -735,7 +735,7 @@ void Textblock::calcExtraSpaceImpl () int clearPosition = 0; for (int i = 0; i < NUM_OOFM; i++) - if (searchOutOfFlowMgr(i)) + if (searchOutOfFlowMgr (i)) clearPosition = misc::max (clearPosition, searchOutOfFlowMgr(i)->getClearPosition (this)); @@ -2309,20 +2309,22 @@ void Textblock::addWidget (core::Widget *widget, core::style::Style *style) if (testWidgetOutOfFlow (widget)) { int oofmIndex = getOOFMIndex (widget); + DBG_OBJ_MSGF ("construct.word", 1, "ouf of flow: oofmIndex = %d (%s)", + oofmIndex, OOFM_NAME[oofmIndex]); + widget->setParent (oofContainer[oofmIndex]); widget->setGenerator (this); - int oofmSubRef = - searchOutOfFlowMgr(oofmIndex)->addWidgetOOF (widget, this, - words->size ()); + oof::OutOfFlowMgr *oofm = searchOutOfFlowMgr (oofmIndex); + int oofmSubRef = oofm->addWidgetOOF (widget, this, words->size ()); widget->parentRef = makeParentRefOOF (oofmIndex, oofmSubRef); - DBG_OBJ_MSGF ("construct.word", 1, - "ouf of flow: oofmIndex = %d, oofmSubRef = %d => " - "parentRef = %d", - oofmIndex, oofmSubRef, widget->parentRef); + DBG_OBJ_MSGF ("construct.word", 1, "oofmSubRef = %d => parentRef = %d", + oofmSubRef, widget->parentRef); - Word *word = addWord (0, 0, 0, 0, style); + core::Requisition size; + oofm->calcWidgetRefSize (widget, &size); + Word *word = addWord (size.width, size.ascent, size.descent, 0, style); word->content.type = core::Content::WIDGET_OOF_REF; word->content.widget = widget; @@ -3055,6 +3057,13 @@ void Textblock::borderChanged (int y, Widget *vloat) DBG_OBJ_LEAVE (); } +void Textblock::widgetRefSizeChanged (int externalIndex) +{ + int lineNo = findLineOfWord (externalIndex); + if (lineNo >= 0 && lineNo < lines->size ()) + queueResize (makeParentRefInFlow (lineNo), true); +} + void Textblock::clearPositionChanged () { DBG_OBJ_ENTER0 ("resize", 0, "clearPositionChanged"); diff --git a/dw/textblock.hh b/dw/textblock.hh index 5e626876..a7eeab47 100644 --- a/dw/textblock.hh +++ b/dw/textblock.hh @@ -857,6 +857,10 @@ public: static void setPenaltyEmDashRight2 (int penaltyRightEmDash2); static void setStretchabilityFactor (int stretchabilityFactor); + static inline bool mustAddBreaks (core::style::Style *style) + { return !testStyleOutOfFlow (style) || + testStyleRelativelyPositioned (style); } + Textblock (bool limitTextWidth); ~Textblock (); @@ -881,6 +885,7 @@ public: bool mustBeWidenedToAvailWidth (); void borderChanged (int y, core::Widget *vloat); + void widgetRefSizeChanged (int externalIndex); void clearPositionChanged (); void oofSizeChanged (bool extremesChanged); int getLineBreakWidth (); @@ -888,7 +893,7 @@ public: bool isPossibleContainerParent (int oofmIndex); }; -#define DBG_SET_WORD_PENALTY(n, i, is) \ +#define DBG_SET_WORD_PENALTY(n, i, is) \ D_STMT_START { \ if (words->getRef(n)->badnessAndPenalty.getPenalty (i) == INT_MIN) \ DBG_OBJ_ARRATTRSET_SYM ("words", n, "penalty." is, "-inf"); \ @@ -897,7 +902,7 @@ public: else \ DBG_OBJ_ARRATTRSET_NUM ("words", n, "penalty." is, \ words->getRef(n)->badnessAndPenalty \ - .getPenalty (i)); \ + .getPenalty (i)); \ } D_STMT_END #define DBG_SET_WORD(n) \ diff --git a/dw/textblock_linebreaking.cc b/dw/textblock_linebreaking.cc index e9815d93..719389a6 100644 --- a/dw/textblock_linebreaking.cc +++ b/dw/textblock_linebreaking.cc @@ -1914,8 +1914,22 @@ void Textblock::rewrap () for (int i = firstWord; i < words->size (); i++) { Word *word = words->getRef (i); - if (word->content.type == core::Content::WIDGET_IN_FLOW) + switch (word->content.type) { + case core::Content::WIDGET_IN_FLOW: word->content.widget->sizeRequest (&word->size); + break; + + case core::Content::WIDGET_OOF_REF: + { + int oofmIndex = getOOFMIndex (word->content.widget); + oof::OutOfFlowMgr *oofm = searchOutOfFlowMgr (oofmIndex); + oofm->calcWidgetRefSize (word->content.widget, &(word->size)); + } + break; + + default: + break; + } wordWrap (i, false); diff --git a/src/html.cc b/src/html.cc index d2e513b2..ffdbcac1 100644 --- a/src/html.cc +++ b/src/html.cc @@ -380,9 +380,9 @@ static void Html_add_textblock(DilloHtml *html, bool addBreaks, int breakSpace, S_TOP(html)->hand_over_break = true; } -static bool Html_will_textblock_be_out_of_flow(DilloHtml *html) +static bool Html_must_add_breaks(DilloHtml *html) { - return HT2TB(html)->testStyleOutOfFlow (html->style ()); + return HT2TB(html)->mustAddBreaks (html->style ()); } /* @@ -3892,7 +3892,7 @@ static void Html_check_html5_obsolete(DilloHtml *html, int ni) static void Html_display_block(DilloHtml *html) { - Html_add_textblock(html, !Html_will_textblock_be_out_of_flow (html), 0, + Html_add_textblock(html, Html_must_add_breaks (html), 0, false /* Perhaps true for widgets oof? */); } |