InlineFlowBox.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. /*
  2. * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
  3. *
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Library General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2 of the License, or (at your option) any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Library General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Library General Public License
  15. * along with this library; see the file COPYING.LIB. If not, write to
  16. * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  17. * Boston, MA 02110-1301, USA.
  18. *
  19. */
  20. #ifndef InlineFlowBox_h
  21. #define InlineFlowBox_h
  22. #include "InlineBox.h"
  23. #include "RenderOverflow.h"
  24. #include "ShadowData.h"
  25. namespace WebCore {
  26. class HitTestRequest;
  27. class HitTestResult;
  28. class InlineTextBox;
  29. class RenderLineBoxList;
  30. class SimpleFontData;
  31. class VerticalPositionCache;
  32. struct GlyphOverflow;
  33. typedef HashMap<const InlineTextBox*, pair<Vector<const SimpleFontData*>, GlyphOverflow> > GlyphOverflowAndFallbackFontsMap;
  34. class InlineFlowBox : public InlineBox {
  35. public:
  36. InlineFlowBox(RenderObject* obj)
  37. : InlineBox(obj)
  38. , m_firstChild(0)
  39. , m_lastChild(0)
  40. , m_prevLineBox(0)
  41. , m_nextLineBox(0)
  42. , m_includeLogicalLeftEdge(false)
  43. , m_includeLogicalRightEdge(false)
  44. , m_descendantsHaveSameLineHeightAndBaseline(true)
  45. , m_baselineType(AlphabeticBaseline)
  46. , m_hasAnnotationsBefore(false)
  47. , m_hasAnnotationsAfter(false)
  48. #ifndef NDEBUG
  49. , m_hasBadChildList(false)
  50. #endif
  51. {
  52. // Internet Explorer and Firefox always create a marker for list items, even when the list-style-type is none. We do not make a marker
  53. // in the list-style-type: none case, since it is wasteful to do so. However, in order to match other browsers we have to pretend like
  54. // an invisible marker exists. The side effect of having an invisible marker is that the quirks mode behavior of shrinking lines with no
  55. // text children must not apply. This change also means that gaps will exist between image bullet list items. Even when the list bullet
  56. // is an image, the line is still considered to be immune from the quirk.
  57. m_hasTextChildren = obj->style()->display() == LIST_ITEM;
  58. m_hasTextDescendants = m_hasTextChildren;
  59. }
  60. #ifndef NDEBUG
  61. virtual ~InlineFlowBox();
  62. virtual void showLineTreeAndMark(const InlineBox* = 0, const char* = 0, const InlineBox* = 0, const char* = 0, const RenderObject* = 0, int = 0) const;
  63. virtual const char* boxName() const;
  64. #endif
  65. InlineFlowBox* prevLineBox() const { return m_prevLineBox; }
  66. InlineFlowBox* nextLineBox() const { return m_nextLineBox; }
  67. void setNextLineBox(InlineFlowBox* n) { m_nextLineBox = n; }
  68. void setPreviousLineBox(InlineFlowBox* p) { m_prevLineBox = p; }
  69. InlineBox* firstChild() const { checkConsistency(); return m_firstChild; }
  70. InlineBox* lastChild() const { checkConsistency(); return m_lastChild; }
  71. virtual bool isLeaf() const FINAL { return false; }
  72. InlineBox* firstLeafChild() const;
  73. InlineBox* lastLeafChild() const;
  74. typedef void (*CustomInlineBoxRangeReverse)(void* userData, Vector<InlineBox*>::iterator first, Vector<InlineBox*>::iterator last);
  75. void collectLeafBoxesInLogicalOrder(Vector<InlineBox*>&, CustomInlineBoxRangeReverse customReverseImplementation = 0, void* userData = 0) const;
  76. virtual void setConstructed() FINAL
  77. {
  78. InlineBox::setConstructed();
  79. for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
  80. child->setConstructed();
  81. }
  82. void addToLine(InlineBox* child);
  83. virtual void deleteLine(RenderArena*) FINAL;
  84. virtual void extractLine() FINAL;
  85. virtual void attachLine() FINAL;
  86. virtual void adjustPosition(float dx, float dy);
  87. virtual void extractLineBoxFromRenderObject();
  88. virtual void attachLineBoxToRenderObject();
  89. virtual void removeLineBoxFromRenderObject();
  90. virtual void clearTruncation() OVERRIDE;
  91. IntRect roundedFrameRect() const;
  92. virtual void paintBoxDecorations(PaintInfo&, const LayoutPoint&) FINAL;
  93. virtual void paintMask(PaintInfo&, const LayoutPoint&) FINAL;
  94. void paintFillLayers(const PaintInfo&, const Color&, const FillLayer*, const LayoutRect&, CompositeOperator = CompositeSourceOver);
  95. void paintFillLayer(const PaintInfo&, const Color&, const FillLayer*, const LayoutRect&, CompositeOperator = CompositeSourceOver);
  96. void paintBoxShadow(const PaintInfo&, RenderStyle*, ShadowStyle, const LayoutRect&);
  97. virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom);
  98. virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom) OVERRIDE;
  99. bool boxShadowCanBeAppliedToBackground(const FillLayer&) const;
  100. virtual RenderLineBoxList* rendererLineBoxes() const;
  101. // logicalLeft = left in a horizontal line and top in a vertical line.
  102. LayoutUnit marginBorderPaddingLogicalLeft() const { return marginLogicalLeft() + borderLogicalLeft() + paddingLogicalLeft(); }
  103. LayoutUnit marginBorderPaddingLogicalRight() const { return marginLogicalRight() + borderLogicalRight() + paddingLogicalRight(); }
  104. LayoutUnit marginLogicalLeft() const
  105. {
  106. if (!includeLogicalLeftEdge())
  107. return 0;
  108. return isHorizontal() ? boxModelObject()->marginLeft() : boxModelObject()->marginTop();
  109. }
  110. LayoutUnit marginLogicalRight() const
  111. {
  112. if (!includeLogicalRightEdge())
  113. return 0;
  114. return isHorizontal() ? boxModelObject()->marginRight() : boxModelObject()->marginBottom();
  115. }
  116. int borderLogicalLeft() const
  117. {
  118. if (!includeLogicalLeftEdge())
  119. return 0;
  120. return isHorizontal() ? renderer()->style(isFirstLineStyle())->borderLeftWidth() : renderer()->style(isFirstLineStyle())->borderTopWidth();
  121. }
  122. int borderLogicalRight() const
  123. {
  124. if (!includeLogicalRightEdge())
  125. return 0;
  126. return isHorizontal() ? renderer()->style(isFirstLineStyle())->borderRightWidth() : renderer()->style(isFirstLineStyle())->borderBottomWidth();
  127. }
  128. int paddingLogicalLeft() const
  129. {
  130. if (!includeLogicalLeftEdge())
  131. return 0;
  132. return isHorizontal() ? boxModelObject()->paddingLeft() : boxModelObject()->paddingTop();
  133. }
  134. int paddingLogicalRight() const
  135. {
  136. if (!includeLogicalRightEdge())
  137. return 0;
  138. return isHorizontal() ? boxModelObject()->paddingRight() : boxModelObject()->paddingBottom();
  139. }
  140. bool includeLogicalLeftEdge() const { return m_includeLogicalLeftEdge; }
  141. bool includeLogicalRightEdge() const { return m_includeLogicalRightEdge; }
  142. void setEdges(bool includeLeft, bool includeRight)
  143. {
  144. m_includeLogicalLeftEdge = includeLeft;
  145. m_includeLogicalRightEdge = includeRight;
  146. }
  147. // Helper functions used during line construction and placement.
  148. void determineSpacingForFlowBoxes(bool lastLine, bool isLogicallyLastRunWrapped, RenderObject* logicallyLastRunRenderer);
  149. LayoutUnit getFlowSpacingLogicalWidth();
  150. float placeBoxesInInlineDirection(float logicalLeft, bool& needsWordSpacing, GlyphOverflowAndFallbackFontsMap&);
  151. float placeBoxRangeInInlineDirection(InlineBox* firstChild, InlineBox* lastChild, float& logicalLeft, float& minLogicalLeft, float& maxLogicalRight, bool& needsWordSpacing, GlyphOverflowAndFallbackFontsMap&);
  152. void beginPlacingBoxRangesInInlineDirection(float logicalLeft) { setLogicalLeft(logicalLeft); }
  153. void endPlacingBoxRangesInInlineDirection(float logicalLeft, float logicalRight, float minLogicalLeft, float maxLogicalRight)
  154. {
  155. setLogicalWidth(logicalRight - logicalLeft);
  156. if (knownToHaveNoOverflow() && (minLogicalLeft < logicalLeft || maxLogicalRight > logicalRight))
  157. clearKnownToHaveNoOverflow();
  158. }
  159. void computeLogicalBoxHeights(RootInlineBox*, LayoutUnit& maxPositionTop, LayoutUnit& maxPositionBottom,
  160. int& maxAscent, int& maxDescent, bool& setMaxAscent, bool& setMaxDescent,
  161. bool strictMode, GlyphOverflowAndFallbackFontsMap&, FontBaseline, VerticalPositionCache&);
  162. void adjustMaxAscentAndDescent(int& maxAscent, int& maxDescent,
  163. int maxPositionTop, int maxPositionBottom);
  164. void placeBoxesInBlockDirection(LayoutUnit logicalTop, LayoutUnit maxHeight, int maxAscent, bool strictMode, LayoutUnit& lineTop, LayoutUnit& lineBottom, bool& setLineTop,
  165. LayoutUnit& lineTopIncludingMargins, LayoutUnit& lineBottomIncludingMargins, bool& hasAnnotationsBefore, bool& hasAnnotationsAfter, FontBaseline);
  166. void flipLinesInBlockDirection(LayoutUnit lineTop, LayoutUnit lineBottom);
  167. bool requiresIdeographicBaseline(const GlyphOverflowAndFallbackFontsMap&) const;
  168. LayoutUnit computeOverAnnotationAdjustment(LayoutUnit allowedPosition) const;
  169. LayoutUnit computeUnderAnnotationAdjustment(LayoutUnit allowedPosition) const;
  170. void computeOverflow(LayoutUnit lineTop, LayoutUnit lineBottom, GlyphOverflowAndFallbackFontsMap&);
  171. void removeChild(InlineBox* child);
  172. virtual RenderObject::SelectionState selectionState();
  173. virtual bool canAccommodateEllipsis(bool ltr, int blockEdge, int ellipsisWidth) const OVERRIDE FINAL;
  174. virtual float placeEllipsisBox(bool ltr, float blockLeftEdge, float blockRightEdge, float ellipsisWidth, float &truncatedWidth, bool&) OVERRIDE;
  175. bool hasTextChildren() const { return m_hasTextChildren; }
  176. bool hasTextDescendants() const { return m_hasTextDescendants; }
  177. void setHasTextChildren() { m_hasTextChildren = true; setHasTextDescendants(); }
  178. void setHasTextDescendants() { m_hasTextDescendants = true; }
  179. void checkConsistency() const;
  180. void setHasBadChildList();
  181. // Line visual and layout overflow are in the coordinate space of the block. This means that they aren't purely physical directions.
  182. // For horizontal-tb and vertical-lr they will match physical directions, but for horizontal-bt and vertical-rl, the top/bottom and left/right
  183. // respectively are flipped when compared to their physical counterparts. For example minX is on the left in vertical-lr, but it is on the right in vertical-rl.
  184. LayoutRect layoutOverflowRect(LayoutUnit lineTop, LayoutUnit lineBottom) const
  185. {
  186. return m_overflow ? m_overflow->layoutOverflowRect() : enclosingLayoutRect(frameRectIncludingLineHeight(lineTop, lineBottom));
  187. }
  188. LayoutUnit logicalTopLayoutOverflow(LayoutUnit lineTop) const
  189. {
  190. if (m_overflow)
  191. return isHorizontal() ? m_overflow->layoutOverflowRect().y() : m_overflow->layoutOverflowRect().x();
  192. return lineTop;
  193. }
  194. LayoutUnit logicalBottomLayoutOverflow(LayoutUnit lineBottom) const
  195. {
  196. if (m_overflow)
  197. return isHorizontal() ? m_overflow->layoutOverflowRect().maxY() : m_overflow->layoutOverflowRect().maxX();
  198. return lineBottom;
  199. }
  200. LayoutRect logicalLayoutOverflowRect(LayoutUnit lineTop, LayoutUnit lineBottom) const
  201. {
  202. LayoutRect result = layoutOverflowRect(lineTop, lineBottom);
  203. if (!renderer()->isHorizontalWritingMode())
  204. result = result.transposedRect();
  205. return result;
  206. }
  207. LayoutRect visualOverflowRect(LayoutUnit lineTop, LayoutUnit lineBottom) const
  208. {
  209. return m_overflow ? m_overflow->visualOverflowRect() : enclosingLayoutRect(frameRectIncludingLineHeight(lineTop, lineBottom));
  210. }
  211. LayoutUnit logicalLeftVisualOverflow() const { return m_overflow ? (isHorizontal() ? m_overflow->visualOverflowRect().x() : m_overflow->visualOverflowRect().y()) : static_cast<LayoutUnit>(logicalLeft()); }
  212. LayoutUnit logicalRightVisualOverflow() const { return m_overflow ? (isHorizontal() ? m_overflow->visualOverflowRect().maxX() : m_overflow->visualOverflowRect().maxY()) : static_cast<LayoutUnit>(ceilf(logicalRight())); }
  213. LayoutUnit logicalTopVisualOverflow(LayoutUnit lineTop) const
  214. {
  215. if (m_overflow)
  216. return isHorizontal() ? m_overflow->visualOverflowRect().y() : m_overflow->visualOverflowRect().x();
  217. return lineTop;
  218. }
  219. LayoutUnit logicalBottomVisualOverflow(LayoutUnit lineBottom) const
  220. {
  221. if (m_overflow)
  222. return isHorizontal() ? m_overflow->visualOverflowRect().maxY() : m_overflow->visualOverflowRect().maxX();
  223. return lineBottom;
  224. }
  225. LayoutRect logicalVisualOverflowRect(LayoutUnit lineTop, LayoutUnit lineBottom) const
  226. {
  227. LayoutRect result = visualOverflowRect(lineTop, lineBottom);
  228. if (!renderer()->isHorizontalWritingMode())
  229. result = result.transposedRect();
  230. return result;
  231. }
  232. void setOverflowFromLogicalRects(const LayoutRect& logicalLayoutOverflow, const LayoutRect& logicalVisualOverflow, LayoutUnit lineTop, LayoutUnit lineBottom);
  233. void setLayoutOverflow(const LayoutRect&, LayoutUnit lineTop, LayoutUnit lineBottom);
  234. void setVisualOverflow(const LayoutRect&, LayoutUnit lineTop, LayoutUnit lineBottom);
  235. FloatRect frameRectIncludingLineHeight(LayoutUnit lineTop, LayoutUnit lineBottom) const
  236. {
  237. if (isHorizontal())
  238. return FloatRect(m_topLeft.x(), lineTop, width(), lineBottom - lineTop);
  239. return FloatRect(lineTop, m_topLeft.y(), lineBottom - lineTop, height());
  240. }
  241. FloatRect logicalFrameRectIncludingLineHeight(LayoutUnit lineTop, LayoutUnit lineBottom) const
  242. {
  243. return FloatRect(logicalLeft(), lineTop, logicalWidth(), lineBottom - lineTop);
  244. }
  245. bool descendantsHaveSameLineHeightAndBaseline() const { return m_descendantsHaveSameLineHeightAndBaseline; }
  246. void clearDescendantsHaveSameLineHeightAndBaseline()
  247. {
  248. m_descendantsHaveSameLineHeightAndBaseline = false;
  249. if (parent() && parent()->descendantsHaveSameLineHeightAndBaseline())
  250. parent()->clearDescendantsHaveSameLineHeightAndBaseline();
  251. }
  252. private:
  253. void addBoxShadowVisualOverflow(LayoutRect& logicalVisualOverflow);
  254. void addBorderOutsetVisualOverflow(LayoutRect& logicalVisualOverflow);
  255. void addTextBoxVisualOverflow(InlineTextBox*, GlyphOverflowAndFallbackFontsMap&, LayoutRect& logicalVisualOverflow);
  256. void addReplacedChildOverflow(const InlineBox*, LayoutRect& logicalLayoutOverflow, LayoutRect& logicalVisualOverflow);
  257. void constrainToLineTopAndBottomIfNeeded(LayoutRect&) const;
  258. protected:
  259. OwnPtr<RenderOverflow> m_overflow;
  260. virtual bool isInlineFlowBox() const FINAL { return true; }
  261. InlineBox* m_firstChild;
  262. InlineBox* m_lastChild;
  263. InlineFlowBox* m_prevLineBox; // The previous box that also uses our RenderObject
  264. InlineFlowBox* m_nextLineBox; // The next box that also uses our RenderObject
  265. #if ENABLE(CSS3_TEXT)
  266. // Maximum logicalTop among all children of an InlineFlowBox. Used to
  267. // calculate the offset for TextUnderlinePositionUnder.
  268. void computeMaxLogicalTop(float& maxLogicalTop) const;
  269. #endif // CSS3_TEXT
  270. private:
  271. unsigned m_includeLogicalLeftEdge : 1;
  272. unsigned m_includeLogicalRightEdge : 1;
  273. unsigned m_hasTextChildren : 1;
  274. unsigned m_hasTextDescendants : 1;
  275. unsigned m_descendantsHaveSameLineHeightAndBaseline : 1;
  276. protected:
  277. // The following members are only used by RootInlineBox but moved here to keep the bits packed.
  278. // Whether or not this line uses alphabetic or ideographic baselines by default.
  279. unsigned m_baselineType : 1; // FontBaseline
  280. // If the line contains any ruby runs, then this will be true.
  281. unsigned m_hasAnnotationsBefore : 1;
  282. unsigned m_hasAnnotationsAfter : 1;
  283. unsigned m_lineBreakBidiStatusEor : 5; // WTF::Unicode::Direction
  284. unsigned m_lineBreakBidiStatusLastStrong : 5; // WTF::Unicode::Direction
  285. unsigned m_lineBreakBidiStatusLast : 5; // WTF::Unicode::Direction
  286. // End of RootInlineBox-specific members.
  287. #ifndef NDEBUG
  288. private:
  289. unsigned m_hasBadChildList : 1;
  290. #endif
  291. };
  292. inline InlineFlowBox* toInlineFlowBox(InlineBox* object)
  293. {
  294. ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isInlineFlowBox());
  295. return static_cast<InlineFlowBox*>(object);
  296. }
  297. inline const InlineFlowBox* toInlineFlowBox(const InlineBox* object)
  298. {
  299. ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isInlineFlowBox());
  300. return static_cast<const InlineFlowBox*>(object);
  301. }
  302. // This will catch anyone doing an unnecessary cast.
  303. void toInlineFlowBox(const InlineFlowBox*);
  304. #ifdef NDEBUG
  305. inline void InlineFlowBox::checkConsistency() const
  306. {
  307. }
  308. #endif
  309. inline void InlineFlowBox::setHasBadChildList()
  310. {
  311. #ifndef NDEBUG
  312. m_hasBadChildList = true;
  313. #endif
  314. }
  315. } // namespace WebCore
  316. #ifndef NDEBUG
  317. // Outside the WebCore namespace for ease of invocation from gdb.
  318. void showTree(const WebCore::InlineFlowBox*);
  319. #endif
  320. #endif // InlineFlowBox_h