Move parseFontFaceDescriptor to CSSPropertyParser.cpp
[chromium-blink-merge.git] / third_party / WebKit / Source / core / layout / line / InlineBox.cpp
blob7a1e4a9c9f05f9a2b625e7645968ab4ae0ee3348
1 /*
2 * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
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.
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.
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.
20 #include "config.h"
21 #include "core/layout/line/InlineBox.h"
23 #include "core/layout/HitTestLocation.h"
24 #include "core/layout/LayoutBlockFlow.h"
25 #include "core/layout/LayoutObject.h"
26 #include "core/layout/line/InlineFlowBox.h"
27 #include "core/layout/line/RootInlineBox.h"
28 #include "core/paint/BlockPainter.h"
29 #include "core/paint/PaintInfo.h"
30 #include "platform/fonts/FontMetrics.h"
31 #include "wtf/Partitions.h"
33 #ifndef NDEBUG
34 #include <stdio.h>
35 #endif
37 namespace blink {
39 struct SameSizeAsInlineBox {
40 virtual ~SameSizeAsInlineBox() { }
41 void* a[4];
42 LayoutPoint b;
43 LayoutUnit c;
44 uint32_t d : 32;
45 #if ENABLE(ASSERT)
46 bool f;
47 #endif
50 static_assert(sizeof(InlineBox) == sizeof(SameSizeAsInlineBox), "InlineBox should stay small");
52 #if ENABLE(ASSERT)
54 InlineBox::~InlineBox()
56 if (!m_hasBadParent && m_parent)
57 m_parent->setHasBadChildList();
60 #endif
62 void InlineBox::destroy()
64 // We do not need to issue invalidations if the page is being destroyed
65 // since these objects will never be repainted.
66 if (!m_layoutObject.documentBeingDestroyed())
67 m_layoutObject.invalidateDisplayItemClient(*this);
68 delete this;
71 void InlineBox::remove(MarkLineBoxes markLineBoxes)
73 if (parent())
74 parent()->removeChild(this, markLineBoxes);
77 void* InlineBox::operator new(size_t sz)
79 return partitionAlloc(WTF::Partitions::layoutPartition(), sz);
82 void InlineBox::operator delete(void* ptr)
84 partitionFree(ptr);
87 const char* InlineBox::boxName() const
89 return "InlineBox";
92 String InlineBox::debugName() const
94 return boxName();
97 #ifndef NDEBUG
98 void InlineBox::showTreeForThis() const
100 layoutObject().showTreeForThis();
103 void InlineBox::showLineTreeForThis() const
105 layoutObject().containingBlock()->showLineTreeAndMark(this, "*");
108 void InlineBox::showLineTreeAndMark(const InlineBox* markedBox1, const char* markedLabel1, const InlineBox* markedBox2, const char* markedLabel2, const LayoutObject* obj, int depth) const
110 int printedCharacters = 0;
111 if (this == markedBox1)
112 printedCharacters += fprintf(stderr, "%s", markedLabel1);
113 if (this == markedBox2)
114 printedCharacters += fprintf(stderr, "%s", markedLabel2);
115 if (&layoutObject() == obj)
116 printedCharacters += fprintf(stderr, "*");
117 for (; printedCharacters < depth * 2; printedCharacters++)
118 fputc(' ', stderr);
120 showBox(printedCharacters);
123 void InlineBox::showBox(int printedCharacters) const
125 printedCharacters += fprintf(stderr, "%s %p", boxName(), this);
126 for (; printedCharacters < showTreeCharacterOffset; printedCharacters++)
127 fputc(' ', stderr);
128 fprintf(stderr, "\t%s %p {pos=%g,%g size=%g,%g} baseline=%i/%i\n",
129 layoutObject().decoratedName().ascii().data(), &layoutObject(),
130 x().toFloat(), y().toFloat(), width().toFloat(), height().toFloat(),
131 baselinePosition(AlphabeticBaseline), baselinePosition(IdeographicBaseline));
133 #endif
135 LayoutUnit InlineBox::logicalHeight() const
137 if (hasVirtualLogicalHeight())
138 return virtualLogicalHeight();
140 if (lineLayoutItem().isText())
141 return m_bitfields.isText() ? LayoutUnit(lineLayoutItem().style(isFirstLineStyle())->fontMetrics().height()) : LayoutUnit();
142 if (lineLayoutItem().isBox() && parent())
143 return isHorizontal() ? toLayoutBox(layoutObject()).size().height() : toLayoutBox(layoutObject()).size().width();
145 ASSERT(isInlineFlowBox());
146 LineLayoutBoxModel flowObject = boxModelObject();
147 const FontMetrics& fontMetrics = lineLayoutItem().style(isFirstLineStyle())->fontMetrics();
148 LayoutUnit result = fontMetrics.height();
149 if (parent())
150 result += flowObject.borderAndPaddingLogicalHeight();
151 return result;
154 int InlineBox::baselinePosition(FontBaseline baselineType) const
156 return boxModelObject().baselinePosition(baselineType, m_bitfields.firstLine(), isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine);
159 LayoutUnit InlineBox::lineHeight() const
161 return boxModelObject().lineHeight(m_bitfields.firstLine(), isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine);
164 int InlineBox::caretMinOffset() const
166 return lineLayoutItem().caretMinOffset();
169 int InlineBox::caretMaxOffset() const
171 return lineLayoutItem().caretMaxOffset();
174 void InlineBox::dirtyLineBoxes()
176 markDirty();
177 for (InlineFlowBox* curr = parent(); curr && !curr->isDirty(); curr = curr->parent())
178 curr->markDirty();
181 void InlineBox::deleteLine()
183 if (!m_bitfields.extracted() && lineLayoutItem().isBox())
184 toLayoutBox(layoutObject()).setInlineBoxWrapper(nullptr);
185 destroy();
188 void InlineBox::extractLine()
190 m_bitfields.setExtracted(true);
191 if (lineLayoutItem().isBox())
192 toLayoutBox(layoutObject()).setInlineBoxWrapper(nullptr);
195 void InlineBox::attachLine()
197 m_bitfields.setExtracted(false);
198 if (lineLayoutItem().isBox())
199 toLayoutBox(layoutObject()).setInlineBoxWrapper(this);
202 void InlineBox::move(const LayoutSize& delta)
204 m_topLeft.move(delta);
206 if (lineLayoutItem().isReplaced())
207 toLayoutBox(layoutObject()).move(delta.width(), delta.height());
210 void InlineBox::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit /* lineTop */, LayoutUnit /* lineBottom */)
212 // Text clips are painted only for the direct inline children of the object that has a text clip style on it, not block children.
213 if (paintInfo.phase != PaintPhaseTextClip)
214 BlockPainter::paintInlineBox(*this, paintInfo, paintOffset);
217 bool InlineBox::nodeAtPoint(HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit /* lineTop */, LayoutUnit /* lineBottom */)
219 // Hit test all phases of replaced elements atomically, as though the replaced element established its
220 // own stacking context. (See Appendix E.2, section 6.4 on inline block/table elements in the CSS2.1
221 // specification.)
222 LayoutPoint childPoint = accumulatedOffset;
223 if (parent()->lineLayoutItem().hasFlippedBlocksWritingMode()) // Faster than calling containingBlock().
224 childPoint = layoutObject().containingBlock()->flipForWritingModeForChild(&toLayoutBox(layoutObject()), childPoint);
226 if (lineLayoutItem().style()->hasBorderRadius()) {
227 LayoutRect borderRect = logicalFrameRect();
228 borderRect.moveBy(accumulatedOffset);
229 FloatRoundedRect border = lineLayoutItem().style()->getRoundedBorderFor(borderRect);
230 if (!locationInContainer.intersects(border))
231 return false;
234 return lineLayoutItem().hitTest(result, locationInContainer, childPoint);
237 const RootInlineBox& InlineBox::root() const
239 if (m_parent)
240 return m_parent->root();
241 ASSERT(isRootInlineBox());
242 return static_cast<const RootInlineBox&>(*this);
245 RootInlineBox& InlineBox::root()
247 if (m_parent)
248 return m_parent->root();
249 ASSERT(isRootInlineBox());
250 return static_cast<RootInlineBox&>(*this);
253 bool InlineBox::nextOnLineExists() const
255 if (!m_bitfields.determinedIfNextOnLineExists()) {
256 m_bitfields.setDeterminedIfNextOnLineExists(true);
258 if (!parent())
259 m_bitfields.setNextOnLineExists(false);
260 else if (nextOnLine())
261 m_bitfields.setNextOnLineExists(true);
262 else
263 m_bitfields.setNextOnLineExists(parent()->nextOnLineExists());
265 return m_bitfields.nextOnLineExists();
268 InlineBox* InlineBox::nextLeafChild() const
270 InlineBox* leaf = nullptr;
271 for (InlineBox* box = nextOnLine(); box && !leaf; box = box->nextOnLine())
272 leaf = box->isLeaf() ? box : toInlineFlowBox(box)->firstLeafChild();
273 if (!leaf && parent())
274 leaf = parent()->nextLeafChild();
275 return leaf;
278 InlineBox* InlineBox::prevLeafChild() const
280 InlineBox* leaf = nullptr;
281 for (InlineBox* box = prevOnLine(); box && !leaf; box = box->prevOnLine())
282 leaf = box->isLeaf() ? box : toInlineFlowBox(box)->lastLeafChild();
283 if (!leaf && parent())
284 leaf = parent()->prevLeafChild();
285 return leaf;
288 InlineBox* InlineBox::nextLeafChildIgnoringLineBreak() const
290 InlineBox* leaf = nextLeafChild();
291 return (leaf && leaf->isLineBreak()) ? nullptr : leaf;
294 InlineBox* InlineBox::prevLeafChildIgnoringLineBreak() const
296 InlineBox* leaf = prevLeafChild();
297 return (leaf && leaf->isLineBreak()) ? nullptr : leaf;
300 SelectionState InlineBox::selectionState() const
302 return layoutObject().selectionState();
305 bool InlineBox::canAccommodateEllipsis(bool ltr, int blockEdge, int ellipsisWidth) const
307 // Non-replaced elements can always accommodate an ellipsis.
308 if (!lineLayoutItem().isReplaced())
309 return true;
311 IntRect boxRect(left(), 0, m_logicalWidth, 10);
312 IntRect ellipsisRect(ltr ? blockEdge - ellipsisWidth : blockEdge, 0, ellipsisWidth, 10);
313 return !(boxRect.intersects(ellipsisRect));
316 LayoutUnit InlineBox::placeEllipsisBox(bool, LayoutUnit, LayoutUnit, LayoutUnit, LayoutUnit& truncatedWidth, bool&)
318 // Use -1 to mean "we didn't set the position."
319 truncatedWidth += logicalWidth();
320 return -1;
323 void InlineBox::clearKnownToHaveNoOverflow()
325 m_bitfields.setKnownToHaveNoOverflow(false);
326 if (parent() && parent()->knownToHaveNoOverflow())
327 parent()->clearKnownToHaveNoOverflow();
330 LayoutPoint InlineBox::locationIncludingFlipping()
332 return logicalPositionToPhysicalPoint(m_topLeft, size());
335 LayoutPoint InlineBox::logicalPositionToPhysicalPoint(const LayoutPoint& point, const LayoutSize& size)
337 if (!UNLIKELY(lineLayoutItem().hasFlippedBlocksWritingMode()))
338 return LayoutPoint(point.x(), point.y());
340 LayoutBlockFlow& block = root().block();
341 if (block.style()->isHorizontalWritingMode())
342 return LayoutPoint(point.x(), block.size().height() - size.height() - point.y());
344 return LayoutPoint(block.size().width() - size.width() - point.x(), point.y());
347 void InlineBox::logicalRectToPhysicalRect(LayoutRect& current)
349 if (isHorizontal() && !lineLayoutItem().hasFlippedBlocksWritingMode())
350 return;
352 if (!isHorizontal()) {
353 current = current.transposedRect();
355 current.setLocation(logicalPositionToPhysicalPoint(current.location(), current.size()));
356 return;
359 void InlineBox::flipForWritingMode(FloatRect& rect)
361 if (!UNLIKELY(lineLayoutItem().hasFlippedBlocksWritingMode()))
362 return;
363 root().block().flipForWritingMode(rect);
366 FloatPoint InlineBox::flipForWritingMode(const FloatPoint& point)
368 if (!UNLIKELY(lineLayoutItem().hasFlippedBlocksWritingMode()))
369 return point;
370 return root().block().flipForWritingMode(point);
373 void InlineBox::flipForWritingMode(LayoutRect& rect)
375 if (!UNLIKELY(lineLayoutItem().hasFlippedBlocksWritingMode()))
376 return;
377 root().block().flipForWritingMode(rect);
380 LayoutPoint InlineBox::flipForWritingMode(const LayoutPoint& point)
382 if (!UNLIKELY(lineLayoutItem().hasFlippedBlocksWritingMode()))
383 return point;
384 return root().block().flipForWritingMode(point);
387 } // namespace blink
389 #ifndef NDEBUG
391 void showTree(const blink::InlineBox* b)
393 if (b)
394 b->showTreeForThis();
395 else
396 fprintf(stderr, "Cannot showTree for (nil) InlineBox.\n");
399 void showLineTree(const blink::InlineBox* b)
401 if (b)
402 b->showLineTreeForThis();
403 else
404 fprintf(stderr, "Cannot showLineTree for (nil) InlineBox.\n");
407 #endif