KHtml

render_block.h
1 /*
2  * This file is part of the render object implementation for KHTML.
3  *
4  * Copyright (C) 1999-2003 Lars Knoll ([email protected])
5  * (C) 1999-2003 Antti Koivisto ([email protected])
6  * (C) 2002-2003 Dirk Mueller ([email protected])
7  * (C) 2003 Apple Computer, Inc.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public License
20  * along with this library; see the file COPYING.LIB. If not, write to
21  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22  * Boston, MA 02110-1301, USA.
23  *
24  */
25 
26 #ifndef RENDER_BLOCK_H
27 #define RENDER_BLOCK_H
28 
29 #include <QList>
30 
31 #include "render_flow.h"
32 
33 namespace DOM
34 {
35 class Position;
36 }
37 
38 namespace khtml
39 {
40 
41 class RenderBlock : public RenderFlow
42 {
43 public:
44  RenderBlock(DOM::NodeImpl *node);
45  virtual ~RenderBlock();
46 
47  const char *renderName() const override;
48 
49  bool isRenderBlock() const override
50  {
51  return true;
52  }
53  bool isBlockFlow() const override
54  {
55  return (!isInline() || isReplaced()) && !isTable();
56  }
57  bool isInlineFlow() const override
58  {
59  return isInline() && !isReplaced();
60  }
61  bool isInlineBlockOrInlineTable() const override
62  {
63  return isInline() && isReplaced();
64  }
65 
66  bool childrenInline() const override
67  {
68  return m_childrenInline;
69  }
70  virtual void setChildrenInline(bool b)
71  {
72  m_childrenInline = b;
73  }
74  short baselinePosition(bool firstLine) const override;
75 
76  int getBaselineOfLastLineBox() const;
77  void makeChildrenNonInline(RenderObject *insertionPoint = nullptr);
78 
79  void makePageBreakAvoidBlocks();
80 
81  // The height (and width) of a block when you include overflow spillage out of the bottom
82  // of the block (e.g., a <div style="height:25px"> that has a 100px tall image inside
83  // it would have an overflow height of borderTop() + paddingTop() + 100px.
84  int overflowHeight() const override
85  {
86  return m_overflowHeight;
87  }
88  int overflowWidth() const override
89  {
90  return m_overflowWidth;
91  }
92  int overflowLeft() const override
93  {
94  return m_overflowLeft;
95  }
96  int overflowTop() const override
97  {
98  return m_overflowTop;
99  }
100  virtual void setOverflowHeight(int h)
101  {
102  m_overflowHeight = h;
103  }
104  virtual void setOverflowWidth(int w)
105  {
106  m_overflowWidth = w;
107  }
108  virtual void setOverflowLeft(int l)
109  {
110  m_overflowLeft = l;
111  }
112  virtual void setOverflowTop(int t)
113  {
114  m_overflowTop = t;
115  }
116 
117  bool isSelfCollapsingBlock() const override;
118  bool isTopMarginQuirk() const override
119  {
120  return m_topMarginQuirk;
121  }
122  bool isBottomMarginQuirk() const override
123  {
124  return m_bottomMarginQuirk;
125  }
126 
127  short maxTopMargin(bool positive) const override
128  {
129  if (positive) {
130  return m_maxTopPosMargin;
131  } else {
132  return m_maxTopNegMargin;
133  }
134  }
135  short maxBottomMargin(bool positive) const override
136  {
137  if (positive) {
138  return m_maxBottomPosMargin;
139  } else {
140  return m_maxBottomNegMargin;
141  }
142  }
143 
144  void initMaxMarginValues()
145  {
146  if (m_marginTop >= 0) {
147  m_maxTopPosMargin = m_marginTop;
148  } else {
149  m_maxTopNegMargin = -m_marginTop;
150  }
151  if (m_marginBottom >= 0) {
152  m_maxBottomPosMargin = m_marginBottom;
153  } else {
154  m_maxBottomNegMargin = -m_marginBottom;
155  }
156  }
157 
158  void addChildToFlow(RenderObject *newChild, RenderObject *beforeChild) override;
159  void removeChild(RenderObject *oldChild) override;
160 
161  void setStyle(RenderStyle *_style) override;
162  void attach() override;
163  void updateFirstLetter();
164 
165  void layout() override;
166  void layoutBlock(bool relayoutChildren);
167  void layoutBlockChildren(bool relayoutChildren);
168  void layoutInlineChildren(bool relayoutChildren, int breakBeforeLine = 0);
169 
170  void layoutPositionedObjects(bool relayoutChildren);
171  void insertPositionedObject(RenderObject *o);
172  void removePositionedObject(RenderObject *o);
173 
174  QRegion visibleFloatingRegion(int x, int y) const;
175  // Called to lay out the legend for a fieldset.
176  virtual RenderObject *layoutLegend(bool /*relayoutChildren*/)
177  {
178  return nullptr;
179  }
180 
181  // the implementation of the following functions is in bidi.cpp
182  void bidiReorderLine(const BidiIterator &start, const BidiIterator &end, BidiState &bidi);
183  void fitBelowFloats(int widthToFit, int &availableWidth);
184  BidiIterator findNextLineBreak(BidiIterator &start, BidiState &info);
185  RootInlineBox *constructLine(const BidiIterator &start, const BidiIterator &end);
186  InlineFlowBox *createLineBoxes(RenderObject *obj);
187  bool inlineChildNeedsLineBox(RenderObject *obj);
188  void computeHorizontalPositionsForLine(InlineFlowBox *lineBox, BidiState &bidi);
189  void computeVerticalPositionsForLine(RootInlineBox *lineBox);
190  bool clearLineOfPageBreaks(InlineFlowBox *lineBox);
191  void checkLinesForOverflow();
192  void deleteEllipsisLineBoxes();
193  void checkLinesForTextOverflow();
194  RootInlineBox *determineStartPosition(bool fullLayout, BidiIterator &start, BidiState &bidi);
195  RootInlineBox *determineEndPosition(RootInlineBox *startLine, BidiIterator &cleanLineStart, BidiStatus &cleanLineBidiStatus, BidiContext *cleanLineBidiContext, int &yPos);
196  bool matchedEndLine(const BidiIterator &start, const BidiStatus &status, BidiContext *context,
197  const BidiIterator &endLineStart, const BidiStatus &endLineStatus, BidiContext *endLineContext,
198  RootInlineBox *&endLine, int &endYPos);
199  // end bidi.cpp functions
200 
201  void paint(PaintInfo &i, int tx, int ty) override;
202  void paintObject(PaintInfo &i, int tx, int ty, bool paintOutline = true);
203  void paintFloats(PaintInfo &i, int _tx, int _ty, bool paintSelection = false);
204 
205  void insertFloatingObject(RenderObject *o);
206  void removeFloatingObject(RenderObject *o);
207 
208  // called from lineWidth, to position the floats added in the last line.
209  void positionNewFloats();
210  void clearFloats();
211  int getClearDelta(RenderObject *child, int yPos);
212  void markAllDescendantsWithFloatsForLayout(RenderObject *floatToRemove = nullptr) override;
213 
214  // FIXME: containsFloats() should not return true if the floating objects list
215  // is empty. However, layoutInlineChildren() relies on the current behavior.
216  // http://bugzilla.opendarwin.org/show_bug.cgi?id=7395#c3
217  bool hasFloats() const override
218  {
219  return m_floatingObjects != nullptr;
220  }
221  bool containsFloat(RenderObject *o) const override;
222 
223  bool hasOverhangingFloats() const override
224  {
225  return floatBottom() > m_height;
226  }
227  void addOverHangingFloats(RenderBlock *block, int xoffset, int yoffset, bool child);
228 
229  int nearestFloatBottom(int height) const;
230  int floatBottom() const;
231  inline int leftBottom();
232  inline int rightBottom();
233 
234  virtual unsigned short lineWidth(int y, bool *canClearLine = nullptr) const;
235  int lowestPosition(bool includeOverflowInterior = true, bool includeSelf = true) const override;
236  int rightmostPosition(bool includeOverflowInterior = true, bool includeSelf = true) const override;
237  int leftmostPosition(bool includeOverflowInterior = true, bool includeSelf = true) const override;
238  int highestPosition(bool includeOverflowInterior, bool includeSelf) const override;
239  int lowestAbsolutePosition() const;
240  int leftmostAbsolutePosition() const;
241  int rightmostAbsolutePosition() const;
242  int highestAbsolutePosition() const;
243 
244  int rightOffset() const;
245  int rightRelOffset(int y, int fixedOffset, bool applyTextIndent = true, int *heightRemaining = nullptr, bool *canClearLine = nullptr) const;
246  int rightOffset(int y, bool *canClearLine = nullptr) const
247  {
248  return rightRelOffset(y, rightOffset(), true, nullptr, canClearLine);
249  }
250 
251  int leftOffset() const;
252  int leftRelOffset(int y, int fixedOffset, bool applyTextIndent = true, int *heightRemaining = nullptr, bool *canClearLine = nullptr) const;
253  int leftOffset(int y, bool *canClearLine = nullptr) const
254  {
255  return leftRelOffset(y, leftOffset(), true, nullptr, canClearLine);
256  }
257 
258  bool nodeAtPoint(NodeInfo &info, int x, int y, int _tx, int _ty, HitTestAction hitTestAction = HitTestAll, bool inside = false) override;
259 
260  bool isPointInScrollbar(int x, int y, int tx, int ty);
261 
262  RenderPosition positionForCoordinates(int x, int y) override;
263 
264  void calcMinMaxWidth() override;
265  void calcInlineMinMaxWidth();
266  void calcBlockMinMaxWidth();
267 
268  void close() override;
269 
270  int getBaselineOfFirstLineBox() override;
271 
272  RootInlineBox *firstRootBox() const
273  {
274  return static_cast<RootInlineBox *>(m_firstLineBox);
275  }
276  RootInlineBox *lastRootBox() const
277  {
278  return static_cast<RootInlineBox *>(m_lastLineBox);
279  }
280 
281  InlineFlowBox *getFirstLineBox() override;
282 
283  bool inRootBlockContext() const;
284  void deleteLineBoxTree();
285 
286 #ifdef ENABLE_DUMP
287  void printTree(int indent = 0) const override;
288  void dump(QTextStream &stream, const QString &ind) const override;
289 #endif
290 
291 protected:
292  void newLine();
293 
294 private:
295  RenderPosition positionForBox(InlineBox *box, bool start = true) const;
296  RenderPosition positionForRenderer(RenderObject *renderer, bool start = true) const;
297 
298 protected:
299  struct FloatingObject {
300  enum Type {
301  FloatLeft,
302  FloatRight
303  };
304 
305  FloatingObject(Type _type)
306  {
307  node = nullptr;
308  startY = 0;
309  endY = 0;
310  type = _type;
311  left = 0;
312  width = 0;
313  noPaint = false;
314  crossedLayer = false;
315 
316  }
317  RenderObject *node;
318  int startY;
319  int endY;
320  short left;
321  short width;
322  KDE_BF_ENUM(Type) type : 1; // left or right aligned
323  bool noPaint : 1;
324  bool crossedLayer : 1; // lock noPaint flag
325  };
326 
327  // The following helper functions and structs are used by layoutBlockChildren.
328  class CompactInfo
329  {
330  // A compact child that needs to be collapsed into the margin of the following block.
331  RenderObject *m_compact;
332 
333  // The block with the open margin that the compact child is going to place itself within.
334  RenderObject *m_block;
335  bool m_treatAsBlock : 1;
336 
337  public:
338  RenderObject *compact() const
339  {
340  return m_compact;
341  }
342  RenderObject *block() const
343  {
344  return m_block;
345  }
346  void setTreatAsBlock(bool b)
347  {
348  m_treatAsBlock = b;
349  }
350  bool treatAsBlock() const
351  {
352  return m_treatAsBlock;
353  }
354  bool matches(RenderObject *child) const
355  {
356  return m_compact && m_block == child;
357  }
358 
359  void clear()
360  {
361  set(nullptr, nullptr);
362  }
363  void set(RenderObject *c, RenderObject *b)
364  {
365  m_compact = c;
366  m_block = b;
367  }
368 
369  CompactInfo()
370  {
371  clear();
372  }
373  };
374 
375  class MarginInfo
376  {
377  // Collapsing flags for whether we can collapse our margins with our children's margins.
378  bool m_canCollapseWithChildren : 1;
379  bool m_canCollapseTopWithChildren : 1;
380  bool m_canCollapseBottomWithChildren : 1;
381 
382  // Whether or not we are a quirky container, i.e., do we collapse away top and bottom
383  // margins in our container. Table cells and the body are the common examples. We
384  // also have a custom style property for Safari RSS to deal with TypePad blog articles.
385  bool m_quirkContainer : 1;
386 
387  // This flag tracks whether we are still looking at child margins that can all collapse together at the beginning of a block.
388  // They may or may not collapse with the top margin of the block (|m_canCollapseTopWithChildren| tells us that), but they will
389  // always be collapsing with one another. This variable can remain set to true through multiple iterations
390  // as long as we keep encountering self-collapsing blocks.
391  bool m_atTopOfBlock : 1;
392 
393  // This flag is set when we know we're examining bottom margins and we know we're at the bottom of the block.
394  bool m_atBottomOfBlock : 1;
395 
396  // If our last normal flow child was a self-collapsing block that cleared a float,
397  // we track it in this variable.
398  bool m_selfCollapsingBlockClearedFloat : 1;
399 
400  // These variables are used to detect quirky margins that we need to collapse away (in table cells
401  // and in the body element).
402  bool m_topQuirk : 1;
403  bool m_bottomQuirk : 1;
404  bool m_determinedTopQuirk : 1;
405 
406  // These flags track the previous maximal positive and negative margins.
407  int m_posMargin;
408  int m_negMargin;
409 
410  public:
411  MarginInfo(RenderBlock *b, int top, int bottom);
412 
413  void setAtTopOfBlock(bool b)
414  {
415  m_atTopOfBlock = b;
416  }
417  void setAtBottomOfBlock(bool b)
418  {
419  m_atBottomOfBlock = b;
420  }
421  void clearMargin()
422  {
423  m_posMargin = m_negMargin = 0;
424  }
425  void setSelfCollapsingBlockClearedFloat(bool b)
426  {
427  m_selfCollapsingBlockClearedFloat = b;
428  }
429  void setTopQuirk(bool b)
430  {
431  m_topQuirk = b;
432  }
433  void setBottomQuirk(bool b)
434  {
435  m_bottomQuirk = b;
436  }
437  void setDeterminedTopQuirk(bool b)
438  {
439  m_determinedTopQuirk = b;
440  }
441  void setPosMargin(int p)
442  {
443  m_posMargin = p;
444  }
445  void setNegMargin(int n)
446  {
447  m_negMargin = n;
448  }
449  void setPosMarginIfLarger(int p)
450  {
451  if (p > m_posMargin) {
452  m_posMargin = p;
453  }
454  }
455  void setNegMarginIfLarger(int n)
456  {
457  if (n > m_negMargin) {
458  m_negMargin = n;
459  }
460  }
461 
462  void setMargin(int p, int n)
463  {
464  m_posMargin = p;
465  m_negMargin = n;
466  }
467 
468  bool atTopOfBlock() const
469  {
470  return m_atTopOfBlock;
471  }
472  bool canCollapseWithTop() const
473  {
474  return m_atTopOfBlock && m_canCollapseTopWithChildren;
475  }
476  bool canCollapseWithBottom() const
477  {
478  return m_atBottomOfBlock && m_canCollapseBottomWithChildren;
479  }
480  bool canCollapseTopWithChildren() const
481  {
482  return m_canCollapseTopWithChildren;
483  }
484  bool canCollapseBottomWithChildren() const
485  {
486  return m_canCollapseBottomWithChildren;
487  }
488  bool selfCollapsingBlockClearedFloat() const
489  {
490  return m_selfCollapsingBlockClearedFloat;
491  }
492  bool quirkContainer() const
493  {
494  return m_quirkContainer;
495  }
496  bool determinedTopQuirk() const
497  {
498  return m_determinedTopQuirk;
499  }
500  bool topQuirk() const
501  {
502  return m_topQuirk;
503  }
504  bool bottomQuirk() const
505  {
506  return m_bottomQuirk;
507  }
508  int posMargin() const
509  {
510  return m_posMargin;
511  }
512  int negMargin() const
513  {
514  return m_negMargin;
515  }
516  int margin() const
517  {
518  return m_posMargin - m_negMargin;
519  }
520  };
521 
522  class PageBreakInfo
523  {
524  int m_pageBottom; // Next calculated page-break
525  bool m_forcePageBreak : 1; // Must break before next block
526  // ### to do better "page-break-after/before: avoid" this struct
527  // should keep a pagebreakAvoid block and gather children in it
528  public:
529  PageBreakInfo(int pageBottom) : m_pageBottom(pageBottom), m_forcePageBreak(false) {}
530  bool forcePageBreak()
531  {
532  return m_forcePageBreak;
533  }
534  void setForcePageBreak(bool b)
535  {
536  m_forcePageBreak = b;
537  }
538  int pageBottom()
539  {
540  return m_pageBottom;
541  }
542  void setPageBottom(int bottom)
543  {
544  m_pageBottom = bottom;
545  }
546  };
547 
548  bool canClear(RenderObject *child, PageBreakLevel level) override;
549  void clearPageBreak(RenderObject *child, int pageBottom);
550 
551  void adjustPositionedBlock(RenderObject *child, const MarginInfo &marginInfo);
552  void adjustFloatingBlock(const MarginInfo &marginInfo);
553  RenderObject *handleSpecialChild(RenderObject *child, const MarginInfo &marginInfo, CompactInfo &compactInfo, bool &handled);
554  RenderObject *handleFloatingChild(RenderObject *child, const MarginInfo &marginInfo, bool &handled);
555  RenderObject *handlePositionedChild(RenderObject *child, const MarginInfo &marginInfo, bool &handled);
556  RenderObject *handleCompactChild(RenderObject *child, CompactInfo &compactInfo, const MarginInfo &marginInfo, bool &handled);
557  RenderObject *handleRunInChild(RenderObject *child, bool &handled);
558  int collapseMargins(RenderObject *child, MarginInfo &marginInfo, int yPos);
559  int clearFloatsIfNeeded(RenderObject *child, MarginInfo &marginInfo, int oldTopPosMargin, int oldTopNegMargin, int yPos);
560  void adjustSizeForCompactIfNeeded(RenderObject *child, CompactInfo &compactInfo);
561  void insertCompactIfNeeded(RenderObject *child, CompactInfo &compactInfo);
562  int estimateVerticalPosition(RenderObject *child, const MarginInfo &info);
563  void determineHorizontalPosition(RenderObject *child);
564  void handleBottomOfBlock(int top, int bottom, MarginInfo &marginInfo);
565  void setCollapsedBottomMargin(const MarginInfo &marginInfo);
566  void clearChildOfPageBreaks(RenderObject *child, PageBreakInfo &pageBreakInfo, MarginInfo &marginInfo);
567  // End helper functions and structs used by layoutBlockChildren.
568 
569 protected:
570  // How much content overflows out of our block vertically or horizontally (all we support
571  // for now is spillage out of the bottom and the right, which are the common cases).
572  int m_overflowHeight;
573  int m_overflowWidth;
574 
575  // Left and top overflow.
576  int m_overflowTop;
577  int m_overflowLeft;
578 
579  QList<FloatingObject *> *m_floatingObjects;
580  QList<RenderObject *> *m_positionedObjects;
581 
582 private:
583  bool m_childrenInline : 1;
584  bool m_firstLine : 1; // used in inline layouting
585  KDE_BF_ENUM(EClear) m_clearStatus : 2; // used during layuting of paragraphs
586  bool m_avoidPageBreak : 1; // anonymous avoid page-break block
587  bool m_topMarginQuirk : 1;
588  bool m_bottomMarginQuirk : 1;
589 
590  short m_maxTopPosMargin;
591  short m_maxTopNegMargin;
592  short m_maxBottomPosMargin;
593  short m_maxBottomNegMargin;
594 
595 };
596 
597 } // namespace
598 
599 #endif // RENDER_BLOCK_H
600 
This file is part of the HTML rendering engine for KDE.
const QList< QKeySequence > & close()
QTextStream & left(QTextStream &stream)
Type type(const QSqlDatabase &db)
This library provides a full-featured HTML parser and widget.
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Tue Oct 26 2021 22:48:06 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.