From 0a565f9b2bfc084a3292ad0c3db85e76cc8dc060 Mon Sep 17 00:00:00 2001 From: Sebastian Geerken Date: Wed, 3 Jun 2015 22:40:07 +0200 Subject: Moved dev docs to devdoc. --- devdoc/dw-fixed-positions.doc | 63 ++++ devdoc/dw-interrupted-drawing-1.png | Bin 0 -> 7142 bytes devdoc/dw-interrupted-drawing-2.png | Bin 0 -> 42606 bytes devdoc/dw-interrupted-drawing-2.svg | 706 ++++++++++++++++++++++++++++++++++++ devdoc/dw-interrupted-drawing.doc | 121 ++++++ devdoc/dw-miscellaneous.doc | 187 ++++++++++ devdoc/dw-size-request-pos-01.png | Bin 0 -> 31630 bytes devdoc/dw-size-request-pos.doc | 73 ++++ devdoc/dw-stacking-context.doc | 114 ++++++ 9 files changed, 1264 insertions(+) create mode 100644 devdoc/dw-fixed-positions.doc create mode 100644 devdoc/dw-interrupted-drawing-1.png create mode 100644 devdoc/dw-interrupted-drawing-2.png create mode 100644 devdoc/dw-interrupted-drawing-2.svg create mode 100644 devdoc/dw-interrupted-drawing.doc create mode 100644 devdoc/dw-miscellaneous.doc create mode 100644 devdoc/dw-size-request-pos-01.png create mode 100644 devdoc/dw-size-request-pos.doc create mode 100644 devdoc/dw-stacking-context.doc (limited to 'devdoc') diff --git a/devdoc/dw-fixed-positions.doc b/devdoc/dw-fixed-positions.doc new file mode 100644 index 00000000..d62565ff --- /dev/null +++ b/devdoc/dw-fixed-positions.doc @@ -0,0 +1,63 @@ +/** \page dw-fixed-positions Fixed positions + +In some cases, widgets or widget content must be positioned relative +to the viewport. As in the CSS specification, these positions will be +called "fixed positions". This must not be confused with "fixedly +positioned elements" (see \ref dw-out-of-flow), which are a special +case of fixed positions. + + +Applications +============ + +As defined by CSS +----------------- + +- "position: fixed"; see \ref dw-out-of-flow. +- "background-attachment: fixed"; see \ref dw-images-and-backgrounds. + +Idea for tables +--------------- + +Often, tables have a header, which contains informations necessary to +interpret the columns in the table body. For this, HTML defines the elements +<thead> and <tbody> +[1]. + +For large tables, the problem occurs that the table header gets out of +the reader's view. In paged media, where a large table covers multiple +pages, this is often solved by *repeating* the table header on each +page occupied by the table. When using a viewport, a table larger than +the vieport could be displayed like this: + +1. If the top of the table is within the viewport, show the table + header at the usual position. +2. As soon as top of the table gets above the top border of the + viewport, keep the table header at the viewport top, so that it is + still visible (this means, it moves down, relative to the + *canvas*). This way, the header is still visible, so our objective + is achieved. +3. When scrolling further down, at some point the table body gets out + of the viewport again, and so should the table header. + +(Some images would be nice.) + +These ideas should be considered when developing a design for fixed +positions. + + +Design sketch +============== + +[...] + + +---------------------------------------------------------------------- + +[1] +... and also <tfoot>, which is not discussed here, for reasons +of simplicity. However, it is obvious that <tfoot> should be +dealt with in an analogue way as <thead>. + + +*/ \ No newline at end of file diff --git a/devdoc/dw-interrupted-drawing-1.png b/devdoc/dw-interrupted-drawing-1.png new file mode 100644 index 00000000..58289490 Binary files /dev/null and b/devdoc/dw-interrupted-drawing-1.png differ diff --git a/devdoc/dw-interrupted-drawing-2.png b/devdoc/dw-interrupted-drawing-2.png new file mode 100644 index 00000000..8ec54035 Binary files /dev/null and b/devdoc/dw-interrupted-drawing-2.png differ diff --git a/devdoc/dw-interrupted-drawing-2.svg b/devdoc/dw-interrupted-drawing-2.svg new file mode 100644 index 00000000..6dbc6aca --- /dev/null +++ b/devdoc/dw-interrupted-drawing-2.svg @@ -0,0 +1,706 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + body + + + #sc-1 + + + + #fl-1 + + + + #sc-2 + + + + + + + + + + + + + + + + + + + + + + + + + + + #sc-1 detects that #fl-1interrupts the drawing + + + + + #fl-1 is drawn asan interruption + + + + drawing of #sc-1is continued + + + + + + + + + no need anymoreto draw #fl-1 + + + + + + + diff --git a/devdoc/dw-interrupted-drawing.doc b/devdoc/dw-interrupted-drawing.doc new file mode 100644 index 00000000..c7037666 --- /dev/null +++ b/devdoc/dw-interrupted-drawing.doc @@ -0,0 +1,121 @@ +/** \page dw-interrupted-drawing Interrupted drawing + +Describing the problem +====================== + +Without interrupting drawing (which is described below), a widget can +define the order in which its parts (background, non-widget content, +child widgets, etc.) are drawn, but it must be drawn as a whole. There +are situations when this is not possible. + +Consider the following simple HTML document: + + + + + +
+
+ Float, line 1/3
+ Float, line 2/3
+ Float, line 3/3 +
+ Stacking Context 1 +
Stacking Context 2
+
+ + +The rendering will look like this: + +\image html dw-interrupted-drawing-1.png + +Note the missing "Float, line 2/3" of element #fl-1, which is covered +by element #sc-2. + +As described in \ref dw-out-of-flow, it has to be distinguished +between the *container* hierarchy (equivalent to the hierarchy of +dw::core::Widget.) and the the *generator* hierarchy. In the following +diagram, the former is represented by solid lines, the latter by +dotted lines: + +\dot +digraph G { + node [shape=rect, fontname=Helvetica, fontsize=10]; + edge [arrowhead="vee"]; + + "#sc-1" [fillcolor="#ffe0e0", style="filled"]; + "#fl-1" [fillcolor="#b0ffb0", style="filled"]; + "#sc-2" [fillcolor="#f0f0ff", style="filled"]; + + "body" -> "#sc-1"; + "body" -> "#fl-1"; + { rank=same; "#sc-1" -> "#fl-1" [style=dotted]; } + "#sc-1" -> "#sc-2"; +} +\enddot + + +The drawing order of the four elements (represented by widgets) is: + +- body, +- #sc-1, +- #fl-1, +- #sc-2. + +Since + +1. #sc-2 is a child of #sc-1, but +2. #fl-1 is a child of the body, and +3. a widget can only draw its descendants (not neccessary children, + but drawing siblings is not allowed), + +#sc-1 cannot be drawn as a whole; instead drawing is **interrupted** +by #fl-1. This means: + +1. the background and text of #sc-1 is drawn; +2. drawing of #sc-1 is **interrupted** by #fl-1 (see below for details), +3. drawing of #sc-1 is **continued**, by drawing #sc-2. + +The exact control flow is described in this sequence diagram: + +\image html dw-interrupted-drawing-2.png + + +When is drawing interrupted? +============================ + +A widget out of flow is regarded as part of the stacking context (see +\ref dw-stacking-context) of its *generator* (in the example above: +#fl-1 is part of the stacking context stablished by #sc-1, not the one +established by body). For this reason, a widget out of flow must, in +some cases, drawn while the *gerator* is drawn, as an +interruption. The exact rule: + +A widget out of flow must be drawn as an interruption (while the +*generator* is drawn) if the stacking context of the generator (to +which this widget belongs) is in front of the stacking context of the +container (the parent widget). + +See dw::oof::OOFAwareWidget::doesWidgetOOFInterruptDrawing. + + +How does interruption of drawing work? +====================================== + +When a widget detects that an other widget should be drawn as +interruption (see above), it calls dw::core::Widget::drawInterruption, +which + +1. draws the widget within another "context" (area and reference + widget); for this the original drawing area + (dw::core::DrawingContext::getToplevelArea) is used. +2. Using dw::core::DrawingContext::addWidgetDrawnAsInterruption, and + checking later with + dw::core::DrawingContext::hasWidgetBeenDrawnAsInterruption prevents + these widgets from being drawn twice. + +*/ diff --git a/devdoc/dw-miscellaneous.doc b/devdoc/dw-miscellaneous.doc new file mode 100644 index 00000000..d6b3cae3 --- /dev/null +++ b/devdoc/dw-miscellaneous.doc @@ -0,0 +1,187 @@ +/** \page dw-miscellaneous Miscellaneous Notes on Dw + +This is a barely sorted list of issues which I consider noteworthy, +but have yet to be moved to other parts of the documentation (which is +partly to be created). + +General +======= + +Widget allocation outside of parent allocation +---------------------------------------------- +A widget allocation outside of the allocation of the parent is +allowed, but the part outside is not visible. + +Which widgets may be drawn? +------------------- + +All drawing starts with the toplevel widget +(cf. dw::core::Widget::queueDrawArea, dw::core::Layout::queueDraw, and +dw::core::Layout::expose), and a widget has to draw its children, in a +way consistent with their stacking order. + +There are two exceptions: + +1. Direct descendants, which are not children, may be drawn, if the + parent can distinguish them and so omit drawing them a second + time. See dw::core::StackingContextMgr and \ref dw-stacking-context. + Parents should not draw children in flow for which + dw::core::StackingContextMgr::handledByStackingContextMgr returns + true. +2. Interrupted drawing: via dw::core::Widget::drawInterruption; see + \ref dw-interrupted-drawing. + +Similar rules apply to handling mouse events +(dw::core::Widget::getWidgetAtPoint). + +Interrupted drawing +------------------- +→ \ref dw-interrupted-drawing. + +Similar rules apply to handling mouse events +(dw::core::Widget::getWidgetAtPoint). + + +Floats +====== + +Handling collisions +------------------- +The CSS specification allows two strategies to deal with colliding +floats: placing the second float beside or below the first one. Many +other browsers implement the first approach, while dillo implements +the second one, which may cause problems when the author assumes the +first. Example: the "tabs" at the top of every page at Wikipedia +("Article", "Talk", ...). + +Float containers in flow +------------------------ +Consider the following HTML snippet: + + + +

Text

+ + +Interestingly, dillo shows "Text" always *below* the image, even if +there is enough space left of it. An investigation shows that the +paragraph (<p>) is regarded as own floats container (because of +*overflow:hidden*), so the floats container above (<body>) +regards this block as widget which must be fit between the floats +(dw::Textblock::mustBorderBeRegarded > +dw::Textblock::getWidgetRegardingBorderForLine). However, since a +textblock in flow always covers (at least) the whole available width, +which is defined *without* considering floats, the space left of the +float will always be to narrow, so that the paragraph is moved below +the float, by inserting an empty line before. + +When searching for a solution, several difficulties show up: + +1. The available width, which is used for the width of the textblock, + is defined independent of floats. Aside from problems when changing + this definition, a dependance on floats would be difficult to + implement, since *sizeRequest* is independent of a position. (See + also \ref dw-out-of-flow.) +2. I must admit that I do not rembember the exact rationale and the + test case behind adding the exception in + dw::Textblock::getWidgetRegardingBorderForLine (see above), but + simply removing this exception will result in a possible + overlapping of floats from both containers, since no collisions are + tested for. +3. On the other hand, mixing the float containers (interaction of two + or more instances of dw::oof::OOFFloatsMgr), e. g. for + collision tests, would become too complex and possibly result in + performance problems. + +Instead, this approach is focussed: + +- Goal: the paragraph is narrowed so it fits, *as a whole*, between + the floats. +- The approach is to remove the exception in + dw::Textblock::getWidgetRegardingBorderForLine. A textblock, which + is a float container in flow (as this paragraph), is returned by + this method and so dw::Textblock::mustBorderBeRegarded returns + *true*. This will put this paragraph again at the correct position. +- To avoid overlappings, the linebreaking width of this paragraph + (which is also used for positioning of floats) is the available + width, minus the maximal float width on either side. (This is an + approach similar to the one dw::Ruler will use soon). Most likely, + some new methods will have to be added to calculate this. +- For paragraphs like this, dw::Textblock::borderChanged must rewrap + all lines; *y* is irrelevant in this case. +- Since the textblock will tend to become taller when getting + narrower, and so possibly cover more (wider) floats, and so become + narrower again etc., there may be multible solutions for calculating + the size. Generally, a smaller height (and so larger width) is + preferred. +- There remains a problem: what if a word is too large? Should a + textblock of this kind then reard the floats in detail, to insert + empty lines when needed? + +**Real-world cases:** *Overflow:hidden* is set for headings in +Wikipedia, and so this case occurs when there is a float (thumb image) +before a heading. See e. g. +this page +and scroll a bit up; the company logos should be right of this section. + +**Priority:** Since this is not a regression, compared to not +supporting floats at all, a fix is not urgent for a new release. + +Positioned elements +=================== + +General +------- +(See also *relative positions* below.) + +What about negative positions? + +dw::oof::OutOfFlowMgr::tellPosition1 and +dw::oof::OutOfFlowMgr::tellPosition2 could be combined again, and +called in the respective circumstance, depending on +dw::oof::OutOfFlowMgr::mayAffectBordersAtAll. + +Relative positions +------------------ +**General Overview:** At the original position, a space as large as +the positioned element is left. This is implemented by assigning a +size to the widget *reference*. For this there are two new methods: +dw::oof::OutOfFlowMgr::calcWidgetRefSize and +dw::oof::OOFAwareWidget::widgetRefSizeChanged. + +**Bug:** Since the size of a relatively positioned element should be +calculated as if it was in flow, the available width should be +delegated to the *generator*; however, since +dw::oof::OOFPosRelMgr::dealingWithSizeOfChild returns *false* in all +cases, it is delegated to the *container*. **Idea for fix:** +dw::oof::OOFPosRelMgr::dealingWithSizeOfChild should return *false* if +and only if the generator of the child is the container (to prevent an +endless recursion). In other cases, +dw::oof::OOFPosRelMgr::getAvailWidthOfChild and +dw::oof::OOFPosRelMgr::getAvailHeightOfChild should directly call the +respective methods of the *generator*, which must be made public then. + +**Performance:** In many cases, the first call of +dw::oof::OOFPosRelMgr::sizeAllocateEnd will queue again the resize +idle, since some elements are not considered in +dw::oof::OOFPosRelMgr::getSize. One case could be removed: if a +positioned element has *left* = *top* = 0, and its total size (the +requisition) is equal to the space left at the original position, the +size of the widget *reference* +(dw::oof::OOFAwareWidget::getRequisitionWithoutOOF, see +dw::oof::OOFPosRelMgr::calcWidgetRefSize). + +**Documentation:** Describe why the latter is not covered by +dw::oof::OOFPositionedMgr::doChildrenExceedContainer. (Is this really +the case?) + +**Open:** Stacking order? Furthermore: a relatively positioned element +does not always constitute a containing block (see CSS specification). + +Fixed positions +--------------- +Currently, fixedly positioned elements are positioned relative to the +canvas, not to the viewport. For a complete implementation, see \ref +dw-fixed-positions. + +*/ diff --git a/devdoc/dw-size-request-pos-01.png b/devdoc/dw-size-request-pos-01.png new file mode 100644 index 00000000..ba32e243 Binary files /dev/null and b/devdoc/dw-size-request-pos-01.png differ diff --git a/devdoc/dw-size-request-pos.doc b/devdoc/dw-size-request-pos.doc new file mode 100644 index 00000000..08af0eec --- /dev/null +++ b/devdoc/dw-size-request-pos.doc @@ -0,0 +1,73 @@ +/** \page dw-size-request-pos Size requisitions depending on positions + +
The complex "widget + sizes" is currently divided into three documents: \ref + dw-widget-sizes, \ref dw-grows, and **Size requisitions depending on + positions** (this document).
+ +Motivation +========== + +As described in \ref dw-out-of-flow (*The sizeRequest/sizeAllocate +problem*), the principle that the size of a widget depends only on the +sizes of its children causes some problems with floats; the current +solution is a frequent correction by calling +dw::core::Widget::queueResize. In this document, an alternative +approach is presented. + + +General Idea +============ + +A widget size may depend on the position relative to an anchestor +widget. If a widget wants to get the size of a child widget, it should + +1. call the new method dw::core::Widget::sizeRequestReference, + which returns NULL, when the child's size does not depend on the + position, or a widget relative to which the child's position must + be calculated; +2. call dw::core::Widget::sizeRequest with the position relative to + this widget. + +The position passed to dw::core::Widget::sizeRequest must be the +position at which this child will be allocated. + +There are situations where the parent widget is unable to determine +this position before the size is known. An example: a textblock widget +cannot determine the position of an inline widget (like an image, or +an inline block) before the line is finished; on the other hand, +finishing the line depends on knowing the sizes of the inline widgets. + +This may result in a conflict, when the size of an inline widgets +depends on the position. Fortunately, this is not the case in dillo: +the only widget whose size depends on the position is dw::Textblock +(the size will depend on the position within its floats container); but +an inline blocks constitute its own floats container, so that there is +no dependance on a position within another widget. + +Generally, this case should be handled by providing a fallback +strategy. (TODO: How does this look like? The widget is forced to +calculate its size independant of the position?) + +Resizing +-------- +Currently, the size of a widget has to be recalculated, when + +1. it has called dw::core::Widget::queueResize, or +2. the size of a child widget has to be recalculated. + +Since for this new approach, the size does not only depend on the size +of the children, the second condition must be modified. However, +regarding changes of the position is not sufficient. Consider this +example, where a float size changes as soon as the image is loaded: + +\image html dw-size-request-pos-01.png + +The second paragraph ("A longer paragraph" ...) stays at the same +position, both absolute and relative to the float container, but has +to be rewrapped because of the float. + +(TODO: A detailed design is yet to de developed.) + +*/ \ No newline at end of file diff --git a/devdoc/dw-stacking-context.doc b/devdoc/dw-stacking-context.doc new file mode 100644 index 00000000..6138ca5d --- /dev/null +++ b/devdoc/dw-stacking-context.doc @@ -0,0 +1,114 @@ +/** \page dw-stacking-context Handling stacking contexts + +Stacking Context and dw::core::StackingContextMgr +================================================= + +For the definition of stacking contexts, see CSS 2.1 specification, + +- section + 9.9.1: Specifying the stack level: the 'z-index' property and +- appendix E. + +A widget establishes a stacking context when it is positioned and its +style value of *z-index* is different from *auto* (see +dw::core::StackingContextMgr::isEstablishingStackingContext). In this +case, it is assigned an instance of dw::core::StackingContextMgr, +which has also access to the widgets establishing the child contexts. + + +Stacking Order +============== + +The stacking order influences + +1. the order in which child widgets are drawn (dw::core::Widget::draw), + and +2. the order in which mouse events are dispatched to child widgets + (dw::core::Widget::getWidgetAtPoint). + +The first is done from bottom to top, the latter from top to bottom. + +I'm here referring to the simplified description in +section +9.9.1. The table shows a recommended order for the implementations +of dw::core::Widget::draw and dw::core::Widget::getWidgetAtPoint +(for the latter, read from bottom to top): + + + + + + + + + + + +
CSS specification Drawing Mouse events +
*1. the background and borders of the element forming the + stacking context.* + dw::core::Widget::drawBox + Nothing necessary. +
*2. the child stacking contexts with negative stack levels (most + negative first).* + dw::core::StackingContextMgr::drawBottom (when defined) + dw::core::StackingContextMgr::getBottomWidgetAtPoint (when defined) +
*3. the in-flow, non-inline-level, non-positioned descendants.* + + When (i) widget specific content is drawn, then (ii) + dw::oof::OOFAwareWidget::drawOOF is called, this will + have this effect: + + 1. all in-flow elements are drawn, + 2. floats are drawn and + 3. positioned elements with *z-index: auto* are drawn + (latter two done by + dw::oof::OOFAwareWidget::drawOOF, in this order). + + This order differs from the specified order, but + since floats and in-flow elements do not overlap, + this difference has no effect. + + Drawing in-line elements, floats and positioned + elements with *z-index: auto* and should avoid + duplicate calls: Widgets drawn by + dw::core::StackingContextMgr::drawBottom and by + dw::core::StackingContextMgr::drawTop should be + excluded here. This can be tested with + dw::core::StackingContextMgr::handledByStackingContextMgr. + + Likewise, the implementation should (i) test + dw::oof::OOFAwareWidget::getWidgetOOFAtPoint, and + (ii) search through the chilren. Also, duplicate + calls should be avoided using + dw::core::StackingContextMgr::handledByStackingContextMgr. + + There are already the implementations + dw::core::Widget::getWidgetAtPoint (ignoring + dw::oof::OutOfFlowMgr) and + dw::oof::OOFAwareWidget::getWidgetAtPoint (including + dw::oof::OutOfFlowMgr). + +
*4. the non-positioned floats.* +
*5. the in-flow, inline-level, non-positioned descendants, + including inline tables and inline blocks.* +
(What about positioned elements with *z-index: auto*? Seems to be + missing in + section + 9.9.1, but mentioned in + appendix E, + item 8. +
*6. the child stacking contexts with stack level 0 and the + positioned descendants with stack level 0.* + dw::core::StackingContextMgr::drawTop (when defined) + dw::core::StackingContextMgr::getTopWidgetAtPoint + (when defined) +
*7. the child stacking contexts with positive stack levels (least + positive first).* +
+ +Note: This is not quite in conformance with the specification: this +description refers to any widget, not only widgets establishing a +stacking context. Does this make a difference? + +*/ \ No newline at end of file -- cgit v1.2.3