aboutsummaryrefslogtreecommitdiff
path: root/devdoc/dw-out-of-flow-floats.doc
blob: 2f92a5c67e86b3eaa7872dbce728362a1e284861 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/** \page dw-out-of-flow-floats Handling Elements Out Of Flow: Floats

TODO: Much missing.

(Historical) Note: Floats make use of dw-size-request-pos, which reduces the
complexity of a previous design.


Sorting floats
==============

Floats are sorted, to make binary search possible, in these lists:

- for each generator: dw::OutOfFlowMgr::TBInfo::leftFloatsGB and
  dw::OutOfFlowMgr::TBInfo::rightFloatsGB;
- for the container: dw::OutOfFlowMgr::leftFloatsCB and
  dw::OutOfFlowMgr::rightFloatsCB.

The other two lists, dw::OutOfFlowMgr::leftFloatsAll and
dw::OutOfFlowMgr::rightFloatsAll are not sorted at all.

New floats are always added to the end of either list; this order is
called *generation order*. See also above: *GB lists and CB lists*.

On the other hand, there are different sorting criteria, implemented
by different comparators, so that different kinds of keys may be used
for searching. These sorting criteria are equivalent to the generation
order.

dw::OutOfFlowMgr::Float::CompareSideSpanningIndex compares
*sideSpanningIndex* (used to compare floats to those on the respective
other side); if you look at the definition
(dw::OutOfFlowMgr::addWidgetOOF) it becomes clear that this order is
equivalent to the generation order.

dw::OutOfFlowMgr::Float::CompareGBAndExtIndex compares *externalIndex*
for floats with same generators, otherwise: (i) if one generator (T1)
is a direct anchestor of the other generator (T2), the child of T1,
which is an anchestor of, or identical to, T2 is compared to the float
generated by T1, using *externalIndex*, as in this example:

    T1 -+-> child --> ... -> T2 -> Float
        `-> Float

Otherwise, the two blocks are compared, according to their position in
dw::OutOfFlowMgr::tbInfos:

    common anchestor -+-> ... --> T1 -> Float
                      `-> ... --> T2 -> Float

This is equivalent to the generation order, as long it is ensured that
*externalIndex* reflects the generation order within a generating
block, for both floats and child blocks.

dw::OutOfFlowMgr::Float::ComparePosition ...


Miscellaneous notes
===================

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:

    <body>
      <img src="....jpg" style="float:right">
      <p style="overflow:hidden">Text</p>
    </body>

Interestingly, dillo shows "Text" always *below* the image, even if
there is enough space left of it. An investigation shows that the
paragraph (&lt;p&gt;) is regarded as own floats container (because of
*overflow:hidden*), so the floats container above (&lt;body&gt;)
regards this block as widget which must be fit between the floats
(dw::Textblock::mustBorderBeRegarded &gt;
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.&nbsp;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?

<b>Real-world cases:</b> *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.&nbsp;g.
<a href="http://de.wikipedia.org/wiki/Emmerich_am_Rhein#Ans.C3.A4ssige_Unternehmen">this page</a>
and scroll a bit up; the company logos should be right of this section.

<b>Priority:</b> Since this is not a regression, compared to not
supporting floats at all, a fix is not urgent for a new release.

Resizing
--------
Has the case that a float changes its position to be regarded? Probably yes, but
cases where no other mechanisms come into play are rather unlikely.

<b>Priority:</b> If this plays a role, this means a regression compared to not
supporting floats at all.

*/