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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
|
#ifndef __DW_OUTOFFLOWMGR_HH__
#define __DW_OUTOFFLOWMGR_HH__
#include "core.hh"
namespace dw {
class Textblock;
/**
* \brief Represents additional data for containing blocks.
*/
class OutOfFlowMgr
{
private:
enum Side { LEFT, RIGHT };
Textblock *containingBlock;
// These two values are set by sizeAllocateStart(), and they are
// accessable also within sizeAllocateEnd(), and also for the
// containing block, for which allocation and WAS_ALLOCATED is set
// *after* sizeAllocateEnd(). See the two inline functions below
// for usage.
core::Allocation containingBlockAllocation;
bool containingBlockWasAllocated;
class Float: public lout::object::Comparable
{
private:
OutOfFlowMgr *oofm;
public:
class CompareSideSpanningIndex: public lout::object::Comparator
{
int compare(Object *o1, Object *o2);
};
class CompareGBAndExtIndex: public lout::object::Comparator
{
private:
OutOfFlowMgr *oofm;
public:
CompareGBAndExtIndex (OutOfFlowMgr *oofm) { this->oofm = oofm; }
int compare(Object *o1, Object *o2);
};
core::Widget *widget;
Textblock *generatingBlock;
int externalIndex;
int yReq, yReal; // relative to generator, not container
int index; /* When GB is not yet allocated: position
within TBInfo::leftFloatsGB or
TBInfo::rightFloatsGB, respectively. When GB
is allocated: position within leftFloatsCB
or rightFloatsCB, respectively, even when
the floats are still elements of
TBInfo::*FloatsGB. */
int sideSpanningIndex, mark;
core::Requisition size;
bool dirty;
bool inCBList; /* Neccessary to prevent floats from being moved
twice from GB to CB list. */
Float (OutOfFlowMgr *oofm, core::Widget *widget,
Textblock *generatingBlock, int externalIndex);
void intoStringBuffer(lout::misc::StringBuffer *sb);
int compareTo(Comparable *other);
int yForTextblock (Textblock *textblock, int y);
inline int yForTextblock (Textblock *textblock)
{ return yForTextblock (textblock, yReal); }
int yForContainer (int y);
inline int yForContainer () { return yForContainer (yReal); }
bool covers (Textblock *textblock, int y, int h);
};
/**
* This list is kept sorted.
*
* To prevent accessing methods of the base class in an
* uncontrolled way, the inheritance is private, not public; this
* means that all methods must be delegated (see iterator(), size()
* etc. below.)
*
* TODO Update comment: still sorted, but ...
*
* More: add() and change() may check order again.
*/
class SortedFloatsVector: private lout::container::typed::Vector<Float>
{
public:
enum Type { GB, CB } type;
private:
OutOfFlowMgr *oofm;
Side side;
public:
inline SortedFloatsVector (OutOfFlowMgr *oofm, Side side, Type type) :
lout::container::typed::Vector<Float> (1, false)
{ this->oofm = oofm; this->side = side; this->type = type; }
int findFloatIndex (Textblock *lastGB, int lastExtIndex);
int find (Textblock *textblock, int y, int start, int end);
int findFirst (Textblock *textblock, int y, int h, Textblock *lastGB,
int lastExtIndex);
int findLastBeforeSideSpanningIndex (int sideSpanningIndex);
void put (Float *vloat);
inline lout::container::typed::Iterator<Float> iterator()
{ return lout::container::typed::Vector<Float>::iterator (); }
inline int size ()
{ return lout::container::typed::Vector<Float>::size (); }
inline Float *get (int pos)
{ return lout::container::typed::Vector<Float>::get (pos); }
inline void clear ()
{ lout::container::typed::Vector<Float>::clear (); }
};
class TBInfo: public lout::object::Object
{
public:
bool wasAllocated;
int xCB, yCB; // relative to the containing block
int width, height;
int index; // position within "tbInfos"
Textblock *textblock; // for debugging; may be removed again
TBInfo *parent;
int parentExtIndex;
// These two lists store all floats generated by this textblock,
// as long as this textblock is not allocates.
SortedFloatsVector *leftFloatsGB, *rightFloatsGB;
TBInfo (OutOfFlowMgr *oofm, Textblock *textblock,
TBInfo *parent, int parentExtIndex);
~TBInfo ();
};
class AbsolutelyPositioned: public lout::object::Object
{
public:
core::Widget *widget;
int xCB, yCB; // relative to the containing block
int width, height;
bool dirty;
AbsolutelyPositioned (OutOfFlowMgr *oofm, core::Widget *widget,
Textblock *generatingBlock, int externalIndex);
};
// These two lists store all floats, in the order in which they are
// defined. Only used for iterators.
lout::container::typed::Vector<Float> *leftFloatsAll, *rightFloatsAll;
// These two lists store all floats whose generators are already
// allocated.
SortedFloatsVector *leftFloatsCB, *rightFloatsCB;
lout::container::typed::HashTable<lout::object::TypedPointer
<dw::core::Widget>, Float> *floatsByWidget;
lout::container::typed::Vector<TBInfo> *tbInfos;
lout::container::typed::HashTable<lout::object::TypedPointer <Textblock>,
TBInfo> *tbInfosByTextblock;
lout::container::typed::Vector<AbsolutelyPositioned> *absolutelyPositioned;
int lastLeftTBIndex, lastRightTBIndex, leftFloatsMark, rightFloatsMark;
/**
* Variant of Widget::wasAllocated(), which can also be used within
* OOFM::sizeAllocateEnd(), and also for the generating block.
*/
inline bool wasAllocated (core::Widget *widget) {
return widget->wasAllocated () ||
(widget == (core::Widget*)containingBlock &&
containingBlockWasAllocated); }
/**
* Variant of Widget::getAllocation(), which can also be used
* within OOFM::sizeAllocateEnd(), and also for the generating
* block.
*/
inline core::Allocation *getAllocation (core::Widget *widget) {
return widget == (core::Widget*)containingBlock ?
&containingBlockAllocation : widget->getAllocation (); }
void moveExternalIndices (SortedFloatsVector *list, int oldStartIndex,
int diff);
Float *findFloatByWidget (core::Widget *widget);
void moveFromGBToCB (Side side);
void sizeAllocateFloats (Side side);
bool isTextblockCoveredByFloats (Textblock *tb, int tbx, int tby,
int tbWidth, int tbHeight, int *floatPos,
core::Widget **vloat);
bool isTextblockCoveredByFloats (SortedFloatsVector *list, Textblock *tb,
int tbx, int tby, int tbWidth, int tbHeight,
int *floatPos, core::Widget **vloat);
void drawFloats (SortedFloatsVector *list, core::View *view,
core::Rectangle *area);
void drawAbsolutelyPositioned (core::View *view, core::Rectangle *area);
core::Widget *getFloatWidgetAtPoint (SortedFloatsVector *list, int x, int y,
int level);
core::Widget *getAbsolutelyPositionedWidgetAtPoint (int x, int y, int level);
bool collides (Float *vloat, Float *other, int *yReal);
void checkCoverage (Float *vloat, int oldY);
void getFloatsLists (Float *vloat, SortedFloatsVector **listSame,
SortedFloatsVector **listOpp);
int getFloatsSize (SortedFloatsVector *list);
void accumExtremes (SortedFloatsVector *list, int *oofMinWidth,
int *oofMaxWidth);
TBInfo *getTextblock (Textblock *textblock);
int getBorder (Textblock *textblock, Side side, int y, int h,
Textblock *lastGB, int lastExtIndex);
SortedFloatsVector *getFloatsListForTextblock (Textblock *textblock,
Side side);
bool hasFloat (Textblock *textblock, Side side, int y, int h,
Textblock *lastGB, int lastExtIndex);
void ensureFloatSize (Float *vloat);
int getBorderDiff (Textblock *textblock, Float *vloat, Side side);
void tellFloatPosition (core::Widget *widget, int yReq);
void getAbsolutelyPositionedSize (int *oofWidthAbsPos, int *oofHeightAbsPos);
void ensureAbsolutelyPositionedSizeAndPosition (AbsolutelyPositioned
*abspos);
int calcValueForAbsolutelyPositioned (AbsolutelyPositioned *abspos,
core::style::Length styleLen,
int refLen);
void sizeAllocateAbsolutelyPositioned ();
static inline bool isWidgetFloat (core::Widget *widget)
{ return widget->getStyle()->vloat != core::style::FLOAT_NONE; }
static inline bool isWidgetAbsolutelyPositioned (core::Widget *widget)
{ return widget->getStyle()->position == core::style::POSITION_ABSOLUTE; }
/*
* Format for parent ref (see also below for isRefOutOfFlow,
* createRefNormalFlow, and getLineNoFromRef.
*
* Widget in flow:
*
* +---+ - - - +---+---+- - - - - -+---+---+---+---+
* | line number | 0 |
* +---+ - - - +---+---+- - - - - -+---+---+---+---+
*
* So, anything with the least signifant bit set to 1 is out of flow.
*
* Floats:
*
* +---+ - - - +---+---+- - - - - -+---+---+---+---+
* | left float index | 0 | 0 | 1 |
* +---+ - - - +---+---+- - - - - -+---+---+---+---+
*
* +---+ - - - +---+---+- - - - - -+---+---+---+---+
* | right float index | 1 | 0 | 1 |
* +---+ - - - +---+---+- - - - - -+---+---+---+---+
*
* Absolutely positioned blocks:
*
* +---+ - - - +---+---+- - - - - -+---+---+---+---+
* | index | 1 | 1 |
* +---+ - - - +---+---+- - - - - -+---+---+---+---+
*/
inline static bool isRefFloat (int ref)
{ return ref != -1 && (ref & 3) == 1; }
inline static bool isRefLeftFloat (int ref)
{ return ref != -1 && (ref & 7) == 1; }
inline static bool isRefRightFloat (int ref)
{ return ref != -1 && (ref & 7) == 5; }
inline static bool isRefAbsolutelyPositioned (int ref)
{ return ref != -1 && (ref & 3) == 3; }
inline static int createRefLeftFloat (int index)
{ return (index << 3) | 1; }
inline static int createRefRightFloat (int index)
{ return (index << 3) | 5; }
inline static int createRefAbsolutelyPositioned (int index)
{ return (index << 2) | 3; }
inline static int getFloatIndexFromRef (int ref)
{ return ref == -1 ? ref : (ref >> 3); }
inline static int getAbsolutelyPositionedIndexFromRef (int ref)
{ return ref == -1 ? ref : (ref >> 2); }
public:
OutOfFlowMgr (Textblock *containingBlock);
~OutOfFlowMgr ();
void sizeAllocateStart (core::Allocation *containingBlockAllocation);
void sizeAllocateEnd ();
void draw (core::View *view, core::Rectangle *area);
void markSizeChange (int ref);
void markExtremesChange (int ref);
core::Widget *getWidgetAtPoint (int x, int y, int level);
static bool isWidgetOutOfFlow (core::Widget *widget);
void addWidgetInFlow (Textblock *textblock, Textblock *parentBlock,
int externalIndex);
void addWidgetOOF (core::Widget *widget, Textblock *generatingBlock,
int externalIndex);
void moveExternalIndices (Textblock *generatingBlock, int oldStartIndex,
int diff);
void tellPosition (core::Widget *widget, int yReq);
void getSize (int cbWidth, int cbHeight, int *oofWidth, int *oofHeight);
void getExtremes (int cbMinWidth, int cbMaxWidth, int *oofMinWidth,
int *oofMaxWidth);
int getLeftBorder (Textblock *textblock, int y, int h, Textblock *lastGB,
int lastExtIndex);
int getRightBorder (Textblock *textblock, int y, int h, Textblock *lastGB,
int lastExtIndex);
bool hasFloatLeft (Textblock *textblock, int y, int h, Textblock *lastGB,
int lastExtIndex);
bool hasFloatRight (Textblock *textblock, int y, int h, Textblock *lastGB,
int lastExtIndex);
inline static bool isRefOutOfFlow (int ref)
{ return ref != -1 && (ref & 1) != 0; }
inline static int createRefNormalFlow (int lineNo) { return lineNo << 1; }
inline static int getLineNoFromRef (int ref)
{ return ref == -1 ? ref : (ref >> 1); }
// for iterators
inline int getNumWidgets () {
return leftFloatsAll->size() + rightFloatsAll->size() +
absolutelyPositioned->size(); }
inline core::Widget *getWidget (int i) {
if (i < leftFloatsAll->size())
return leftFloatsAll->get(i)->widget;
else if (i < leftFloatsAll->size() + rightFloatsAll->size())
return rightFloatsAll->get(i - leftFloatsAll->size())->widget;
else
return absolutelyPositioned->get(i - (leftFloatsAll->size() +
rightFloatsAll->size()))->widget;
}
};
} // namespace dw
#endif // __DW_OUTOFFLOWMGR_HH__
|