blob: ebda99c08131ef9f769f4ad2acb64cd87eadbb56 [file] [log] [blame]
darinb9481ed2006-03-20 02:57:59 +00001/*
darinb9481ed2006-03-20 02:57:59 +00002 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
darin@apple.comb6cb2562009-08-05 21:25:09 +00004 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
darinb9481ed2006-03-20 02:57:59 +00005 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
ddkilzerc8eccec2007-09-26 02:29:57 +000018 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
darinb9481ed2006-03-20 02:57:59 +000020 *
21 */
22
23#include "config.h"
24#include "RenderInline.h"
25
aroben@apple.coma7c639a2009-12-18 17:38:45 +000026#include "Chrome.h"
darin@apple.com36744d62009-01-25 20:23:04 +000027#include "FloatQuad.h"
zalan@apple.come36543a2014-07-29 01:45:54 +000028#include "FrameSelection.h"
hyatt@apple.com9bfe16c2009-01-28 23:44:41 +000029#include "GraphicsContext.h"
hyatt@apple.comcd6f8952009-01-28 17:30:26 +000030#include "HitTestResult.h"
akling@apple.com27e7d142013-11-07 12:04:02 +000031#include "InlineElementBox.h"
hyatt@apple.coma61b8a32011-04-06 18:20:52 +000032#include "InlineTextBox.h"
bdakin@apple.come3d43bb2009-02-05 00:19:31 +000033#include "Page.h"
darinb9481ed2006-03-20 02:57:59 +000034#include "RenderBlock.h"
rniwa@webkit.org39c8c1b2013-05-22 19:21:52 +000035#include "RenderFullScreen.h"
simon.fraser@apple.comca41ec62012-05-25 21:42:32 +000036#include "RenderGeometryMap.h"
akling@apple.com1626ee02013-11-04 12:55:48 +000037#include "RenderIterator.h"
eric@webkit.orgb35848a2010-06-10 08:33:22 +000038#include "RenderLayer.h"
antti@apple.com8d8ae712013-09-18 18:04:32 +000039#include "RenderLineBreak.h"
cdumez@apple.com0abff8b2014-10-17 21:25:10 +000040#include "RenderListMarker.h"
abucur@adobe.com7f2c82d2013-11-20 08:47:35 +000041#include "RenderNamedFlowThread.h"
dbates@webkit.orge825c2a2010-10-14 16:00:52 +000042#include "RenderTheme.h"
hyatt@apple.com62dc0012009-01-26 22:45:24 +000043#include "RenderView.h"
commit-queue@webkit.orgd0c076d2012-08-22 22:25:59 +000044#include "StyleInheritedData.h"
mitz@apple.coma0c027c2009-10-27 23:32:44 +000045#include "TransformState.h"
darinb9481ed2006-03-20 02:57:59 +000046#include "VisiblePosition.h"
47
commit-queue@webkit.org85192c52014-01-26 06:25:55 +000048#if ENABLE(DASHBOARD_SUPPORT)
mrowe@apple.comfc8aa692009-03-09 03:44:38 +000049#include "Frame.h"
50#endif
51
darinb9481ed2006-03-20 02:57:59 +000052namespace WebCore {
53
akling@apple.com8f40c5b2013-10-27 22:54:07 +000054RenderInline::RenderInline(Element& element, PassRef<RenderStyle> style)
dbates@webkit.org0cefe4f2014-07-03 22:13:54 +000055 : RenderBoxModelObject(element, WTF::move(style), RenderInlineFlag)
weinigc24ab182006-10-30 22:41:29 +000056{
hyatt@apple.comcd6f8952009-01-28 17:30:26 +000057 setChildrenInline(true);
weinigc24ab182006-10-30 22:41:29 +000058}
darinb9481ed2006-03-20 02:57:59 +000059
akling@apple.com8f40c5b2013-10-27 22:54:07 +000060RenderInline::RenderInline(Document& document, PassRef<RenderStyle> style)
dbates@webkit.org0cefe4f2014-07-03 22:13:54 +000061 : RenderBoxModelObject(document, WTF::move(style), RenderInlineFlag)
antti@apple.com6310f612013-01-19 14:34:36 +000062{
akling@apple.com42e10632013-10-14 17:55:52 +000063 setChildrenInline(true);
antti@apple.com6310f612013-01-19 14:34:36 +000064}
65
simon.fraser@apple.com73cb0b32011-07-09 00:43:14 +000066void RenderInline::willBeDestroyed()
hyatt@apple.comcd6f8952009-01-28 17:30:26 +000067{
mitz@apple.com9e0c4ef2011-11-11 07:08:46 +000068#if !ASSERT_DISABLED
inferno@chromium.org576aa552011-02-25 23:18:18 +000069 // Make sure we do not retain "this" in the continuation outline table map of our containing blocks.
akling@apple.com827be9c2013-10-29 02:58:43 +000070 if (parent() && style().visibility() == VISIBLE && hasOutline()) {
inferno@chromium.org576aa552011-02-25 23:18:18 +000071 bool containingBlockPaintsContinuationOutline = continuation() || isInlineElementContinuation();
72 if (containingBlockPaintsContinuationOutline) {
73 if (RenderBlock* cb = containingBlock()) {
74 if (RenderBlock* cbCb = cb->containingBlock())
75 ASSERT(!cbCb->paintsContinuationOutline(this));
76 }
77 }
78 }
79#endif
80
hyatt@apple.com4db38f52009-01-29 18:00:39 +000081 // Make sure to destroy anonymous children first while they are still connected to the rest of the tree, so that they will
82 // properly dirty line boxes that they are removed from. Effects that do :before/:after only on hover could crash otherwise.
antti@apple.comda4d3162013-09-23 17:43:04 +000083 destroyLeftoverChildren();
hyatt@apple.com4db38f52009-01-29 18:00:39 +000084
darin@apple.comecb53322009-11-03 18:23:53 +000085 // Destroy our continuation before anything other than anonymous children.
86 // The reason we don't destroy it before anonymous children is that they may
87 // have continuations of their own that are anonymous children of our continuation.
commit-queue@webkit.org47509532010-12-30 03:16:05 +000088 RenderBoxModelObject* continuation = this->continuation();
89 if (continuation) {
90 continuation->destroy();
simon.fraser@apple.come0de5672014-09-19 01:01:39 +000091 setContinuation(nullptr);
darin@apple.comecb53322009-11-03 18:23:53 +000092 }
93
hyatt@apple.com4db38f52009-01-29 18:00:39 +000094 if (!documentBeingDestroyed()) {
95 if (firstLineBox()) {
hyatt@apple.com0d4818f2009-02-08 05:39:22 +000096 // We can't wait for RenderBoxModelObject::destroy to clear the selection,
hyatt@apple.com4db38f52009-01-29 18:00:39 +000097 // because by then we will have nuked the line boxes.
hyatt@apple.com4db38f52009-01-29 18:00:39 +000098 if (isSelectionBorder())
zalan@apple.come36543a2014-07-29 01:45:54 +000099 frame().selection().setNeedsSelectionUpdate();
hyatt@apple.com4db38f52009-01-29 18:00:39 +0000100
101 // If line boxes are contained inside a root, that means we're an inline.
102 // In that case, we need to remove all the line boxes so that the parent
103 // lines aren't pointing to deleted children. If the first line box does
104 // not have a parent that means they are either already disconnected or
105 // root lines that can just be destroyed without disconnecting.
106 if (firstLineBox()->parent()) {
antti@apple.com48e10642013-10-13 11:39:33 +0000107 for (auto box = firstLineBox(); box; box = box->nextLineBox())
108 box->removeFromParent();
hyatt@apple.com4db38f52009-01-29 18:00:39 +0000109 }
inferno@chromium.org3bdb04c2011-05-09 16:29:36 +0000110 } else if (parent())
cdumez@apple.comf8022152014-10-15 00:29:51 +0000111 parent()->dirtyLinesFromChangedChild(*this);
hyatt@apple.com4db38f52009-01-29 18:00:39 +0000112 }
113
akling@apple.com31dd4f42013-10-30 22:27:59 +0000114 m_lineBoxes.deleteLineBoxes();
hyatt@apple.com4db38f52009-01-29 18:00:39 +0000115
simon.fraser@apple.com73cb0b32011-07-09 00:43:14 +0000116 RenderBoxModelObject::willBeDestroyed();
hyatt@apple.comcd6f8952009-01-28 17:30:26 +0000117}
118
hyatt@apple.comca8ce862010-05-22 04:23:04 +0000119RenderInline* RenderInline::inlineElementContinuation() const
hyatt@apple.comcd6f8952009-01-28 17:30:26 +0000120{
commit-queue@webkit.org47509532010-12-30 03:16:05 +0000121 RenderBoxModelObject* continuation = this->continuation();
jhoneycutt@apple.comd4c71aa2014-04-19 00:49:07 +0000122 if (!continuation)
123 return nullptr;
124
cdumez@apple.come9437792014-10-08 23:33:43 +0000125 if (is<RenderInline>(*continuation))
126 return downcast<RenderInline>(continuation);
jhoneycutt@apple.comd4c71aa2014-04-19 00:49:07 +0000127
cdumez@apple.come9437792014-10-08 23:33:43 +0000128 return is<RenderBlock>(*continuation) ? downcast<RenderBlock>(*continuation).inlineElementContinuation() : nullptr;
hyatt@apple.comcd6f8952009-01-28 17:30:26 +0000129}
130
fmalita@chromium.org49d26f22012-10-01 22:04:56 +0000131void RenderInline::updateFromStyle()
hyatt@apple.com0de4d642009-02-05 22:26:53 +0000132{
fmalita@chromium.org49d26f22012-10-01 22:04:56 +0000133 RenderBoxModelObject::updateFromStyle();
hyatt@apple.com0de4d642009-02-05 22:26:53 +0000134
hyatt@apple.com0de4d642009-02-05 22:26:53 +0000135 // FIXME: Support transforms and reflections on inline flows someday.
136 setHasTransform(false);
137 setHasReflection(false);
138}
139
akling@apple.com14141552013-10-14 07:58:09 +0000140static RenderElement* inFlowPositionedInlineAncestor(RenderElement* p)
robert@webkit.org6722a652012-02-19 15:24:50 +0000141{
142 while (p && p->isRenderInline()) {
simon.fraser@apple.comea93fa02012-08-24 00:52:53 +0000143 if (p->isInFlowPositioned())
144 return p;
robert@webkit.org6722a652012-02-19 15:24:50 +0000145 p = p->parent();
146 }
simon.fraser@apple.comea93fa02012-08-24 00:52:53 +0000147 return 0;
robert@webkit.org6722a652012-02-19 15:24:50 +0000148}
149
hyatt@apple.comac928752014-04-03 19:22:48 +0000150static void updateStyleOfAnonymousBlockContinuations(RenderBox* box, const RenderStyle* newStyle, const RenderStyle* oldStyle)
robert@webkit.org6722a652012-02-19 15:24:50 +0000151{
hyatt@apple.comac928752014-04-03 19:22:48 +0000152 for (;box && box->isAnonymousBlock(); box = box->nextSiblingBox()) {
153 if (box->style().position() == newStyle->position())
robert@webkit.org6722a652012-02-19 15:24:50 +0000154 continue;
hyatt@apple.comac928752014-04-03 19:22:48 +0000155
cdumez@apple.come9437792014-10-08 23:33:43 +0000156 if (!is<RenderBlock>(*box))
hyatt@apple.comd6965492014-04-03 21:40:49 +0000157 continue;
hyatt@apple.comac928752014-04-03 19:22:48 +0000158
cdumez@apple.come9437792014-10-08 23:33:43 +0000159 RenderBlock& block = downcast<RenderBlock>(*box);
160 if (!block.isAnonymousBlockContinuation())
hyatt@apple.comd6965492014-04-03 21:40:49 +0000161 continue;
hyatt@apple.comac928752014-04-03 19:22:48 +0000162
simon.fraser@apple.comea93fa02012-08-24 00:52:53 +0000163 // If we are no longer in-flow positioned but our descendant block(s) still have an in-flow positioned ancestor then
164 // their containing anonymous block should keep its in-flow positioning.
cdumez@apple.come9437792014-10-08 23:33:43 +0000165 RenderInline* continuation = block.inlineElementContinuation();
166 if (oldStyle->hasInFlowPosition() && inFlowPositionedInlineAncestor(continuation))
robert@webkit.org6722a652012-02-19 15:24:50 +0000167 continue;
cdumez@apple.come9437792014-10-08 23:33:43 +0000168 auto blockStyle = RenderStyle::createAnonymousStyleWithDisplay(&block.style(), BLOCK);
akling@apple.come8eb70e2013-10-19 13:58:49 +0000169 blockStyle.get().setPosition(newStyle->position());
cdumez@apple.come9437792014-10-08 23:33:43 +0000170 block.setStyle(WTF::move(blockStyle));
robert@webkit.org6722a652012-02-19 15:24:50 +0000171 }
172}
173
weinig@apple.com1a57c822009-02-04 22:27:50 +0000174void RenderInline::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
weinigc24ab182006-10-30 22:41:29 +0000175{
hyatt@apple.com0d4818f2009-02-08 05:39:22 +0000176 RenderBoxModelObject::styleDidChange(diff, oldStyle);
simon.fraser@apple.coma89b8cd2008-10-10 03:15:31 +0000177
darinb9481ed2006-03-20 02:57:59 +0000178 // Ensure that all of the split inlines pick up the new style. We
179 // only do this if we're an inline, since we don't want to propagate
180 // a block's style to the other inlines.
181 // e.g., <font>foo <h4>goo</h4> moo</font>. The <font> inlines before
182 // and after the block share the same style, but the block doesn't
183 // need to pass its style on to anyone else.
akling@apple.com827be9c2013-10-29 02:58:43 +0000184 RenderStyle& newStyle = style();
robert@webkit.org6722a652012-02-19 15:24:50 +0000185 RenderInline* continuation = inlineElementContinuation();
dpranke@chromium.orgcecd9c02012-12-11 18:53:19 +0000186 for (RenderInline* currCont = continuation; currCont; currCont = currCont->inlineElementContinuation()) {
187 RenderBoxModelObject* nextCont = currCont->continuation();
simon.fraser@apple.come0de5672014-09-19 01:01:39 +0000188 currCont->setContinuation(nullptr);
akling@apple.com827be9c2013-10-29 02:58:43 +0000189 currCont->setStyle(newStyle);
dpranke@chromium.orgcecd9c02012-12-11 18:53:19 +0000190 currCont->setContinuation(nextCont);
darinb9481ed2006-03-20 02:57:59 +0000191 }
192
simon.fraser@apple.comea93fa02012-08-24 00:52:53 +0000193 // If an inline's in-flow positioning has changed then any descendant blocks will need to change their in-flow positioning accordingly.
robert@webkit.org6722a652012-02-19 15:24:50 +0000194 // Do this by updating the position of the descendant blocks' containing anonymous blocks - there may be more than one.
akling@apple.com827be9c2013-10-29 02:58:43 +0000195 if (continuation && oldStyle && newStyle.position() != oldStyle->position()
196 && (newStyle.hasInFlowPosition() || oldStyle->hasInFlowPosition())) {
robert@webkit.org6722a652012-02-19 15:24:50 +0000197 // If any descendant blocks exist then they will be in the next anonymous block and its siblings.
198 RenderObject* block = containingBlock()->nextSibling();
199 ASSERT(block && block->isAnonymousBlock());
cdumez@apple.come9437792014-10-08 23:33:43 +0000200 updateStyleOfAnonymousBlockContinuations(downcast<RenderBlock>(block), &newStyle, oldStyle);
robert@webkit.org6722a652012-02-19 15:24:50 +0000201 }
202
akling@apple.com4ea8c6b2013-11-11 06:20:36 +0000203 if (!alwaysCreateLineBoxes()) {
akling@apple.com827be9c2013-10-29 02:58:43 +0000204 bool alwaysCreateLineBoxes = hasSelfPaintingLayer() || hasBoxDecorations() || newStyle.hasPadding() || newStyle.hasMargin() || hasOutline();
hyatt@apple.coma61b8a32011-04-06 18:20:52 +0000205 if (oldStyle && alwaysCreateLineBoxes) {
206 dirtyLineBoxes(false);
antti@apple.comca2a8ff2013-10-04 04:04:35 +0000207 setNeedsLayout();
hyatt@apple.coma61b8a32011-04-06 18:20:52 +0000208 }
akling@apple.com4ea8c6b2013-11-11 06:20:36 +0000209 setRenderInlineAlwaysCreatesLineBoxes(alwaysCreateLineBoxes);
hyatt@apple.coma61b8a32011-04-06 18:20:52 +0000210 }
darinb9481ed2006-03-20 02:57:59 +0000211}
212
inferno@chromium.org88a424d2011-08-09 18:18:36 +0000213void RenderInline::updateAlwaysCreateLineBoxes(bool fullLayout)
hyatt@apple.coma61b8a32011-04-06 18:20:52 +0000214{
215 // Once we have been tainted once, just assume it will happen again. This way effects like hover highlighting that change the
216 // background color will only cause a layout on the first rollover.
akling@apple.com4ea8c6b2013-11-11 06:20:36 +0000217 if (alwaysCreateLineBoxes())
hyatt@apple.coma61b8a32011-04-06 18:20:52 +0000218 return;
219
akling@apple.com827be9c2013-10-29 02:58:43 +0000220 RenderStyle* parentStyle = &parent()->style();
cdumez@apple.comf8022152014-10-15 00:29:51 +0000221 RenderInline* parentRenderInline = is<RenderInline>(*parent()) ? downcast<RenderInline>(parent()) : nullptr;
akling@apple.com836b22b2013-08-25 21:22:06 +0000222 bool checkFonts = document().inNoQuirksMode();
hyatt@apple.comfd6f22e2013-03-01 21:44:06 +0000223 RenderFlowThread* flowThread = flowThreadContainingBlock();
hyatt@apple.coma61b8a32011-04-06 18:20:52 +0000224 bool alwaysCreateLineBoxes = (parentRenderInline && parentRenderInline->alwaysCreateLineBoxes())
225 || (parentRenderInline && parentStyle->verticalAlign() != BASELINE)
akling@apple.com827be9c2013-10-29 02:58:43 +0000226 || style().verticalAlign() != BASELINE
227 || style().textEmphasisMark() != TextEmphasisMarkNone
228 || (checkFonts && (!parentStyle->font().fontMetrics().hasIdenticalAscentDescentAndLineGap(style().font().fontMetrics())
229 || parentStyle->lineHeight() != style().lineHeight()))
abucur@adobe.coma0437722014-01-10 10:38:18 +0000230 || (flowThread && flowThread->isRenderNamedFlowThread()); // FIXME: Enable the optimization once we make overflow computation for culled inlines in regions.
hyatt@apple.coma61b8a32011-04-06 18:20:52 +0000231
benjamin@webkit.org23358d72013-09-25 21:13:38 +0000232 if (!alwaysCreateLineBoxes && checkFonts && document().styleSheetCollection().usesFirstLineRules()) {
hyatt@apple.coma61b8a32011-04-06 18:20:52 +0000233 // Have to check the first line style as well.
akling@apple.com827be9c2013-10-29 02:58:43 +0000234 parentStyle = &parent()->firstLineStyle();
235 RenderStyle& childStyle = firstLineStyle();
236 alwaysCreateLineBoxes = !parentStyle->font().fontMetrics().hasIdenticalAscentDescentAndLineGap(childStyle.font().fontMetrics())
237 || childStyle.verticalAlign() != BASELINE
238 || parentStyle->lineHeight() != childStyle.lineHeight();
hyatt@apple.coma61b8a32011-04-06 18:20:52 +0000239 }
240
241 if (alwaysCreateLineBoxes) {
inferno@chromium.org88a424d2011-08-09 18:18:36 +0000242 if (!fullLayout)
243 dirtyLineBoxes(false);
akling@apple.com4ea8c6b2013-11-11 06:20:36 +0000244 setAlwaysCreateLineBoxes();
hyatt@apple.coma61b8a32011-04-06 18:20:52 +0000245 }
246}
247
commit-queue@webkit.orgf5887ce2012-06-09 01:56:42 +0000248LayoutRect RenderInline::localCaretRect(InlineBox* inlineBox, int, LayoutUnit* extraWidthToEndOfLine)
249{
250 if (firstChild()) {
251 // This condition is possible if the RenderInline is at an editing boundary,
252 // i.e. the VisiblePosition is:
253 // <RenderInline editingBoundary=true>|<RenderText> </RenderText></RenderInline>
254 // FIXME: need to figure out how to make this return a valid rect, note that
255 // there are no line boxes created in the above case.
256 return LayoutRect();
257 }
258
259 ASSERT_UNUSED(inlineBox, !inlineBox);
260
261 if (extraWidthToEndOfLine)
262 *extraWidthToEndOfLine = 0;
263
bjonesbe@adobe.com562a50d2014-02-20 20:01:19 +0000264 LayoutRect caretRect = localCaretRectForEmptyElement(horizontalBorderAndPaddingExtent(), 0);
commit-queue@webkit.orgf5887ce2012-06-09 01:56:42 +0000265
266 if (InlineBox* firstBox = firstLineBox())
zalan@apple.com83de8f82014-08-26 02:11:44 +0000267 caretRect.moveBy(LayoutPoint(firstBox->topLeft()));
commit-queue@webkit.orgf5887ce2012-06-09 01:56:42 +0000268
269 return caretRect;
270}
271
hyatt@apple.comc05db8d22009-01-29 21:39:21 +0000272void RenderInline::addChild(RenderObject* newChild, RenderObject* beforeChild)
273{
274 if (continuation())
275 return addChildToContinuation(newChild, beforeChild);
276 return addChildIgnoringContinuation(newChild, beforeChild);
277}
278
hyatt@apple.com0d4818f2009-02-08 05:39:22 +0000279static RenderBoxModelObject* nextContinuation(RenderObject* renderer)
hyatt@apple.comc05db8d22009-01-29 21:39:21 +0000280{
cdumez@apple.come9437792014-10-08 23:33:43 +0000281 if (is<RenderInline>(*renderer) && !renderer->isReplaced())
282 return downcast<RenderInline>(*renderer).continuation();
283 return downcast<RenderBlock>(*renderer).inlineElementContinuation();
hyatt@apple.comc05db8d22009-01-29 21:39:21 +0000284}
285
hyatt@apple.com0d4818f2009-02-08 05:39:22 +0000286RenderBoxModelObject* RenderInline::continuationBefore(RenderObject* beforeChild)
hyatt@apple.comc05db8d22009-01-29 21:39:21 +0000287{
288 if (beforeChild && beforeChild->parent() == this)
289 return this;
290
hyatt@apple.com0d4818f2009-02-08 05:39:22 +0000291 RenderBoxModelObject* curr = nextContinuation(this);
292 RenderBoxModelObject* nextToLast = this;
293 RenderBoxModelObject* last = this;
hyatt@apple.comc05db8d22009-01-29 21:39:21 +0000294 while (curr) {
295 if (beforeChild && beforeChild->parent() == curr) {
296 if (curr->firstChild() == beforeChild)
297 return last;
298 return curr;
299 }
300
301 nextToLast = last;
302 last = curr;
303 curr = nextContinuation(curr);
304 }
305
306 if (!beforeChild && !last->firstChild())
307 return nextToLast;
308 return last;
309}
310
311void RenderInline::addChildIgnoringContinuation(RenderObject* newChild, RenderObject* beforeChild)
darinb9481ed2006-03-20 02:57:59 +0000312{
313 // Make sure we don't append things after :after-generated content if we have it.
darinf4656952007-01-04 00:27:25 +0000314 if (!beforeChild && isAfterContent(lastChild()))
darinb9481ed2006-03-20 02:57:59 +0000315 beforeChild = lastChild();
316
commit-queue@webkit.org5ef063d2012-07-26 18:50:48 +0000317 if (!newChild->isInline() && !newChild->isFloatingOrOutOfFlowPositioned()) {
darinb9481ed2006-03-20 02:57:59 +0000318 // We are placing a block inside an inline. We have to perform a split of this
319 // inline into continuations. This involves creating an anonymous block box to hold
320 // |newChild|. We then make that block box a continuation of this inline. We take all of
321 // the children after |beforeChild| and put them in a clone of this object.
akling@apple.com827be9c2013-10-29 02:58:43 +0000322 auto newStyle = RenderStyle::createAnonymousStyleWithDisplay(&style(), BLOCK);
robert@webkit.org6722a652012-02-19 15:24:50 +0000323
simon.fraser@apple.comea93fa02012-08-24 00:52:53 +0000324 // If inside an inline affected by in-flow positioning the block needs to be affected by it too.
robert@webkit.org6722a652012-02-19 15:24:50 +0000325 // Giving the block a layer like this allows it to collect the x/y offsets from inline parents later.
akling@apple.com14141552013-10-14 07:58:09 +0000326 if (auto positionedAncestor = inFlowPositionedInlineAncestor(this))
akling@apple.com827be9c2013-10-29 02:58:43 +0000327 newStyle.get().setPosition(positionedAncestor->style().position());
darinb9481ed2006-03-20 02:57:59 +0000328
dbates@webkit.org0cefe4f2014-07-03 22:13:54 +0000329 RenderBlock* newBox = new RenderBlockFlow(document(), WTF::move(newStyle));
akling@apple.com8f40c5b2013-10-27 22:54:07 +0000330 newBox->initializeStyle();
hyatt@apple.com0d4818f2009-02-08 05:39:22 +0000331 RenderBoxModelObject* oldContinuation = continuation();
darinb9481ed2006-03-20 02:57:59 +0000332 setContinuation(newBox);
333
darinb9481ed2006-03-20 02:57:59 +0000334 splitFlow(beforeChild, newBox, newChild, oldContinuation);
335 return;
336 }
337
hyatt@apple.com0d4818f2009-02-08 05:39:22 +0000338 RenderBoxModelObject::addChild(newChild, beforeChild);
darinb9481ed2006-03-20 02:57:59 +0000339
darin7e7c8e42007-04-25 01:14:03 +0000340 newChild->setNeedsLayoutAndPrefWidthsRecalc();
darinb9481ed2006-03-20 02:57:59 +0000341}
342
akling@apple.com94441872014-01-06 09:47:01 +0000343RenderPtr<RenderInline> RenderInline::clone() const
darinb9481ed2006-03-20 02:57:59 +0000344{
akling@apple.com94441872014-01-06 09:47:01 +0000345 RenderPtr<RenderInline> cloneInline = createRenderer<RenderInline>(*element(), style());
akling@apple.com8f40c5b2013-10-27 22:54:07 +0000346 cloneInline->initializeStyle();
hyatt@apple.com6276bf82013-03-01 16:58:25 +0000347 cloneInline->setFlowThreadState(flowThreadState());
mihnea@adobe.com54cc5442012-08-12 15:57:25 +0000348 return cloneInline;
darinb9481ed2006-03-20 02:57:59 +0000349}
350
351void RenderInline::splitInlines(RenderBlock* fromBlock, RenderBlock* toBlock,
352 RenderBlock* middleBlock,
hyatt@apple.com0d4818f2009-02-08 05:39:22 +0000353 RenderObject* beforeChild, RenderBoxModelObject* oldCont)
darinb9481ed2006-03-20 02:57:59 +0000354{
355 // Create a clone of this inline.
akling@apple.com94441872014-01-06 09:47:01 +0000356 RenderPtr<RenderInline> cloneInline = clone();
mihnea@adobe.com54cc5442012-08-12 15:57:25 +0000357 cloneInline->setContinuation(oldCont);
weinigc24ab182006-10-30 22:41:29 +0000358
ossy@webkit.org8d01a732013-05-22 20:30:41 +0000359#if ENABLE(FULLSCREEN_API)
rniwa@webkit.org39c8c1b2013-05-22 19:21:52 +0000360 // If we're splitting the inline containing the fullscreened element,
361 // |beforeChild| may be the renderer for the fullscreened element. However,
362 // that renderer is wrapped in a RenderFullScreen, so |this| is not its
363 // parent. Since the splitting logic expects |this| to be the parent, set
364 // |beforeChild| to be the RenderFullScreen.
akling@apple.com836b22b2013-08-25 21:22:06 +0000365 const Element* fullScreenElement = document().webkitCurrentFullScreenElement();
rniwa@webkit.org39c8c1b2013-05-22 19:21:52 +0000366 if (fullScreenElement && beforeChild && beforeChild->node() == fullScreenElement)
akling@apple.com836b22b2013-08-25 21:22:06 +0000367 beforeChild = document().fullScreenRenderer();
ossy@webkit.org8d01a732013-05-22 20:30:41 +0000368#endif
rniwa@webkit.org39c8c1b2013-05-22 19:21:52 +0000369
darinb9481ed2006-03-20 02:57:59 +0000370 // Now take all of the children from beforeChild to the end and remove
371 // them from |this| and place them in the clone.
cdumez@apple.comdd2b64a2014-10-10 15:49:24 +0000372 RenderObject* renderer = beforeChild;
373 while (renderer) {
374 RenderObject* tmp = renderer;
375 renderer = tmp->nextSibling();
akling@apple.com49d4d3b2013-10-16 12:40:09 +0000376 removeChildInternal(*tmp, NotifyChildren);
simon.fraser@apple.come0de5672014-09-19 01:01:39 +0000377 cloneInline->addChildIgnoringContinuation(tmp);
darin7e7c8e42007-04-25 01:14:03 +0000378 tmp->setNeedsLayoutAndPrefWidthsRecalc();
darinb9481ed2006-03-20 02:57:59 +0000379 }
380
381 // Hook |clone| up as the continuation of the middle block.
akling@apple.com94441872014-01-06 09:47:01 +0000382 middleBlock->setContinuation(cloneInline.get());
darinb9481ed2006-03-20 02:57:59 +0000383
384 // We have been reparented and are now under the fromBlock. We need
385 // to walk up our inline parent chain until we hit the containing block.
386 // Once we hit the containing block we're done.
cdumez@apple.comdd2b64a2014-10-10 15:49:24 +0000387 RenderBoxModelObject* current = downcast<RenderBoxModelObject>(parent());
388 RenderBoxModelObject* currentChild = this;
hyatt6adcd9d2007-04-24 01:27:57 +0000389
390 // FIXME: Because splitting is O(n^2) as tags nest pathologically, we cap the depth at which we're willing to clone.
391 // There will eventually be a better approach to this problem that will let us nest to a much
392 // greater depth (see bugzilla bug 13430) but for now we have a limit. This *will* result in
393 // incorrect rendering, but the alternative is to hang forever.
394 unsigned splitDepth = 1;
395 const unsigned cMaxSplitDepth = 200;
cdumez@apple.comdd2b64a2014-10-10 15:49:24 +0000396 while (current && current != fromBlock) {
hyatt6adcd9d2007-04-24 01:27:57 +0000397 if (splitDepth < cMaxSplitDepth) {
398 // Create a new clone.
dbates@webkit.org0cefe4f2014-07-03 22:13:54 +0000399 RenderPtr<RenderInline> cloneChild = WTF::move(cloneInline);
cdumez@apple.comdd2b64a2014-10-10 15:49:24 +0000400 cloneInline = downcast<RenderInline>(*current).clone();
darinb9481ed2006-03-20 02:57:59 +0000401
hyatt6adcd9d2007-04-24 01:27:57 +0000402 // Insert our child clone as the first child.
simon.fraser@apple.come0de5672014-09-19 01:01:39 +0000403 cloneInline->addChildIgnoringContinuation(cloneChild.leakPtr());
darinb9481ed2006-03-20 02:57:59 +0000404
hyatt6adcd9d2007-04-24 01:27:57 +0000405 // Hook the clone up as a continuation of |curr|.
cdumez@apple.comdd2b64a2014-10-10 15:49:24 +0000406 RenderInline& currentInline = downcast<RenderInline>(*current);
407 oldCont = currentInline.continuation();
408 currentInline.setContinuation(cloneInline.get());
mihnea@adobe.com54cc5442012-08-12 15:57:25 +0000409 cloneInline->setContinuation(oldCont);
darinb9481ed2006-03-20 02:57:59 +0000410
hyatt6adcd9d2007-04-24 01:27:57 +0000411 // Now we need to take all of the children starting from the first child
cdumez@apple.comdd2b64a2014-10-10 15:49:24 +0000412 // *after* currentChild and append them all to the clone.
413 renderer = currentChild->nextSibling();
414 while (renderer) {
415 RenderObject* tmp = renderer;
416 renderer = tmp->nextSibling();
417 currentInline.removeChildInternal(*tmp, NotifyChildren);
simon.fraser@apple.come0de5672014-09-19 01:01:39 +0000418 cloneInline->addChildIgnoringContinuation(tmp);
darin7e7c8e42007-04-25 01:14:03 +0000419 tmp->setNeedsLayoutAndPrefWidthsRecalc();
hyatt6adcd9d2007-04-24 01:27:57 +0000420 }
darinb9481ed2006-03-20 02:57:59 +0000421 }
hyatt6adcd9d2007-04-24 01:27:57 +0000422
darinb9481ed2006-03-20 02:57:59 +0000423 // Keep walking up the chain.
cdumez@apple.comdd2b64a2014-10-10 15:49:24 +0000424 currentChild = current;
425 current = downcast<RenderBoxModelObject>(current->parent());
426 ++splitDepth;
darinb9481ed2006-03-20 02:57:59 +0000427 }
428
429 // Now we are at the block level. We need to put the clone into the toBlock.
akling@apple.com94441872014-01-06 09:47:01 +0000430 toBlock->insertChildInternal(cloneInline.leakPtr(), nullptr, NotifyChildren);
darinb9481ed2006-03-20 02:57:59 +0000431
cdumez@apple.comdd2b64a2014-10-10 15:49:24 +0000432 // Now take all the children after currentChild and remove them from the fromBlock
darinb9481ed2006-03-20 02:57:59 +0000433 // and put them in the toBlock.
cdumez@apple.comdd2b64a2014-10-10 15:49:24 +0000434 renderer = currentChild->nextSibling();
435 while (renderer) {
436 RenderObject* tmp = renderer;
437 renderer = tmp->nextSibling();
akling@apple.com49d4d3b2013-10-16 12:40:09 +0000438 fromBlock->removeChildInternal(*tmp, NotifyChildren);
antti@apple.comda4d3162013-09-23 17:43:04 +0000439 toBlock->insertChildInternal(tmp, nullptr, NotifyChildren);
darinb9481ed2006-03-20 02:57:59 +0000440 }
441}
442
443void RenderInline::splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox,
hyatt@apple.com0d4818f2009-02-08 05:39:22 +0000444 RenderObject* newChild, RenderBoxModelObject* oldCont)
darinb9481ed2006-03-20 02:57:59 +0000445{
cdumez@apple.come9437792014-10-08 23:33:43 +0000446 RenderBlock* pre = nullptr;
darinb9481ed2006-03-20 02:57:59 +0000447 RenderBlock* block = containingBlock();
hyattd55a81b2007-08-06 21:50:48 +0000448
449 // Delete our line boxes before we do the inline split into continuations.
antti@apple.coma2c7f242013-10-22 22:37:25 +0000450 block->deleteLines();
hyattd55a81b2007-08-06 21:50:48 +0000451
darinb9481ed2006-03-20 02:57:59 +0000452 bool madeNewBeforeBlock = false;
darinfcd2c932006-06-28 15:42:13 +0000453 if (block->isAnonymousBlock() && (!block->parent() || !block->parent()->createsAnonymousWrapper())) {
darinb9481ed2006-03-20 02:57:59 +0000454 // We can reuse this block and make it the preBlock of the next continuation.
455 pre = block;
cdumez@apple.come9437792014-10-08 23:33:43 +0000456 pre->removePositionedObjects(nullptr);
bjonesbe@adobe.com24199752013-10-08 23:20:42 +0000457 // FIXME-BLOCKFLOW: The enclosing method should likely be switched over
458 // to only work on RenderBlockFlow, in which case this conversion can be
459 // removed.
cdumez@apple.come9437792014-10-08 23:33:43 +0000460 if (is<RenderBlockFlow>(*pre))
461 downcast<RenderBlockFlow>(*pre).removeFloatingObjects();
darinb9481ed2006-03-20 02:57:59 +0000462 block = block->containingBlock();
darin45d6dcf2006-04-17 06:15:47 +0000463 } else {
darinb9481ed2006-03-20 02:57:59 +0000464 // No anonymous block available for use. Make one.
465 pre = block->createAnonymousBlock();
466 madeNewBeforeBlock = true;
467 }
468
cdumez@apple.come9437792014-10-08 23:33:43 +0000469 RenderBlock& post = downcast<RenderBlock>(*pre->createAnonymousBoxWithSameTypeAs(block));
weinigc24ab182006-10-30 22:41:29 +0000470
darinb9481ed2006-03-20 02:57:59 +0000471 RenderObject* boxFirst = madeNewBeforeBlock ? block->firstChild() : pre->nextSibling();
472 if (madeNewBeforeBlock)
antti@apple.comda4d3162013-09-23 17:43:04 +0000473 block->insertChildInternal(pre, boxFirst, NotifyChildren);
474 block->insertChildInternal(newBlockBox, boxFirst, NotifyChildren);
cdumez@apple.come9437792014-10-08 23:33:43 +0000475 block->insertChildInternal(&post, boxFirst, NotifyChildren);
darinb9481ed2006-03-20 02:57:59 +0000476 block->setChildrenInline(false);
hyattd55a81b2007-08-06 21:50:48 +0000477
darinb9481ed2006-03-20 02:57:59 +0000478 if (madeNewBeforeBlock) {
479 RenderObject* o = boxFirst;
weinigc24ab182006-10-30 22:41:29 +0000480 while (o) {
darinb9481ed2006-03-20 02:57:59 +0000481 RenderObject* no = o;
482 o = no->nextSibling();
akling@apple.com49d4d3b2013-10-16 12:40:09 +0000483 block->removeChildInternal(*no, NotifyChildren);
antti@apple.comda4d3162013-09-23 17:43:04 +0000484 pre->insertChildInternal(no, nullptr, NotifyChildren);
darin7e7c8e42007-04-25 01:14:03 +0000485 no->setNeedsLayoutAndPrefWidthsRecalc();
darinb9481ed2006-03-20 02:57:59 +0000486 }
487 }
488
cdumez@apple.come9437792014-10-08 23:33:43 +0000489 splitInlines(pre, &post, newBlockBox, beforeChild, oldCont);
darinb9481ed2006-03-20 02:57:59 +0000490
491 // We already know the newBlockBox isn't going to contain inline kids, so avoid wasting
492 // time in makeChildrenNonInline by just setting this explicitly up front.
493 newBlockBox->setChildrenInline(false);
494
hyatt@apple.comc05db8d22009-01-29 21:39:21 +0000495 // We delayed adding the newChild until now so that the |newBlockBox| would be fully
darinb9481ed2006-03-20 02:57:59 +0000496 // connected, thus allowing newChild access to a renderArena should it need
497 // to wrap itself in additional boxes (e.g., table construction).
hyatt@apple.comc05db8d22009-01-29 21:39:21 +0000498 newBlockBox->addChild(newChild);
weinigc24ab182006-10-30 22:41:29 +0000499
darinb9481ed2006-03-20 02:57:59 +0000500 // Always just do a full layout in order to ensure that line boxes (especially wrappers for images)
501 // get deleted properly. Because objects moves from the pre block into the post block, we want to
502 // make new line boxes instead of leaving the old line boxes around.
darin7e7c8e42007-04-25 01:14:03 +0000503 pre->setNeedsLayoutAndPrefWidthsRecalc();
504 block->setNeedsLayoutAndPrefWidthsRecalc();
cdumez@apple.come9437792014-10-08 23:33:43 +0000505 post.setNeedsLayoutAndPrefWidthsRecalc();
darinb9481ed2006-03-20 02:57:59 +0000506}
507
hyatt@apple.comc05db8d22009-01-29 21:39:21 +0000508void RenderInline::addChildToContinuation(RenderObject* newChild, RenderObject* beforeChild)
509{
hyatt@apple.com0d4818f2009-02-08 05:39:22 +0000510 RenderBoxModelObject* flow = continuationBefore(beforeChild);
cdumez@apple.comdd2b64a2014-10-10 15:49:24 +0000511 ASSERT(!beforeChild || is<RenderBlock>(*beforeChild->parent()) || is<RenderInline>(*beforeChild->parent()));
512 RenderBoxModelObject* beforeChildParent = nullptr;
hyatt@apple.comc05db8d22009-01-29 21:39:21 +0000513 if (beforeChild)
cdumez@apple.comdd2b64a2014-10-10 15:49:24 +0000514 beforeChildParent = downcast<RenderBoxModelObject>(beforeChild->parent());
hyatt@apple.comc05db8d22009-01-29 21:39:21 +0000515 else {
cdumez@apple.comdd2b64a2014-10-10 15:49:24 +0000516 if (RenderBoxModelObject* continuation = nextContinuation(flow))
517 beforeChildParent = continuation;
hyatt@apple.comc05db8d22009-01-29 21:39:21 +0000518 else
519 beforeChildParent = flow;
520 }
521
simon.fraser@apple.com2f071852012-06-25 00:11:30 +0000522 if (newChild->isFloatingOrOutOfFlowPositioned())
hyatt@apple.comc05db8d22009-01-29 21:39:21 +0000523 return beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild);
524
525 // A continuation always consists of two potential candidates: an inline or an anonymous
526 // block box holding block children.
527 bool childInline = newChild->isInline();
528 bool bcpInline = beforeChildParent->isInline();
529 bool flowInline = flow->isInline();
530
531 if (flow == beforeChildParent)
532 return flow->addChildIgnoringContinuation(newChild, beforeChild);
533 else {
534 // The goal here is to match up if we can, so that we can coalesce and create the
535 // minimal # of continuations needed for the inline.
536 if (childInline == bcpInline)
537 return beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild);
538 else if (flowInline == childInline)
simon.fraser@apple.come0de5672014-09-19 01:01:39 +0000539 return flow->addChildIgnoringContinuation(newChild); // Just treat like an append.
hyatt@apple.comc05db8d22009-01-29 21:39:21 +0000540 else
541 return beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild);
542 }
543}
544
leviw@chromium.orgb3757502011-06-29 21:33:11 +0000545void RenderInline::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
darinb9481ed2006-03-20 02:57:59 +0000546{
leviw@chromium.org61ca1372011-06-07 18:56:41 +0000547 m_lineBoxes.paint(this, paintInfo, paintOffset);
darinb9481ed2006-03-20 02:57:59 +0000548}
549
commit-queue@webkit.org6f2377d2012-05-11 02:08:06 +0000550template<typename GeneratorContext>
simon.fraser@apple.come0de5672014-09-19 01:01:39 +0000551void RenderInline::generateLineBoxRects(GeneratorContext& context) const
darinb9481ed2006-03-20 02:57:59 +0000552{
hyatt@apple.coma61b8a32011-04-06 18:20:52 +0000553 if (!alwaysCreateLineBoxes())
simon.fraser@apple.come0de5672014-09-19 01:01:39 +0000554 generateCulledLineBoxRects(context, this);
hyatt@apple.coma61b8a32011-04-06 18:20:52 +0000555 else if (InlineFlowBox* curr = firstLineBox()) {
weinig@apple.combcc57932009-03-18 20:02:18 +0000556 for (; curr; curr = curr->nextLineBox())
simon.fraser@apple.come0de5672014-09-19 01:01:39 +0000557 context.addRect(FloatRect(curr->topLeft(), curr->size()));
weinig@apple.combcc57932009-03-18 20:02:18 +0000558 } else
simon.fraser@apple.come0de5672014-09-19 01:01:39 +0000559 context.addRect(FloatRect());
commit-queue@webkit.org6f2377d2012-05-11 02:08:06 +0000560}
561
562template<typename GeneratorContext>
simon.fraser@apple.come0de5672014-09-19 01:01:39 +0000563void RenderInline::generateCulledLineBoxRects(GeneratorContext& context, const RenderInline* container) const
commit-queue@webkit.org6f2377d2012-05-11 02:08:06 +0000564{
565 if (!culledInlineFirstLineBox()) {
simon.fraser@apple.come0de5672014-09-19 01:01:39 +0000566 context.addRect(FloatRect());
commit-queue@webkit.org6f2377d2012-05-11 02:08:06 +0000567 return;
568 }
569
akling@apple.com827be9c2013-10-29 02:58:43 +0000570 bool isHorizontal = style().isHorizontalWritingMode();
commit-queue@webkit.org6f2377d2012-05-11 02:08:06 +0000571
cdumez@apple.com35094bd2014-10-07 19:33:53 +0000572 for (RenderObject* current = firstChild(); current; current = current->nextSibling()) {
573 if (current->isFloatingOrOutOfFlowPositioned())
commit-queue@webkit.org6f2377d2012-05-11 02:08:06 +0000574 continue;
575
576 // We want to get the margin box in the inline direction, and then use our font ascent/descent in the block
577 // direction (aligned to the root box's baseline).
cdumez@apple.com35094bd2014-10-07 19:33:53 +0000578 if (is<RenderBox>(*current)) {
579 RenderBox& renderBox = downcast<RenderBox>(*current);
580 if (renderBox.inlineBoxWrapper()) {
581 const RootInlineBox& rootBox = renderBox.inlineBoxWrapper()->root();
akling@apple.com827be9c2013-10-29 02:58:43 +0000582 const RenderStyle& containerStyle = rootBox.isFirstLine() ? container->firstLineStyle() : container->style();
antti@apple.comb0608f62013-09-28 18:30:16 +0000583 int logicalTop = rootBox.logicalTop() + (rootBox.lineStyle().font().fontMetrics().ascent() - containerStyle.font().fontMetrics().ascent());
584 int logicalHeight = containerStyle.font().fontMetrics().height();
commit-queue@webkit.org6f2377d2012-05-11 02:08:06 +0000585 if (isHorizontal)
cdumez@apple.com35094bd2014-10-07 19:33:53 +0000586 context.addRect(FloatRect(renderBox.inlineBoxWrapper()->x() - renderBox.marginLeft(), logicalTop, renderBox.width() + renderBox.horizontalMarginExtent(), logicalHeight));
commit-queue@webkit.org6f2377d2012-05-11 02:08:06 +0000587 else
cdumez@apple.com35094bd2014-10-07 19:33:53 +0000588 context.addRect(FloatRect(logicalTop, renderBox.inlineBoxWrapper()->y() - renderBox.marginTop(), logicalHeight, renderBox.height() + renderBox.verticalMarginExtent()));
commit-queue@webkit.org6f2377d2012-05-11 02:08:06 +0000589 }
cdumez@apple.com35094bd2014-10-07 19:33:53 +0000590 } else if (is<RenderInline>(*current)) {
commit-queue@webkit.org6f2377d2012-05-11 02:08:06 +0000591 // If the child doesn't need line boxes either, then we can recur.
cdumez@apple.com35094bd2014-10-07 19:33:53 +0000592 RenderInline& renderInline = downcast<RenderInline>(*current);
593 if (!renderInline.alwaysCreateLineBoxes())
594 renderInline.generateCulledLineBoxRects(context, container);
commit-queue@webkit.org6f2377d2012-05-11 02:08:06 +0000595 else {
cdumez@apple.com35094bd2014-10-07 19:33:53 +0000596 for (InlineFlowBox* childLine = renderInline.firstLineBox(); childLine; childLine = childLine->nextLineBox()) {
akling@apple.comdbf70302013-09-09 02:11:06 +0000597 const RootInlineBox& rootBox = childLine->root();
akling@apple.com827be9c2013-10-29 02:58:43 +0000598 const RenderStyle& containerStyle = rootBox.isFirstLine() ? container->firstLineStyle() : container->style();
antti@apple.comb0608f62013-09-28 18:30:16 +0000599 int logicalTop = rootBox.logicalTop() + (rootBox.lineStyle().font().fontMetrics().ascent() - containerStyle.font().fontMetrics().ascent());
600 int logicalHeight = containerStyle.fontMetrics().height();
simon.fraser@apple.come0de5672014-09-19 01:01:39 +0000601 if (isHorizontal) {
602 context.addRect(FloatRect(childLine->x() - childLine->marginLogicalLeft(),
commit-queue@webkit.org6f2377d2012-05-11 02:08:06 +0000603 logicalTop,
604 childLine->logicalWidth() + childLine->marginLogicalLeft() + childLine->marginLogicalRight(),
605 logicalHeight));
simon.fraser@apple.come0de5672014-09-19 01:01:39 +0000606 } else {
607 context.addRect(FloatRect(logicalTop,
commit-queue@webkit.org6f2377d2012-05-11 02:08:06 +0000608 childLine->y() - childLine->marginLogicalLeft(),
609 logicalHeight,
610 childLine->logicalWidth() + childLine->marginLogicalLeft() + childLine->marginLogicalRight()));
simon.fraser@apple.come0de5672014-09-19 01:01:39 +0000611 }
commit-queue@webkit.org6f2377d2012-05-11 02:08:06 +0000612 }
613 }
cdumez@apple.com35094bd2014-10-07 19:33:53 +0000614 } else if (is<RenderText>(*current)) {
615 RenderText& currText = downcast<RenderText>(*current);
616 for (InlineTextBox* childText = currText.firstTextBox(); childText; childText = childText->nextTextBox()) {
akling@apple.comdbf70302013-09-09 02:11:06 +0000617 const RootInlineBox& rootBox = childText->root();
akling@apple.com827be9c2013-10-29 02:58:43 +0000618 const RenderStyle& containerStyle = rootBox.isFirstLine() ? container->firstLineStyle() : container->style();
antti@apple.comb0608f62013-09-28 18:30:16 +0000619 int logicalTop = rootBox.logicalTop() + (rootBox.lineStyle().font().fontMetrics().ascent() - containerStyle.font().fontMetrics().ascent());
620 int logicalHeight = containerStyle.font().fontMetrics().height();
commit-queue@webkit.org6f2377d2012-05-11 02:08:06 +0000621 if (isHorizontal)
simon.fraser@apple.come0de5672014-09-19 01:01:39 +0000622 context.addRect(FloatRect(childText->x(), logicalTop, childText->logicalWidth(), logicalHeight));
commit-queue@webkit.org6f2377d2012-05-11 02:08:06 +0000623 else
simon.fraser@apple.come0de5672014-09-19 01:01:39 +0000624 context.addRect(FloatRect(logicalTop, childText->y(), logicalHeight, childText->logicalWidth()));
commit-queue@webkit.org6f2377d2012-05-11 02:08:06 +0000625 }
cdumez@apple.com35094bd2014-10-07 19:33:53 +0000626 } else if (is<RenderLineBreak>(*current)) {
627 if (InlineBox* inlineBox = downcast<RenderLineBreak>(*current).inlineBoxWrapper()) {
antti@apple.com9d8157e2013-09-17 15:13:37 +0000628 // FIXME: This could use a helper to share these with text path.
629 const RootInlineBox& rootBox = inlineBox->root();
akling@apple.com827be9c2013-10-29 02:58:43 +0000630 const RenderStyle& containerStyle = rootBox.isFirstLine() ? container->firstLineStyle() : container->style();
antti@apple.comb0608f62013-09-28 18:30:16 +0000631 int logicalTop = rootBox.logicalTop() + (rootBox.lineStyle().font().fontMetrics().ascent() - containerStyle.font().fontMetrics().ascent());
632 int logicalHeight = containerStyle.fontMetrics().height();
antti@apple.com9d8157e2013-09-17 15:13:37 +0000633 if (isHorizontal)
simon.fraser@apple.come0de5672014-09-19 01:01:39 +0000634 context.addRect(FloatRect(inlineBox->x(), logicalTop, inlineBox->logicalWidth(), logicalHeight));
antti@apple.com9d8157e2013-09-17 15:13:37 +0000635 else
simon.fraser@apple.come0de5672014-09-19 01:01:39 +0000636 context.addRect(FloatRect(logicalTop, inlineBox->y(), logicalHeight, inlineBox->logicalWidth()));
antti@apple.com9d8157e2013-09-17 15:13:37 +0000637 }
commit-queue@webkit.org6f2377d2012-05-11 02:08:06 +0000638 }
639 }
640}
641
642namespace {
643
644class AbsoluteRectsGeneratorContext {
645public:
646 AbsoluteRectsGeneratorContext(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset)
647 : m_rects(rects)
648 , m_accumulatedOffset(accumulatedOffset) { }
649
simon.fraser@apple.come0de5672014-09-19 01:01:39 +0000650 void addRect(const FloatRect& rect)
commit-queue@webkit.org6f2377d2012-05-11 02:08:06 +0000651 {
652 IntRect intRect = enclosingIntRect(rect);
653 intRect.move(m_accumulatedOffset.x(), m_accumulatedOffset.y());
654 m_rects.append(intRect);
655 }
656private:
657 Vector<IntRect>& m_rects;
658 const LayoutPoint& m_accumulatedOffset;
659};
660
661} // unnamed namespace
662
663void RenderInline::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset) const
664{
commit-queue@webkit.org39f4e3f2012-07-17 03:26:00 +0000665 AbsoluteRectsGeneratorContext context(rects, accumulatedOffset);
666 generateLineBoxRects(context);
weinigc24ab182006-10-30 22:41:29 +0000667
akling@apple.com194c6fc2013-09-24 16:20:20 +0000668 if (RenderBoxModelObject* continuation = this->continuation()) {
cdumez@apple.com0abff8b2014-10-17 21:25:10 +0000669 if (is<RenderBox>(*continuation)) {
670 auto& box = downcast<RenderBox>(*continuation);
671 continuation->absoluteRects(rects, toLayoutPoint(accumulatedOffset - containingBlock()->location() + box.locationOffset()));
hyatt@apple.com0d4818f2009-02-08 05:39:22 +0000672 } else
akling@apple.com194c6fc2013-09-24 16:20:20 +0000673 continuation->absoluteRects(rects, toLayoutPoint(accumulatedOffset - containingBlock()->location()));
hyatt@apple.com0d4818f2009-02-08 05:39:22 +0000674 }
darinb9481ed2006-03-20 02:57:59 +0000675}
676
enrica@apple.com2e8c28f2011-07-30 23:51:31 +0000677
commit-queue@webkit.org6f2377d2012-05-11 02:08:06 +0000678namespace {
679
680class AbsoluteQuadsGeneratorContext {
681public:
dbates@webkit.org0303a642012-07-17 07:08:17 +0000682 AbsoluteQuadsGeneratorContext(const RenderInline* renderer, Vector<FloatQuad>& quads)
ddkilzer@apple.com939b2202012-07-10 04:34:13 +0000683 : m_quads(quads)
ddkilzer@apple.com939b2202012-07-10 04:34:13 +0000684 , m_geometryMap()
685 {
simon.fraser@apple.come0de5672014-09-19 01:01:39 +0000686 m_geometryMap.pushMappingsToAncestor(renderer, nullptr);
ddkilzer@apple.com939b2202012-07-10 04:34:13 +0000687 }
commit-queue@webkit.org6f2377d2012-05-11 02:08:06 +0000688
simon.fraser@apple.come0de5672014-09-19 01:01:39 +0000689 void addRect(const FloatRect& rect)
commit-queue@webkit.org6f2377d2012-05-11 02:08:06 +0000690 {
ddkilzer@apple.com939b2202012-07-10 04:34:13 +0000691 m_quads.append(m_geometryMap.absoluteRect(rect));
hyatt@apple.coma61b8a32011-04-06 18:20:52 +0000692 }
commit-queue@webkit.org6f2377d2012-05-11 02:08:06 +0000693private:
commit-queue@webkit.org6f2377d2012-05-11 02:08:06 +0000694 Vector<FloatQuad>& m_quads;
ddkilzer@apple.com939b2202012-07-10 04:34:13 +0000695 RenderGeometryMap m_geometryMap;
commit-queue@webkit.org6f2377d2012-05-11 02:08:06 +0000696};
697
698} // unnamed namespace
hyatt@apple.coma61b8a32011-04-06 18:20:52 +0000699
fsamuel@chromium.orgbc05e3b2011-10-06 21:36:30 +0000700void RenderInline::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
simon.fraser@apple.comaacf70e2008-11-12 23:43:52 +0000701{
dbates@webkit.org0303a642012-07-17 07:08:17 +0000702 AbsoluteQuadsGeneratorContext context(this, quads);
commit-queue@webkit.org39f4e3f2012-07-17 03:26:00 +0000703 generateLineBoxRects(context);
weinig@apple.combcc57932009-03-18 20:02:18 +0000704
akling@apple.com194c6fc2013-09-24 16:20:20 +0000705 if (RenderBoxModelObject* continuation = this->continuation())
706 continuation->absoluteQuads(quads, wasFixed);
simon.fraser@apple.comaacf70e2008-11-12 23:43:52 +0000707}
708
dbates@webkit.org395fca72013-12-06 19:59:38 +0000709#if PLATFORM(IOS)
710void RenderInline::absoluteQuadsForSelection(Vector<FloatQuad>& quads) const
711{
712 AbsoluteQuadsGeneratorContext context(this, quads);
713 generateLineBoxRects(context);
714}
715#endif
716
eae@chromium.org3097a252011-06-28 23:56:01 +0000717LayoutUnit RenderInline::offsetLeft() const
darinb9481ed2006-03-20 02:57:59 +0000718{
commit-queue@webkit.org3a27f9d2012-05-08 19:11:14 +0000719 LayoutPoint topLeft;
hyatt@apple.coma61b8a32011-04-06 18:20:52 +0000720 if (InlineBox* firstBox = firstLineBoxIncludingCulling())
commit-queue@webkit.org3a27f9d2012-05-08 19:11:14 +0000721 topLeft = flooredLayoutPoint(firstBox->topLeft());
commit-queue@webkit.org24fb7492012-05-30 20:30:51 +0000722 return adjustedPositionRelativeToOffsetParent(topLeft).x();
darinb9481ed2006-03-20 02:57:59 +0000723}
724
eae@chromium.org3097a252011-06-28 23:56:01 +0000725LayoutUnit RenderInline::offsetTop() const
darinb9481ed2006-03-20 02:57:59 +0000726{
commit-queue@webkit.org3a27f9d2012-05-08 19:11:14 +0000727 LayoutPoint topLeft;
hyatt@apple.coma61b8a32011-04-06 18:20:52 +0000728 if (InlineBox* firstBox = firstLineBoxIncludingCulling())
commit-queue@webkit.org3a27f9d2012-05-08 19:11:14 +0000729 topLeft = flooredLayoutPoint(firstBox->topLeft());
commit-queue@webkit.org24fb7492012-05-30 20:30:51 +0000730 return adjustedPositionRelativeToOffsetParent(topLeft).y();
darinb9481ed2006-03-20 02:57:59 +0000731}
732
eae@chromium.org05181562011-06-29 21:41:41 +0000733static LayoutUnit computeMargin(const RenderInline* renderer, const Length& margin)
hyatt@apple.com0d4818f2009-02-08 05:39:22 +0000734{
hyatt@apple.com0d4818f2009-02-08 05:39:22 +0000735 if (margin.isAuto())
736 return 0;
737 if (margin.isFixed())
738 return margin.value();
739 if (margin.isPercent())
andersca@apple.com86298632013-11-10 19:32:33 +0000740 return minimumValueForLength(margin, std::max<LayoutUnit>(0, renderer->containingBlock()->availableLogicalWidth()));
hyatt@apple.com0d4818f2009-02-08 05:39:22 +0000741 return 0;
742}
743
eae@chromium.org05181562011-06-29 21:41:41 +0000744LayoutUnit RenderInline::marginLeft() const
hyatt@apple.comd2c45ea2010-09-21 17:49:19 +0000745{
akling@apple.com827be9c2013-10-29 02:58:43 +0000746 return computeMargin(this, style().marginLeft());
hyatt@apple.comd2c45ea2010-09-21 17:49:19 +0000747}
748
eae@chromium.org05181562011-06-29 21:41:41 +0000749LayoutUnit RenderInline::marginRight() const
hyatt@apple.com0d4818f2009-02-08 05:39:22 +0000750{
akling@apple.com827be9c2013-10-29 02:58:43 +0000751 return computeMargin(this, style().marginRight());
hyatt@apple.comd2c45ea2010-09-21 17:49:19 +0000752}
753
eae@chromium.org05181562011-06-29 21:41:41 +0000754LayoutUnit RenderInline::marginTop() const
hyatt@apple.comd2c45ea2010-09-21 17:49:19 +0000755{
akling@apple.com827be9c2013-10-29 02:58:43 +0000756 return computeMargin(this, style().marginTop());
hyatt@apple.comd2c45ea2010-09-21 17:49:19 +0000757}
758
eae@chromium.org05181562011-06-29 21:41:41 +0000759LayoutUnit RenderInline::marginBottom() const
hyatt@apple.comd2c45ea2010-09-21 17:49:19 +0000760{
akling@apple.com827be9c2013-10-29 02:58:43 +0000761 return computeMargin(this, style().marginBottom());
hyatt@apple.comd2c45ea2010-09-21 17:49:19 +0000762}
763
eae@chromium.orgf58ceed2012-05-22 11:16:16 +0000764LayoutUnit RenderInline::marginStart(const RenderStyle* otherStyle) const
hyatt@apple.comd2c45ea2010-09-21 17:49:19 +0000765{
akling@apple.com827be9c2013-10-29 02:58:43 +0000766 return computeMargin(this, style().marginStartUsing(otherStyle ? otherStyle : &style()));
hyatt@apple.comd2c45ea2010-09-21 17:49:19 +0000767}
768
eae@chromium.orgf58ceed2012-05-22 11:16:16 +0000769LayoutUnit RenderInline::marginEnd(const RenderStyle* otherStyle) const
hyatt@apple.comd2c45ea2010-09-21 17:49:19 +0000770{
akling@apple.com827be9c2013-10-29 02:58:43 +0000771 return computeMargin(this, style().marginEndUsing(otherStyle ? otherStyle : &style()));
hyatt@apple.com0d4818f2009-02-08 05:39:22 +0000772}
773
eae@chromium.orgf58ceed2012-05-22 11:16:16 +0000774LayoutUnit RenderInline::marginBefore(const RenderStyle* otherStyle) const
hyatt@apple.com9bcbad62011-03-22 19:03:50 +0000775{
akling@apple.com827be9c2013-10-29 02:58:43 +0000776 return computeMargin(this, style().marginBeforeUsing(otherStyle ? otherStyle : &style()));
hyatt@apple.com9bcbad62011-03-22 19:03:50 +0000777}
778
eae@chromium.orgf58ceed2012-05-22 11:16:16 +0000779LayoutUnit RenderInline::marginAfter(const RenderStyle* otherStyle) const
hyatt@apple.com9bcbad62011-03-22 19:03:50 +0000780{
akling@apple.com827be9c2013-10-29 02:58:43 +0000781 return computeMargin(this, style().marginAfterUsing(otherStyle ? otherStyle : &style()));
hyatt@apple.com9bcbad62011-03-22 19:03:50 +0000782}
783
weinigc24ab182006-10-30 22:41:29 +0000784const char* RenderInline::renderName() const
darinb9481ed2006-03-20 02:57:59 +0000785{
786 if (isRelPositioned())
787 return "RenderInline (relative positioned)";
simon.fraser@apple.com0281aee2012-08-27 17:39:45 +0000788 if (isStickyPositioned())
789 return "RenderInline (sticky positioned)";
commit-queue@webkit.orgfb6d2262012-12-05 21:00:54 +0000790 // FIXME: Temporary hack while the new generated content system is being implemented.
791 if (isPseudoElement())
792 return "RenderInline (generated)";
darinb9481ed2006-03-20 02:57:59 +0000793 if (isAnonymous())
794 return "RenderInline (generated)";
795 return "RenderInline";
796}
797
bdakinc4d8acc2006-10-31 21:48:20 +0000798bool RenderInline::nodeAtPoint(const HitTestRequest& request, HitTestResult& result,
allan.jensen@nokia.com9a9045b2012-08-28 09:41:54 +0000799 const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
darinb9481ed2006-03-20 02:57:59 +0000800{
allan.jensen@nokia.com9a9045b2012-08-28 09:41:54 +0000801 return m_lineBoxes.hitTest(this, request, result, locationInContainer, accumulatedOffset, hitTestAction);
darinb9481ed2006-03-20 02:57:59 +0000802}
803
allan.jensen@digia.com4edbc3a2012-11-27 11:03:23 +0000804namespace {
805
806class HitTestCulledInlinesGeneratorContext {
807public:
simon.fraser@apple.come0de5672014-09-19 01:01:39 +0000808 HitTestCulledInlinesGeneratorContext(Region& region, const HitTestLocation& location)
809 : m_intersected(false)
810 , m_region(region)
811 , m_location(location)
812 { }
813
814 void addRect(const FloatRect& rect)
allan.jensen@digia.com4edbc3a2012-11-27 11:03:23 +0000815 {
816 m_intersected = m_intersected || m_location.intersects(rect);
817 m_region.unite(enclosingIntRect(rect));
818 }
simon.fraser@apple.come0de5672014-09-19 01:01:39 +0000819
allan.jensen@digia.com4edbc3a2012-11-27 11:03:23 +0000820 bool intersected() const { return m_intersected; }
simon.fraser@apple.come0de5672014-09-19 01:01:39 +0000821
allan.jensen@digia.com4edbc3a2012-11-27 11:03:23 +0000822private:
823 bool m_intersected;
824 Region& m_region;
825 const HitTestLocation& m_location;
826};
827
828} // unnamed namespace
829
830bool RenderInline::hitTestCulledInline(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset)
831{
832 ASSERT(result.isRectBasedTest() && !alwaysCreateLineBoxes());
833 if (!visibleToHitTesting())
834 return false;
835
836 HitTestLocation tmpLocation(locationInContainer, -toLayoutSize(accumulatedOffset));
837
838 Region regionResult;
839 HitTestCulledInlinesGeneratorContext context(regionResult, tmpLocation);
840 generateCulledLineBoxRects(context, this);
841
842 if (context.intersected()) {
843 updateHitTestResult(result, tmpLocation.point());
844 // We can not use addNodeToRectBasedTestResult to determine if we fully enclose the hit-test area
845 // because it can only handle rectangular targets.
antti@apple.com8f335082013-09-09 19:54:33 +0000846 result.addNodeToRectBasedTestResult(element(), request, locationInContainer);
rniwa@webkit.org563e8292013-06-11 07:34:42 +0000847 return regionResult.contains(tmpLocation.boundingBox());
allan.jensen@digia.com4edbc3a2012-11-27 11:03:23 +0000848 }
849 return false;
850}
851
stavila@adobe.com4ce2fff2014-04-25 13:56:12 +0000852VisiblePosition RenderInline::positionForPoint(const LayoutPoint& point, const RenderRegion* region)
darinb9481ed2006-03-20 02:57:59 +0000853{
simon.fraser@apple.com0281aee2012-08-27 17:39:45 +0000854 // FIXME: Does not deal with relative or sticky positioned inlines (should it?)
cdumez@apple.come9437792014-10-08 23:33:43 +0000855 RenderBlock& containingBlock = *this->containingBlock();
hyatt@apple.com0d4818f2009-02-08 05:39:22 +0000856 if (firstLineBox()) {
857 // This inline actually has a line box. We must have clicked in the border/padding of one of these boxes. We
858 // should try to find a result by asking our containing block.
cdumez@apple.come9437792014-10-08 23:33:43 +0000859 return containingBlock.positionForPoint(point, region);
hyatt@apple.com0d4818f2009-02-08 05:39:22 +0000860 }
861
862 // Translate the coords from the pre-anonymous block to the post-anonymous block.
cdumez@apple.come9437792014-10-08 23:33:43 +0000863 LayoutPoint parentBlockPoint = containingBlock.location() + point;
864 RenderBoxModelObject* continuation = this->continuation();
865 while (continuation) {
866 RenderBlock* currentBlock = continuation->isInline() ? continuation->containingBlock() : downcast<RenderBlock>(continuation);
867 if (continuation->isInline() || continuation->firstChild())
868 return continuation->positionForPoint(parentBlockPoint - currentBlock->locationOffset(), region);
869 continuation = downcast<RenderBlock>(*continuation).inlineElementContinuation();
darinb9481ed2006-03-20 02:57:59 +0000870 }
hyatt@apple.comcd6f8952009-01-28 17:30:26 +0000871
stavila@adobe.com4ce2fff2014-04-25 13:56:12 +0000872 return RenderBoxModelObject::positionForPoint(point, region);
darinb9481ed2006-03-20 02:57:59 +0000873}
874
commit-queue@webkit.org6f2377d2012-05-11 02:08:06 +0000875namespace {
876
877class LinesBoundingBoxGeneratorContext {
878public:
879 LinesBoundingBoxGeneratorContext(FloatRect& rect) : m_rect(rect) { }
simon.fraser@apple.come0de5672014-09-19 01:01:39 +0000880
881 void addRect(const FloatRect& rect)
commit-queue@webkit.org6f2377d2012-05-11 02:08:06 +0000882 {
883 m_rect.uniteIfNonZero(rect);
884 }
885private:
886 FloatRect& m_rect;
887};
888
889} // unnamed namespace
890
leviw@chromium.org92e93e22012-03-27 10:06:49 +0000891IntRect RenderInline::linesBoundingBox() const
hyatt@apple.com62dc0012009-01-26 22:45:24 +0000892{
hyatt@apple.coma61b8a32011-04-06 18:20:52 +0000893 if (!alwaysCreateLineBoxes()) {
894 ASSERT(!firstLineBox());
commit-queue@webkit.org6f2377d2012-05-11 02:08:06 +0000895 FloatRect floatResult;
commit-queue@webkit.org39f4e3f2012-07-17 03:26:00 +0000896 LinesBoundingBoxGeneratorContext context(floatResult);
897 generateCulledLineBoxRects(context, this);
commit-queue@webkit.org6f2377d2012-05-11 02:08:06 +0000898 return enclosingIntRect(floatResult);
hyatt@apple.coma61b8a32011-04-06 18:20:52 +0000899 }
900
leviw@chromium.org92e93e22012-03-27 10:06:49 +0000901 IntRect result;
hyatt@apple.com62dc0012009-01-26 22:45:24 +0000902
903 // See <rdar://problem/5289721>, for an unknown reason the linked list here is sometimes inconsistent, first is non-zero and last is zero. We have been
904 // unable to reproduce this at all (and consequently unable to figure ot why this is happening). The assert will hopefully catch the problem in debug
905 // builds and help us someday figure out why. We also put in a redundant check of lastLineBox() to avoid the crash for now.
906 ASSERT(!firstLineBox() == !lastLineBox()); // Either both are null or both exist.
907 if (firstLineBox() && lastLineBox()) {
908 // Return the width of the minimal left side and the maximal right side.
hyatt@apple.com0acc9352011-02-17 19:19:07 +0000909 float logicalLeftSide = 0;
910 float logicalRightSide = 0;
hyatt@apple.com9f47d582010-03-12 20:29:50 +0000911 for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
hyatt@apple.com46ed5552010-11-01 19:07:12 +0000912 if (curr == firstLineBox() || curr->logicalLeft() < logicalLeftSide)
913 logicalLeftSide = curr->logicalLeft();
914 if (curr == firstLineBox() || curr->logicalRight() > logicalRightSide)
915 logicalRightSide = curr->logicalRight();
hyatt@apple.com62dc0012009-01-26 22:45:24 +0000916 }
hyatt@apple.com46ed5552010-11-01 19:07:12 +0000917
akling@apple.com827be9c2013-10-29 02:58:43 +0000918 bool isHorizontal = style().isHorizontalWritingMode();
hyatt@apple.com46ed5552010-11-01 19:07:12 +0000919
hyatt@apple.com0acc9352011-02-17 19:19:07 +0000920 float x = isHorizontal ? logicalLeftSide : firstLineBox()->x();
921 float y = isHorizontal ? firstLineBox()->y() : logicalLeftSide;
922 float width = isHorizontal ? logicalRightSide - logicalLeftSide : lastLineBox()->logicalBottom() - x;
923 float height = isHorizontal ? lastLineBox()->logicalBottom() - y : logicalRightSide - logicalLeftSide;
leviw@chromium.org92e93e22012-03-27 10:06:49 +0000924 result = enclosingIntRect(FloatRect(x, y, width, height));
hyatt@apple.com62dc0012009-01-26 22:45:24 +0000925 }
926
927 return result;
928}
929
hyatt@apple.coma61b8a32011-04-06 18:20:52 +0000930InlineBox* RenderInline::culledInlineFirstLineBox() const
931{
cdumez@apple.com35094bd2014-10-07 19:33:53 +0000932 for (RenderObject* current = firstChild(); current; current = current->nextSibling()) {
933 if (current->isFloatingOrOutOfFlowPositioned())
hyatt@apple.coma61b8a32011-04-06 18:20:52 +0000934 continue;
935
936 // We want to get the margin box in the inline direction, and then use our font ascent/descent in the block
937 // direction (aligned to the root box's baseline).
cdumez@apple.com35094bd2014-10-07 19:33:53 +0000938 if (is<RenderBox>(*current))
939 return downcast<RenderBox>(*current).inlineBoxWrapper();
940 if (is<RenderLineBreak>(*current)) {
941 RenderLineBreak& renderBR = downcast<RenderLineBreak>(*current);
942 if (renderBR.inlineBoxWrapper())
943 return renderBR.inlineBoxWrapper();
944 } else if (is<RenderInline>(*current)) {
945 RenderInline& renderInline = downcast<RenderInline>(*current);
946 if (InlineBox* result = renderInline.firstLineBoxIncludingCulling())
hyatt@apple.coma61b8a32011-04-06 18:20:52 +0000947 return result;
cdumez@apple.com35094bd2014-10-07 19:33:53 +0000948 } else if (is<RenderText>(*current)) {
949 RenderText& renderText = downcast<RenderText>(*current);
950 if (renderText.firstTextBox())
951 return renderText.firstTextBox();
hyatt@apple.coma61b8a32011-04-06 18:20:52 +0000952 }
953 }
cdumez@apple.com35094bd2014-10-07 19:33:53 +0000954 return nullptr;
hyatt@apple.coma61b8a32011-04-06 18:20:52 +0000955}
956
957InlineBox* RenderInline::culledInlineLastLineBox() const
958{
cdumez@apple.com35094bd2014-10-07 19:33:53 +0000959 for (RenderObject* current = lastChild(); current; current = current->previousSibling()) {
960 if (current->isFloatingOrOutOfFlowPositioned())
hyatt@apple.coma61b8a32011-04-06 18:20:52 +0000961 continue;
962
963 // We want to get the margin box in the inline direction, and then use our font ascent/descent in the block
964 // direction (aligned to the root box's baseline).
cdumez@apple.com35094bd2014-10-07 19:33:53 +0000965 if (is<RenderBox>(*current))
966 return downcast<RenderBox>(*current).inlineBoxWrapper();
967 if (is<RenderLineBreak>(*current)) {
968 RenderLineBreak& renderBR = downcast<RenderLineBreak>(*current);
969 if (renderBR.inlineBoxWrapper())
970 return renderBR.inlineBoxWrapper();
971 } else if (is<RenderInline>(*current)) {
972 RenderInline& renderInline = downcast<RenderInline>(*current);
973 if (InlineBox* result = renderInline.lastLineBoxIncludingCulling())
hyatt@apple.coma61b8a32011-04-06 18:20:52 +0000974 return result;
cdumez@apple.com35094bd2014-10-07 19:33:53 +0000975 } else if (is<RenderText>(*current)) {
976 RenderText& renderText = downcast<RenderText>(*current);
977 if (renderText.lastTextBox())
978 return renderText.lastTextBox();
hyatt@apple.coma61b8a32011-04-06 18:20:52 +0000979 }
980 }
cdumez@apple.com35094bd2014-10-07 19:33:53 +0000981 return nullptr;
hyatt@apple.coma61b8a32011-04-06 18:20:52 +0000982}
983
leviw@chromium.orgfc300232011-08-18 19:23:22 +0000984LayoutRect RenderInline::culledInlineVisualOverflowBoundingBox() const
hyatt@apple.coma61b8a32011-04-06 18:20:52 +0000985{
commit-queue@webkit.org6f2377d2012-05-11 02:08:06 +0000986 FloatRect floatResult;
commit-queue@webkit.org39f4e3f2012-07-17 03:26:00 +0000987 LinesBoundingBoxGeneratorContext context(floatResult);
988 generateCulledLineBoxRects(context, this);
commit-queue@webkit.org6f2377d2012-05-11 02:08:06 +0000989 LayoutRect result(enclosingLayoutRect(floatResult));
akling@apple.com827be9c2013-10-29 02:58:43 +0000990 bool isHorizontal = style().isHorizontalWritingMode();
cdumez@apple.com35094bd2014-10-07 19:33:53 +0000991 for (RenderObject* current = firstChild(); current; current = current->nextSibling()) {
992 if (current->isFloatingOrOutOfFlowPositioned())
hyatt@apple.coma61b8a32011-04-06 18:20:52 +0000993 continue;
994
995 // For overflow we just have to propagate by hand and recompute it all.
cdumez@apple.com35094bd2014-10-07 19:33:53 +0000996 if (is<RenderBox>(*current)) {
997 RenderBox& renderBox = downcast<RenderBox>(*current);
998 if (!renderBox.hasSelfPaintingLayer() && renderBox.inlineBoxWrapper()) {
999 LayoutRect logicalRect = renderBox.logicalVisualOverflowRectForPropagation(&style());
hyatt@apple.coma61b8a32011-04-06 18:20:52 +00001000 if (isHorizontal) {
cdumez@apple.com35094bd2014-10-07 19:33:53 +00001001 logicalRect.moveBy(renderBox.location());
hyatt@apple.coma61b8a32011-04-06 18:20:52 +00001002 result.uniteIfNonZero(logicalRect);
1003 } else {
cdumez@apple.com35094bd2014-10-07 19:33:53 +00001004 logicalRect.moveBy(renderBox.location());
hyatt@apple.coma61b8a32011-04-06 18:20:52 +00001005 result.uniteIfNonZero(logicalRect.transposedRect());
1006 }
1007 }
cdumez@apple.com35094bd2014-10-07 19:33:53 +00001008 } else if (is<RenderInline>(*current)) {
hyatt@apple.coma61b8a32011-04-06 18:20:52 +00001009 // If the child doesn't need line boxes either, then we can recur.
cdumez@apple.com35094bd2014-10-07 19:33:53 +00001010 RenderInline& renderInline = downcast<RenderInline>(*current);
1011 if (!renderInline.alwaysCreateLineBoxes())
1012 result.uniteIfNonZero(renderInline.culledInlineVisualOverflowBoundingBox());
1013 else if (!renderInline.hasSelfPaintingLayer())
1014 result.uniteIfNonZero(renderInline.linesVisualOverflowBoundingBox());
1015 } else if (is<RenderText>(*current)) {
hyatt@apple.coma61b8a32011-04-06 18:20:52 +00001016 // FIXME; Overflow from text boxes is lost. We will need to cache this information in
1017 // InlineTextBoxes.
cdumez@apple.com35094bd2014-10-07 19:33:53 +00001018 RenderText& renderText = downcast<RenderText>(*current);
1019 result.uniteIfNonZero(renderText.linesVisualOverflowBoundingBox());
hyatt@apple.coma61b8a32011-04-06 18:20:52 +00001020 }
1021 }
1022 return result;
1023}
1024
leviw@chromium.orgfc300232011-08-18 19:23:22 +00001025LayoutRect RenderInline::linesVisualOverflowBoundingBox() const
mitz@apple.com3b8b9f42009-08-26 21:54:11 +00001026{
hyatt@apple.coma61b8a32011-04-06 18:20:52 +00001027 if (!alwaysCreateLineBoxes())
1028 return culledInlineVisualOverflowBoundingBox();
1029
mitz@apple.com3b8b9f42009-08-26 21:54:11 +00001030 if (!firstLineBox() || !lastLineBox())
leviw@chromium.orgfc300232011-08-18 19:23:22 +00001031 return LayoutRect();
mitz@apple.com3b8b9f42009-08-26 21:54:11 +00001032
1033 // Return the width of the minimal left side and the maximal right side.
eae@chromium.org9717cd82012-11-07 18:33:44 +00001034 LayoutUnit logicalLeftSide = LayoutUnit::max();
1035 LayoutUnit logicalRightSide = LayoutUnit::min();
hyatt@apple.com9f47d582010-03-12 20:29:50 +00001036 for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
andersca@apple.com86298632013-11-10 19:32:33 +00001037 logicalLeftSide = std::min(logicalLeftSide, curr->logicalLeftVisualOverflow());
1038 logicalRightSide = std::max(logicalRightSide, curr->logicalRightVisualOverflow());
mitz@apple.com3b8b9f42009-08-26 21:54:11 +00001039 }
1040
akling@apple.comdbf70302013-09-09 02:11:06 +00001041 const RootInlineBox& firstRootBox = firstLineBox()->root();
1042 const RootInlineBox& lastRootBox = lastLineBox()->root();
hyatt@apple.com61f25322011-03-31 20:40:48 +00001043
akling@apple.comdbf70302013-09-09 02:11:06 +00001044 LayoutUnit logicalTop = firstLineBox()->logicalTopVisualOverflow(firstRootBox.lineTop());
leviw@chromium.orgfc300232011-08-18 19:23:22 +00001045 LayoutUnit logicalWidth = logicalRightSide - logicalLeftSide;
akling@apple.comdbf70302013-09-09 02:11:06 +00001046 LayoutUnit logicalHeight = lastLineBox()->logicalBottomVisualOverflow(lastRootBox.lineBottom()) - logicalTop;
hyatt@apple.com61f25322011-03-31 20:40:48 +00001047
leviw@chromium.orgfc300232011-08-18 19:23:22 +00001048 LayoutRect rect(logicalLeftSide, logicalTop, logicalWidth, logicalHeight);
akling@apple.com827be9c2013-10-29 02:58:43 +00001049 if (!style().isHorizontalWritingMode())
hyatt@apple.com61f25322011-03-31 20:40:48 +00001050 rect = rect.transposedRect();
1051 return rect;
mitz@apple.com3b8b9f42009-08-26 21:54:11 +00001052}
1053
abucur@adobe.coma0437722014-01-10 10:38:18 +00001054LayoutRect RenderInline::linesVisualOverflowBoundingBoxInRegion(const RenderRegion* region) const
1055{
1056 ASSERT(alwaysCreateLineBoxes());
1057 ASSERT(region);
1058
1059 if (!firstLineBox() || !lastLineBox())
1060 return LayoutRect();
1061
1062 // Return the width of the minimal left side and the maximal right side.
1063 LayoutUnit logicalLeftSide = LayoutUnit::max();
1064 LayoutUnit logicalRightSide = LayoutUnit::min();
1065 LayoutUnit logicalTop;
1066 LayoutUnit logicalHeight;
1067 InlineFlowBox* lastInlineInRegion = 0;
1068 for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
1069 const RootInlineBox& root = curr->root();
1070 if (root.containingRegion() != region) {
1071 if (lastInlineInRegion)
1072 break;
1073 continue;
1074 }
1075
1076 if (!lastInlineInRegion)
1077 logicalTop = curr->logicalTopVisualOverflow(root.lineTop());
1078
1079 lastInlineInRegion = curr;
1080
1081 logicalLeftSide = std::min(logicalLeftSide, curr->logicalLeftVisualOverflow());
1082 logicalRightSide = std::max(logicalRightSide, curr->logicalRightVisualOverflow());
1083 }
1084
1085 if (!lastInlineInRegion)
1086 return LayoutRect();
1087
1088 logicalHeight = lastInlineInRegion->logicalBottomVisualOverflow(lastInlineInRegion->root().lineBottom()) - logicalTop;
1089
1090 LayoutUnit logicalWidth = logicalRightSide - logicalLeftSide;
1091
1092 LayoutRect rect(logicalLeftSide, logicalTop, logicalWidth, logicalHeight);
1093 if (!style().isHorizontalWritingMode())
1094 rect = rect.transposedRect();
1095 return rect;
1096}
1097
simon.fraser@apple.coma4825062012-11-08 05:15:10 +00001098LayoutRect RenderInline::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
hyatt@apple.com62dc0012009-01-26 22:45:24 +00001099{
akling@apple.com38f0a652014-02-06 21:24:17 +00001100 // Only first-letter renderers are allowed in here during layout. They mutate the tree triggering repaints.
1101 ASSERT(!view().layoutStateEnabled() || style().styleType() == FIRST_LETTER);
hyatt@apple.com62dc0012009-01-26 22:45:24 +00001102
hyatt@apple.coma61b8a32011-04-06 18:20:52 +00001103 if (!firstLineBoxIncludingCulling() && !continuation())
leviw@chromium.orgfc300232011-08-18 19:23:22 +00001104 return LayoutRect();
hyatt@apple.com62dc0012009-01-26 22:45:24 +00001105
jchaffraix@webkit.org0e70bf82012-05-17 21:31:10 +00001106 LayoutRect repaintRect(linesVisualOverflowBoundingBox());
mitz@apple.com8296dea2012-03-13 23:58:59 +00001107 bool hitRepaintContainer = false;
1108
simon.fraser@apple.comea93fa02012-08-24 00:52:53 +00001109 // We need to add in the in-flow position offsets of any inlines (including us) up to our
hyatt@apple.com62dc0012009-01-26 22:45:24 +00001110 // containing block.
cdumez@apple.comf8022152014-10-15 00:29:51 +00001111 RenderBlock* containingBlock = this->containingBlock();
1112 for (const RenderElement* inlineFlow = this; is<RenderInline>(inlineFlow) && inlineFlow != containingBlock;
hyatt@apple.com62dc0012009-01-26 22:45:24 +00001113 inlineFlow = inlineFlow->parent()) {
mitz@apple.com8296dea2012-03-13 23:58:59 +00001114 if (inlineFlow == repaintContainer) {
1115 hitRepaintContainer = true;
1116 break;
1117 }
akling@apple.com827be9c2013-10-29 02:58:43 +00001118 if (inlineFlow->style().hasInFlowPosition() && inlineFlow->hasLayer())
cdumez@apple.comf8022152014-10-15 00:29:51 +00001119 repaintRect.move(downcast<RenderInline>(*inlineFlow).layer()->offsetForInFlowPosition());
hyatt@apple.com62dc0012009-01-26 22:45:24 +00001120 }
1121
akling@apple.com827be9c2013-10-29 02:58:43 +00001122 LayoutUnit outlineSize = style().outlineSize();
jchaffraix@webkit.org0e70bf82012-05-17 21:31:10 +00001123 repaintRect.inflate(outlineSize);
hyatt@apple.com46ed5552010-11-01 19:07:12 +00001124
cdumez@apple.comf8022152014-10-15 00:29:51 +00001125 if (hitRepaintContainer || !containingBlock)
jchaffraix@webkit.org0e70bf82012-05-17 21:31:10 +00001126 return repaintRect;
mitz@apple.com8296dea2012-03-13 23:58:59 +00001127
cdumez@apple.comf8022152014-10-15 00:29:51 +00001128 if (containingBlock->hasOverflowClip())
1129 containingBlock->applyCachedClipAndScrollOffsetForRepaint(repaintRect);
mitz@apple.com8296dea2012-03-13 23:58:59 +00001130
cdumez@apple.comf8022152014-10-15 00:29:51 +00001131 containingBlock->computeRectForRepaint(repaintContainer, repaintRect);
hyatt@apple.com62dc0012009-01-26 22:45:24 +00001132
jchaffraix@webkit.org0e70bf82012-05-17 21:31:10 +00001133 if (outlineSize) {
weinig@apple.comc77041e2013-12-14 18:05:45 +00001134 for (auto& child : childrenOfType<RenderElement>(*this))
1135 repaintRect.unite(child.rectWithOutlineForRepaint(repaintContainer, outlineSize));
hyatt@apple.com62dc0012009-01-26 22:45:24 +00001136
akling@apple.com194c6fc2013-09-24 16:20:20 +00001137 if (RenderBoxModelObject* continuation = this->continuation()) {
1138 if (!continuation->isInline() && continuation->parent())
1139 repaintRect.unite(continuation->rectWithOutlineForRepaint(repaintContainer, outlineSize));
1140 }
hyatt@apple.com62dc0012009-01-26 22:45:24 +00001141 }
1142
jchaffraix@webkit.org0e70bf82012-05-17 21:31:10 +00001143 return repaintRect;
hyatt@apple.com62dc0012009-01-26 22:45:24 +00001144}
1145
simon.fraser@apple.coma4825062012-11-08 05:15:10 +00001146LayoutRect RenderInline::rectWithOutlineForRepaint(const RenderLayerModelObject* repaintContainer, LayoutUnit outlineWidth) const
hyatt@apple.comcd6f8952009-01-28 17:30:26 +00001147{
leviw@chromium.orgfc300232011-08-18 19:23:22 +00001148 LayoutRect r(RenderBoxModelObject::rectWithOutlineForRepaint(repaintContainer, outlineWidth));
weinig@apple.comc77041e2013-12-14 18:05:45 +00001149 for (auto& child : childrenOfType<RenderElement>(*this))
1150 r.unite(child.rectWithOutlineForRepaint(repaintContainer, outlineWidth));
hyatt@apple.comcd6f8952009-01-28 17:30:26 +00001151 return r;
1152}
1153
simon.fraser@apple.coma4825062012-11-08 05:15:10 +00001154void RenderInline::computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect& rect, bool fixed) const
hyatt@apple.com0d4818f2009-02-08 05:39:22 +00001155{
akling@apple.com691cf5c2013-08-24 16:33:15 +00001156 // LayoutState is only valid for root-relative repainting
1157 if (view().layoutStateEnabled() && !repaintContainer) {
1158 LayoutState* layoutState = view().layoutState();
akling@apple.com827be9c2013-10-29 02:58:43 +00001159 if (style().hasInFlowPosition() && layer())
akling@apple.com691cf5c2013-08-24 16:33:15 +00001160 rect.move(layer()->offsetForInFlowPosition());
1161 rect.move(layoutState->m_paintOffset);
1162 if (layoutState->m_clipped)
1163 rect.intersect(layoutState->m_clipRect);
1164 return;
hyatt@apple.com0d4818f2009-02-08 05:39:22 +00001165 }
1166
1167 if (repaintContainer == this)
1168 return;
1169
simon.fraser@apple.comdcacba12009-09-28 16:14:18 +00001170 bool containerSkipped;
cdumez@apple.com225ce472014-10-15 05:01:31 +00001171 RenderElement* container = this->container(repaintContainer, &containerSkipped);
1172 if (!container)
hyatt@apple.com0d4818f2009-02-08 05:39:22 +00001173 return;
1174
leviw@chromium.orgfc300232011-08-18 19:23:22 +00001175 LayoutPoint topLeft = rect.location();
hyatt@apple.com0d4818f2009-02-08 05:39:22 +00001176
akling@apple.com827be9c2013-10-29 02:58:43 +00001177 if (style().hasInFlowPosition() && layer()) {
simon.fraser@apple.comea93fa02012-08-24 00:52:53 +00001178 // Apply the in-flow position offset when invalidating a rectangle. The layer
hyatt@apple.com0d4818f2009-02-08 05:39:22 +00001179 // is translated, but the render box isn't, so we need to do this to get the
simon.fraser@apple.com0281aee2012-08-27 17:39:45 +00001180 // right dirty rect. Since this is called from RenderObject::setStyle, the relative or sticky position
hyatt@apple.com0d4818f2009-02-08 05:39:22 +00001181 // flag on the RenderObject has been cleared, so use the one on the style().
commit-queue@webkit.org6362c302013-06-27 20:33:07 +00001182 topLeft += layer()->offsetForInFlowPosition();
hyatt@apple.com0d4818f2009-02-08 05:39:22 +00001183 }
1184
1185 // FIXME: We ignore the lightweight clipping rect that controls use, since if |o| is in mid-layout,
1186 // its controlClipRect will be wrong. For overflow clip we use the values cached by the layer.
commit-queue@webkit.org9914ba62012-09-13 17:22:21 +00001187 rect.setLocation(topLeft);
cdumez@apple.com225ce472014-10-15 05:01:31 +00001188 if (container->hasOverflowClip()) {
1189 downcast<RenderBox>(*container).applyCachedClipAndScrollOffsetForRepaint(rect);
hyatt@apple.com0d4818f2009-02-08 05:39:22 +00001190 if (rect.isEmpty())
1191 return;
commit-queue@webkit.org9914ba62012-09-13 17:22:21 +00001192 }
simon.fraser@apple.comdcacba12009-09-28 16:14:18 +00001193
1194 if (containerSkipped) {
1195 // If the repaintContainer is below o, then we need to map the rect into repaintContainer's coordinates.
cdumez@apple.com225ce472014-10-15 05:01:31 +00001196 LayoutSize containerOffset = repaintContainer->offsetFromAncestorContainer(*container);
simon.fraser@apple.comdcacba12009-09-28 16:14:18 +00001197 rect.move(-containerOffset);
1198 return;
1199 }
hyatt@apple.com0d4818f2009-02-08 05:39:22 +00001200
cdumez@apple.com225ce472014-10-15 05:01:31 +00001201 container->computeRectForRepaint(repaintContainer, rect, fixed);
hyatt@apple.com0d4818f2009-02-08 05:39:22 +00001202}
1203
cdumez@apple.com225ce472014-10-15 05:01:31 +00001204LayoutSize RenderInline::offsetFromContainer(RenderElement& container, const LayoutPoint&, bool* offsetDependsOnPoint) const
mitz@apple.coma0c027c2009-10-27 23:32:44 +00001205{
cdumez@apple.com225ce472014-10-15 05:01:31 +00001206 ASSERT(&container == this->container());
hyatt@apple.com61bbedf2011-01-26 23:10:57 +00001207
eae@chromium.orga468a4a2011-07-07 02:32:26 +00001208 LayoutSize offset;
simon.fraser@apple.comea93fa02012-08-24 00:52:53 +00001209 if (isInFlowPositioned())
1210 offset += offsetForInFlowPosition();
mitz@apple.coma0c027c2009-10-27 23:32:44 +00001211
cdumez@apple.com225ce472014-10-15 05:01:31 +00001212 if (is<RenderBox>(container))
1213 offset -= downcast<RenderBox>(container).scrolledContentOffset();
mitz@apple.coma0c027c2009-10-27 23:32:44 +00001214
simon.fraser@apple.comca41ec62012-05-25 21:42:32 +00001215 if (offsetDependsOnPoint)
cdumez@apple.com225ce472014-10-15 05:01:31 +00001216 *offsetDependsOnPoint = (is<RenderBox>(container) && container.style().isFlippedBlocksWritingMode()) || is<RenderFlowThread>(container);
simon.fraser@apple.comca41ec62012-05-25 21:42:32 +00001217
mitz@apple.coma0c027c2009-10-27 23:32:44 +00001218 return offset;
1219}
1220
simon.fraser@apple.coma4825062012-11-08 05:15:10 +00001221void RenderInline::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed) const
mitz@apple.coma0c027c2009-10-27 23:32:44 +00001222{
1223 if (repaintContainer == this)
1224 return;
1225
akling@apple.com691cf5c2013-08-24 16:33:15 +00001226 if (view().layoutStateEnabled() && !repaintContainer) {
1227 LayoutState* layoutState = view().layoutState();
1228 LayoutSize offset = layoutState->m_paintOffset;
akling@apple.com827be9c2013-10-29 02:58:43 +00001229 if (style().hasInFlowPosition() && layer())
akling@apple.com691cf5c2013-08-24 16:33:15 +00001230 offset += layer()->offsetForInFlowPosition();
1231 transformState.move(offset);
1232 return;
mitz@apple.coma0c027c2009-10-27 23:32:44 +00001233 }
1234
1235 bool containerSkipped;
cdumez@apple.com225ce472014-10-15 05:01:31 +00001236 RenderElement* container = this->container(repaintContainer, &containerSkipped);
1237 if (!container)
mitz@apple.coma0c027c2009-10-27 23:32:44 +00001238 return;
1239
cdumez@apple.com225ce472014-10-15 05:01:31 +00001240 if (mode & ApplyContainerFlip && is<RenderBox>(*container)) {
1241 if (container->style().isFlippedBlocksWritingMode()) {
zalan@apple.com83de8f82014-08-26 02:11:44 +00001242 LayoutPoint centerPoint(transformState.mappedPoint());
cdumez@apple.com225ce472014-10-15 05:01:31 +00001243 transformState.move(downcast<RenderBox>(*container).flipForWritingMode(centerPoint) - centerPoint);
mitz@apple.comf9967cb2012-07-19 20:46:03 +00001244 }
leviw@chromium.org0d464292012-08-03 22:23:42 +00001245 mode &= ~ApplyContainerFlip;
mitz@apple.come2feae92012-05-03 16:32:33 +00001246 }
hyatt@apple.com61bbedf2011-01-26 23:10:57 +00001247
cdumez@apple.com225ce472014-10-15 05:01:31 +00001248 LayoutSize containerOffset = offsetFromContainer(*container, LayoutPoint(transformState.mappedPoint()));
mitz@apple.coma0c027c2009-10-27 23:32:44 +00001249
cdumez@apple.com225ce472014-10-15 05:01:31 +00001250 bool preserve3D = mode & UseTransforms && (container->style().preserves3D() || style().preserves3D());
1251 if (mode & UseTransforms && shouldUseTransformFromContainer(container)) {
mitz@apple.coma0c027c2009-10-27 23:32:44 +00001252 TransformationMatrix t;
cdumez@apple.com225ce472014-10-15 05:01:31 +00001253 getTransformFromContainer(container, containerOffset, t);
mitz@apple.coma0c027c2009-10-27 23:32:44 +00001254 transformState.applyTransform(t, preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
1255 } else
1256 transformState.move(containerOffset.width(), containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
1257
1258 if (containerSkipped) {
1259 // There can't be a transform between repaintContainer and o, because transforms create containers, so it should be safe
1260 // to just subtract the delta between the repaintContainer and o.
cdumez@apple.com225ce472014-10-15 05:01:31 +00001261 LayoutSize containerOffset = repaintContainer->offsetFromAncestorContainer(*container);
mitz@apple.coma0c027c2009-10-27 23:32:44 +00001262 transformState.move(-containerOffset.width(), -containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
1263 return;
1264 }
1265
cdumez@apple.com225ce472014-10-15 05:01:31 +00001266 container->mapLocalToContainer(repaintContainer, transformState, mode, wasFixed);
mitz@apple.coma0c027c2009-10-27 23:32:44 +00001267}
1268
fmalita@chromium.org49d26f22012-10-01 22:04:56 +00001269const RenderObject* RenderInline::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
simon.fraser@apple.comca41ec62012-05-25 21:42:32 +00001270{
1271 ASSERT(ancestorToStopAt != this);
1272
1273 bool ancestorSkipped;
akling@apple.comc096ce42013-09-23 23:55:20 +00001274 RenderElement* container = this->container(ancestorToStopAt, &ancestorSkipped);
simon.fraser@apple.comca41ec62012-05-25 21:42:32 +00001275 if (!container)
cdumez@apple.com225ce472014-10-15 05:01:31 +00001276 return nullptr;
simon.fraser@apple.comca41ec62012-05-25 21:42:32 +00001277
simon.fraser@apple.comca41ec62012-05-25 21:42:32 +00001278 LayoutSize adjustmentForSkippedAncestor;
1279 if (ancestorSkipped) {
1280 // There can't be a transform between repaintContainer and o, because transforms create containers, so it should be safe
1281 // to just subtract the delta between the ancestor and o.
cdumez@apple.com225ce472014-10-15 05:01:31 +00001282 adjustmentForSkippedAncestor = -ancestorToStopAt->offsetFromAncestorContainer(*container);
simon.fraser@apple.comca41ec62012-05-25 21:42:32 +00001283 }
1284
simon.fraser@apple.com0e7f7d92012-05-27 00:43:12 +00001285 bool offsetDependsOnPoint = false;
cdumez@apple.com225ce472014-10-15 05:01:31 +00001286 LayoutSize containerOffset = offsetFromContainer(*container, LayoutPoint(), &offsetDependsOnPoint);
simon.fraser@apple.comca41ec62012-05-25 21:42:32 +00001287
akling@apple.com827be9c2013-10-29 02:58:43 +00001288 bool preserve3D = container->style().preserves3D() || style().preserves3D();
simon.fraser@apple.comca41ec62012-05-25 21:42:32 +00001289 if (shouldUseTransformFromContainer(container)) {
1290 TransformationMatrix t;
1291 getTransformFromContainer(container, containerOffset, t);
1292 t.translateRight(adjustmentForSkippedAncestor.width(), adjustmentForSkippedAncestor.height()); // FIXME: right?
1293 geometryMap.push(this, t, preserve3D, offsetDependsOnPoint);
1294 } else {
1295 containerOffset += adjustmentForSkippedAncestor;
1296 geometryMap.push(this, containerOffset, preserve3D, offsetDependsOnPoint);
1297 }
1298
1299 return ancestorSkipped ? ancestorToStopAt : container;
1300}
1301
hyatt@apple.comcd6f8952009-01-28 17:30:26 +00001302void RenderInline::updateDragState(bool dragOn)
1303{
hyatt@apple.com0d4818f2009-02-08 05:39:22 +00001304 RenderBoxModelObject::updateDragState(dragOn);
akling@apple.com194c6fc2013-09-24 16:20:20 +00001305 if (RenderBoxModelObject* continuation = this->continuation())
1306 continuation->updateDragState(dragOn);
hyatt@apple.comcd6f8952009-01-28 17:30:26 +00001307}
1308
commit-queue@webkit.org1ce868f2013-03-09 01:37:10 +00001309void RenderInline::childBecameNonInline(RenderObject* child)
1310{
1311 // We have to split the parent flow.
1312 RenderBlock* newBox = containingBlock()->createAnonymousBlock();
1313 RenderBoxModelObject* oldContinuation = continuation();
1314 setContinuation(newBox);
1315 RenderObject* beforeChild = child->nextSibling();
akling@apple.com49d4d3b2013-10-16 12:40:09 +00001316 removeChildInternal(*child, NotifyChildren);
commit-queue@webkit.org1ce868f2013-03-09 01:37:10 +00001317 splitFlow(beforeChild, newBox, child, oldContinuation);
1318}
1319
eae@chromium.org3108e1d2011-07-10 19:20:37 +00001320void RenderInline::updateHitTestResult(HitTestResult& result, const LayoutPoint& point)
hyatt@apple.comcd6f8952009-01-28 17:30:26 +00001321{
1322 if (result.innerNode())
1323 return;
1324
eae@chromium.org3108e1d2011-07-10 19:20:37 +00001325 LayoutPoint localPoint(point);
antti@apple.com8f335082013-09-09 19:54:33 +00001326 if (Element* element = this->element()) {
hyatt@apple.comca8ce862010-05-22 04:23:04 +00001327 if (isInlineElementContinuation()) {
hyatt@apple.comcd6f8952009-01-28 17:30:26 +00001328 // We're in the continuation of a split inline. Adjust our local point to be in the coordinate space
1329 // of the principal renderer's containing block. This will end up being the innerNonSharedNode.
antti@apple.com8f335082013-09-09 19:54:33 +00001330 RenderBlock* firstBlock = element->renderer()->containingBlock();
hyatt@apple.comcd6f8952009-01-28 17:30:26 +00001331
1332 // Get our containing block.
hyatt@apple.com0d4818f2009-02-08 05:39:22 +00001333 RenderBox* block = containingBlock();
eae@chromium.org1146f212012-07-18 22:06:34 +00001334 localPoint.moveBy(block->location() - firstBlock->locationOffset());
hyatt@apple.comcd6f8952009-01-28 17:30:26 +00001335 }
1336
antti@apple.com8f335082013-09-09 19:54:33 +00001337 result.setInnerNode(element);
hyatt@apple.comcd6f8952009-01-28 17:30:26 +00001338 if (!result.innerNonSharedNode())
antti@apple.com8f335082013-09-09 19:54:33 +00001339 result.setInnerNonSharedNode(element);
hyatt@apple.comcd6f8952009-01-28 17:30:26 +00001340 result.setLocalPoint(localPoint);
1341 }
1342}
1343
hyatt@apple.comc92b7352009-02-12 01:35:08 +00001344void RenderInline::dirtyLineBoxes(bool fullLayout)
hyatt@apple.comd5c8cb62009-01-29 02:11:08 +00001345{
hyatt@apple.coma61b8a32011-04-06 18:20:52 +00001346 if (fullLayout) {
akling@apple.com31dd4f42013-10-30 22:27:59 +00001347 m_lineBoxes.deleteLineBoxes();
hyatt@apple.coma61b8a32011-04-06 18:20:52 +00001348 return;
1349 }
1350
1351 if (!alwaysCreateLineBoxes()) {
1352 // We have to grovel into our children in order to dirty the appropriate lines.
cdumez@apple.com35094bd2014-10-07 19:33:53 +00001353 for (RenderObject* current = firstChild(); current; current = current->nextSibling()) {
1354 if (current->isFloatingOrOutOfFlowPositioned())
hyatt@apple.coma61b8a32011-04-06 18:20:52 +00001355 continue;
cdumez@apple.com35094bd2014-10-07 19:33:53 +00001356 if (is<RenderBox>(*current) && !current->needsLayout()) {
1357 RenderBox& renderBox = downcast<RenderBox>(*current);
1358 if (renderBox.inlineBoxWrapper())
1359 renderBox.inlineBoxWrapper()->root().markDirty();
1360 } else if (!current->selfNeedsLayout()) {
1361 if (is<RenderInline>(*current)) {
1362 RenderInline& renderInline = downcast<RenderInline>(*current);
1363 for (InlineFlowBox* childLine = renderInline.firstLineBox(); childLine; childLine = childLine->nextLineBox())
akling@apple.comdbf70302013-09-09 02:11:06 +00001364 childLine->root().markDirty();
cdumez@apple.com35094bd2014-10-07 19:33:53 +00001365 } else if (is<RenderText>(*current)) {
1366 RenderText& renderText = downcast<RenderText>(*current);
1367 for (InlineTextBox* childText = renderText.firstTextBox(); childText; childText = childText->nextTextBox())
akling@apple.comdbf70302013-09-09 02:11:06 +00001368 childText->root().markDirty();
cdumez@apple.com35094bd2014-10-07 19:33:53 +00001369 } else if (is<RenderLineBreak>(*current)) {
1370 RenderLineBreak& renderBR = downcast<RenderLineBreak>(*current);
1371 if (renderBR.inlineBoxWrapper())
1372 renderBR.inlineBoxWrapper()->root().markDirty();
hyatt@apple.coma61b8a32011-04-06 18:20:52 +00001373 }
1374 }
1375 }
1376 } else
hyatt@apple.comd5c8cb62009-01-29 02:11:08 +00001377 m_lineBoxes.dirtyLineBoxes();
1378}
1379
antti@apple.coma2c7f242013-10-22 22:37:25 +00001380void RenderInline::deleteLines()
inferno@chromium.orgf531ade2012-05-22 01:36:43 +00001381{
akling@apple.com31dd4f42013-10-30 22:27:59 +00001382 m_lineBoxes.deleteLineBoxTree();
inferno@chromium.orgf531ade2012-05-22 01:36:43 +00001383}
1384
akling@apple.comb5f24642013-11-06 04:47:12 +00001385std::unique_ptr<InlineFlowBox> RenderInline::createInlineFlowBox()
hyatt@apple.comc3c7e902009-01-28 21:48:33 +00001386{
akling@apple.comb5f24642013-11-06 04:47:12 +00001387 return std::make_unique<InlineFlowBox>(*this);
hyatt@apple.comc92b7352009-02-12 01:35:08 +00001388}
1389
eric@webkit.org49b9d952009-07-03 01:29:07 +00001390InlineFlowBox* RenderInline::createAndAppendInlineFlowBox()
hyatt@apple.comc92b7352009-02-12 01:35:08 +00001391{
hyatt@apple.coma61b8a32011-04-06 18:20:52 +00001392 setAlwaysCreateLineBoxes();
akling@apple.comb5f24642013-11-06 04:47:12 +00001393 auto newFlowBox = createInlineFlowBox();
1394 auto flowBox = newFlowBox.get();
dbates@webkit.org0cefe4f2014-07-03 22:13:54 +00001395 m_lineBoxes.appendLineBox(WTF::move(newFlowBox));
hyatt@apple.comc3c7e902009-01-28 21:48:33 +00001396 return flowBox;
1397}
1398
leviw@chromium.orgfc300232011-08-18 19:23:22 +00001399LayoutUnit RenderInline::lineHeight(bool firstLine, LineDirectionMode /*direction*/, LinePositionMode /*linePositionMode*/) const
hyatt@apple.com7c5bd582009-01-28 19:31:46 +00001400{
benjamin@webkit.org23358d72013-09-25 21:13:38 +00001401 if (firstLine && document().styleSheetCollection().usesFirstLineRules()) {
akling@apple.com827be9c2013-10-29 02:58:43 +00001402 const RenderStyle& firstLineStyle = this->firstLineStyle();
1403 if (&firstLineStyle != &style())
bjonesbe@adobe.com830e80f2014-05-28 01:33:26 +00001404 return firstLineStyle.computedLineHeight();
hyatt@apple.com7c5bd582009-01-28 19:31:46 +00001405 }
kling@webkit.orge19e6cf2012-01-24 20:22:00 +00001406
bjonesbe@adobe.com830e80f2014-05-28 01:33:26 +00001407 return style().computedLineHeight();
hyatt@apple.com7c5bd582009-01-28 19:31:46 +00001408}
1409
eae@chromium.org82b94982012-10-22 18:38:29 +00001410int RenderInline::baselinePosition(FontBaseline baselineType, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const
hyatt@apple.comddd8c302010-10-19 18:38:14 +00001411{
akling@apple.com827be9c2013-10-29 02:58:43 +00001412 const RenderStyle& style = firstLine ? firstLineStyle() : this->style();
antti@apple.comb0608f62013-09-28 18:30:16 +00001413 const FontMetrics& fontMetrics = style.fontMetrics();
zimmermann@webkit.orge8433cc2011-01-22 11:46:23 +00001414 return fontMetrics.ascent(baselineType) + (lineHeight(firstLine, direction, linePositionMode) - fontMetrics.height()) / 2;
hyatt@apple.com4f81f3e2009-02-10 23:00:37 +00001415}
1416
simon.fraser@apple.comea93fa02012-08-24 00:52:53 +00001417LayoutSize RenderInline::offsetForInFlowPositionedInline(const RenderBox* child) const
hyatt@apple.com76dbdb52009-01-29 22:49:13 +00001418{
hyatt@apple.come16585a2011-02-28 23:21:36 +00001419 // FIXME: This function isn't right with mixed writing modes.
1420
simon.fraser@apple.comea93fa02012-08-24 00:52:53 +00001421 ASSERT(isInFlowPositioned());
1422 if (!isInFlowPositioned())
eae@chromium.orga468a4a2011-07-07 02:32:26 +00001423 return LayoutSize();
hyatt@apple.com76dbdb52009-01-29 22:49:13 +00001424
1425 // When we have an enclosing relpositioned inline, we need to add in the offset of the first line
1426 // box from the rest of the content, but only in the cases where we know we're positioned
1427 // relative to the inline itself.
1428
eae@chromium.orga468a4a2011-07-07 02:32:26 +00001429 LayoutSize logicalOffset;
1430 LayoutUnit inlinePosition;
1431 LayoutUnit blockPosition;
hyatt@apple.com76dbdb52009-01-29 22:49:13 +00001432 if (firstLineBox()) {
zalan@apple.com81badc12014-08-26 19:29:09 +00001433 inlinePosition = LayoutUnit::fromFloatRound(firstLineBox()->logicalLeft());
hyatt@apple.come16585a2011-02-28 23:21:36 +00001434 blockPosition = firstLineBox()->logicalTop();
hyatt@apple.com76dbdb52009-01-29 22:49:13 +00001435 } else {
hyatt@apple.come16585a2011-02-28 23:21:36 +00001436 inlinePosition = layer()->staticInlinePosition();
1437 blockPosition = layer()->staticBlockPosition();
hyatt@apple.com76dbdb52009-01-29 22:49:13 +00001438 }
1439
akling@apple.com827be9c2013-10-29 02:58:43 +00001440 if (!child->style().hasStaticInlinePosition(style().isHorizontalWritingMode()))
hyatt@apple.come16585a2011-02-28 23:21:36 +00001441 logicalOffset.setWidth(inlinePosition);
1442
hyatt@apple.com76dbdb52009-01-29 22:49:13 +00001443 // This is not terribly intuitive, but we have to match other browsers. Despite being a block display type inside
1444 // an inline, we still keep our x locked to the left of the relative positioned inline. Arguably the correct
1445 // behavior would be to go flush left to the block that contains the inline, but that isn't what other browsers
1446 // do.
akling@apple.com827be9c2013-10-29 02:58:43 +00001447 else if (!child->style().isOriginalDisplayInlineType())
hyatt@apple.com76dbdb52009-01-29 22:49:13 +00001448 // Avoid adding in the left border/padding of the containing block twice. Subtract it out.
hyatt@apple.come16585a2011-02-28 23:21:36 +00001449 logicalOffset.setWidth(inlinePosition - child->containingBlock()->borderAndPaddingLogicalLeft());
hyatt@apple.com76dbdb52009-01-29 22:49:13 +00001450
akling@apple.com827be9c2013-10-29 02:58:43 +00001451 if (!child->style().hasStaticBlockPosition(style().isHorizontalWritingMode()))
hyatt@apple.come16585a2011-02-28 23:21:36 +00001452 logicalOffset.setHeight(blockPosition);
hyatt@apple.com76dbdb52009-01-29 22:49:13 +00001453
akling@apple.com827be9c2013-10-29 02:58:43 +00001454 return style().isHorizontalWritingMode() ? logicalOffset : logicalOffset.transposedSize();
hyatt@apple.com76dbdb52009-01-29 22:49:13 +00001455}
1456
hyatt@apple.com0d4818f2009-02-08 05:39:22 +00001457void RenderInline::imageChanged(WrappedImagePtr, const IntRect*)
1458{
1459 if (!parent())
1460 return;
1461
1462 // FIXME: We can do better.
1463 repaint();
1464}
1465
wangxianzhu@chromium.org64f38292013-02-28 20:38:23 +00001466void RenderInline::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer)
hyatt@apple.com9bfe16c2009-01-28 23:44:41 +00001467{
commit-queue@webkit.org39f4e3f2012-07-17 03:26:00 +00001468 AbsoluteRectsGeneratorContext context(rects, additionalOffset);
1469 generateLineBoxRects(context);
hyatt@apple.com9bfe16c2009-01-28 23:44:41 +00001470
weinig@apple.comc77041e2013-12-14 18:05:45 +00001471 for (auto& child : childrenOfType<RenderElement>(*this)) {
cdumez@apple.com0abff8b2014-10-17 21:25:10 +00001472 if (is<RenderListMarker>(child))
akling@apple.com1626ee02013-11-04 12:55:48 +00001473 continue;
1474 FloatPoint pos(additionalOffset);
1475 // FIXME: This doesn't work correctly with transforms.
weinig@apple.comc77041e2013-12-14 18:05:45 +00001476 if (child.hasLayer())
1477 pos = child.localToContainerPoint(FloatPoint(), paintContainer);
cdumez@apple.com0abff8b2014-10-17 21:25:10 +00001478 else if (is<RenderBox>(child))
1479 pos.move(downcast<RenderBox>(child).locationOffset());
weinig@apple.comc77041e2013-12-14 18:05:45 +00001480 child.addFocusRingRects(rects, flooredIntPoint(pos), paintContainer);
hyatt@apple.com9bfe16c2009-01-28 23:44:41 +00001481 }
1482
akling@apple.com194c6fc2013-09-24 16:20:20 +00001483 if (RenderBoxModelObject* continuation = this->continuation()) {
1484 if (continuation->isInline())
zalan@apple.comb9d20ae2014-02-12 20:34:57 +00001485 continuation->addFocusRingRects(rects, flooredLayoutPoint(LayoutPoint(additionalOffset + continuation->containingBlock()->location() - containingBlock()->location())), paintContainer);
hyatt@apple.com0d4818f2009-02-08 05:39:22 +00001486 else
cdumez@apple.com0abff8b2014-10-17 21:25:10 +00001487 continuation->addFocusRingRects(rects, flooredLayoutPoint(LayoutPoint(additionalOffset + downcast<RenderBox>(*continuation).location() - containingBlock()->location())), paintContainer);
hyatt@apple.com0d4818f2009-02-08 05:39:22 +00001488 }
hyatt@apple.com9bfe16c2009-01-28 23:44:41 +00001489}
1490
wangxianzhu@chromium.org64f38292013-02-28 20:38:23 +00001491void RenderInline::paintOutline(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
hyatt@apple.comced257d2009-01-29 01:33:16 +00001492{
1493 if (!hasOutline())
1494 return;
dino@apple.com6abd3342014-05-07 20:03:13 +00001495
akling@apple.com827be9c2013-10-29 02:58:43 +00001496 RenderStyle& styleToUse = style();
dino@apple.comc589bac2014-05-07 02:58:39 +00001497 // Only paint the focus ring by hand if the theme isn't able to draw it.
achristensen@apple.com9fb77fc2014-06-25 21:04:17 +00001498 if (styleToUse.outlineStyleIsAuto() && !theme().supportsFocusRing(styleToUse))
dino@apple.comc589bac2014-05-07 02:58:39 +00001499 paintFocusRing(paintInfo, paintOffset, &styleToUse);
dino@apple.com6abd3342014-05-07 20:03:13 +00001500
achristensen@apple.com9fb77fc2014-06-25 21:04:17 +00001501 if (hasOutlineAnnotation() && !styleToUse.outlineStyleIsAuto() && !theme().supportsFocusRing(styleToUse))
dino@apple.comc589bac2014-05-07 02:58:39 +00001502 addPDFURLRect(paintInfo, paintOffset);
hyatt@apple.comced257d2009-01-29 01:33:16 +00001503
wangxianzhu@chromium.org64f38292013-02-28 20:38:23 +00001504 GraphicsContext* graphicsContext = paintInfo.context;
simon.fraser@apple.com9650b152011-05-26 15:34:48 +00001505 if (graphicsContext->paintingDisabled())
1506 return;
1507
akling@apple.com827be9c2013-10-29 02:58:43 +00001508 if (styleToUse.outlineStyleIsAuto() || styleToUse.outlineStyle() == BNONE)
hyatt@apple.comced257d2009-01-29 01:33:16 +00001509 return;
1510
leviw@chromium.org890e9b02011-07-07 23:17:55 +00001511 Vector<LayoutRect> rects;
hyatt@apple.comced257d2009-01-29 01:33:16 +00001512
leviw@chromium.org890e9b02011-07-07 23:17:55 +00001513 rects.append(LayoutRect());
hyatt@apple.com9f47d582010-03-12 20:29:50 +00001514 for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
akling@apple.comdbf70302013-09-09 02:11:06 +00001515 const RootInlineBox& rootBox = curr->root();
andersca@apple.com86298632013-11-10 19:32:33 +00001516 LayoutUnit top = std::max<LayoutUnit>(rootBox.lineTop(), curr->logicalTop());
1517 LayoutUnit bottom = std::min<LayoutUnit>(rootBox.lineBottom(), curr->logicalBottom());
leviw@chromium.org890e9b02011-07-07 23:17:55 +00001518 rects.append(LayoutRect(curr->x(), top, curr->logicalWidth(), bottom - top));
hyatt@apple.comd42ce1a2009-08-21 22:19:51 +00001519 }
leviw@chromium.org890e9b02011-07-07 23:17:55 +00001520 rects.append(LayoutRect());
hyatt@apple.comced257d2009-01-29 01:33:16 +00001521
akling@apple.com827be9c2013-10-29 02:58:43 +00001522 Color outlineColor = styleToUse.visitedDependentColor(CSSPropertyOutlineColor);
commit-queue@webkit.org550a18c2011-05-12 07:04:24 +00001523 bool useTransparencyLayer = outlineColor.hasAlpha();
1524 if (useTransparencyLayer) {
1525 graphicsContext->beginTransparencyLayer(static_cast<float>(outlineColor.alpha()) / 255);
1526 outlineColor = Color(outlineColor.red(), outlineColor.green(), outlineColor.blue());
1527 }
commit-queue@webkit.org550a18c2011-05-12 07:04:24 +00001528
hyatt@apple.comced257d2009-01-29 01:33:16 +00001529 for (unsigned i = 1; i < rects.size() - 1; i++)
leviw@chromium.org07d86ca2011-06-06 21:35:56 +00001530 paintOutlineForLine(graphicsContext, paintOffset, rects.at(i - 1), rects.at(i), rects.at(i + 1), outlineColor);
commit-queue@webkit.org550a18c2011-05-12 07:04:24 +00001531
commit-queue@webkit.org550a18c2011-05-12 07:04:24 +00001532 if (useTransparencyLayer)
1533 graphicsContext->endTransparencyLayer();
hyatt@apple.comced257d2009-01-29 01:33:16 +00001534}
1535
leviw@chromium.org890e9b02011-07-07 23:17:55 +00001536void RenderInline::paintOutlineForLine(GraphicsContext* graphicsContext, const LayoutPoint& paintOffset,
1537 const LayoutRect& lastline, const LayoutRect& thisline, const LayoutRect& nextline,
commit-queue@webkit.org550a18c2011-05-12 07:04:24 +00001538 const Color outlineColor)
hyatt@apple.comced257d2009-01-29 01:33:16 +00001539{
akling@apple.com827be9c2013-10-29 02:58:43 +00001540 const RenderStyle& styleToUse = style();
1541 int outlineWidth = styleToUse.outlineWidth();
1542 EBorderStyle outlineStyle = styleToUse.outlineStyle();
hyatt@apple.comced257d2009-01-29 01:33:16 +00001543
darin@apple.comafab5aa2011-09-23 03:00:38 +00001544 bool antialias = shouldAntialiasLines(graphicsContext);
simon.fraser@apple.com9650b152011-05-26 15:34:48 +00001545
akling@apple.com827be9c2013-10-29 02:58:43 +00001546 int offset = style().outlineOffset();
hyatt@apple.comced257d2009-01-29 01:33:16 +00001547
leviw@chromium.orgc38fcdf2012-02-24 03:55:53 +00001548 LayoutRect box(LayoutPoint(paintOffset.x() + thisline.x() - offset, paintOffset.y() + thisline.y() - offset),
1549 LayoutSize(thisline.width() + offset, thisline.height() + offset));
1550
zalan@apple.com376339c2014-08-28 04:24:31 +00001551 IntRect pixelSnappedBox = snappedIntRect(box);
rwlbuis@webkit.org0be79dc2013-08-14 19:14:00 +00001552 if (pixelSnappedBox.isEmpty())
1553 return;
zalan@apple.com376339c2014-08-28 04:24:31 +00001554 IntRect pixelSnappedLastLine = snappedIntRect(paintOffset.x() + lastline.x(), 0, lastline.width(), 0);
1555 IntRect pixelSnappedNextLine = snappedIntRect(paintOffset.x() + nextline.x(), 0, nextline.width(), 0);
hyatt@apple.comced257d2009-01-29 01:33:16 +00001556
1557 // left edge
hyatt@apple.come68a9c02009-02-12 19:28:24 +00001558 drawLineForBoxSide(graphicsContext,
leviw@chromium.orgc38fcdf2012-02-24 03:55:53 +00001559 pixelSnappedBox.x() - outlineWidth,
1560 pixelSnappedBox.y() - (lastline.isEmpty() || thisline.x() < lastline.x() || (lastline.maxX() - 1) <= thisline.x() ? outlineWidth : 0),
1561 pixelSnappedBox.x(),
1562 pixelSnappedBox.maxY() + (nextline.isEmpty() || thisline.x() <= nextline.x() || (nextline.maxX() - 1) <= thisline.x() ? outlineWidth : 0),
leviw@chromium.org890e9b02011-07-07 23:17:55 +00001563 BSLeft,
1564 outlineColor, outlineStyle,
1565 (lastline.isEmpty() || thisline.x() < lastline.x() || (lastline.maxX() - 1) <= thisline.x() ? outlineWidth : -outlineWidth),
1566 (nextline.isEmpty() || thisline.x() <= nextline.x() || (nextline.maxX() - 1) <= thisline.x() ? outlineWidth : -outlineWidth),
1567 antialias);
hyatt@apple.comced257d2009-01-29 01:33:16 +00001568
1569 // right edge
hyatt@apple.come68a9c02009-02-12 19:28:24 +00001570 drawLineForBoxSide(graphicsContext,
leviw@chromium.orgc38fcdf2012-02-24 03:55:53 +00001571 pixelSnappedBox.maxX(),
1572 pixelSnappedBox.y() - (lastline.isEmpty() || lastline.maxX() < thisline.maxX() || (thisline.maxX() - 1) <= lastline.x() ? outlineWidth : 0),
1573 pixelSnappedBox.maxX() + outlineWidth,
1574 pixelSnappedBox.maxY() + (nextline.isEmpty() || nextline.maxX() <= thisline.maxX() || (thisline.maxX() - 1) <= nextline.x() ? outlineWidth : 0),
leviw@chromium.org890e9b02011-07-07 23:17:55 +00001575 BSRight,
1576 outlineColor, outlineStyle,
1577 (lastline.isEmpty() || lastline.maxX() < thisline.maxX() || (thisline.maxX() - 1) <= lastline.x() ? outlineWidth : -outlineWidth),
1578 (nextline.isEmpty() || nextline.maxX() <= thisline.maxX() || (thisline.maxX() - 1) <= nextline.x() ? outlineWidth : -outlineWidth),
1579 antialias);
hyatt@apple.comced257d2009-01-29 01:33:16 +00001580 // upper edge
1581 if (thisline.x() < lastline.x())
hyatt@apple.come68a9c02009-02-12 19:28:24 +00001582 drawLineForBoxSide(graphicsContext,
leviw@chromium.orgc38fcdf2012-02-24 03:55:53 +00001583 pixelSnappedBox.x() - outlineWidth,
1584 pixelSnappedBox.y() - outlineWidth,
andersca@apple.com86298632013-11-10 19:32:33 +00001585 std::min(pixelSnappedBox.maxX() + outlineWidth, (lastline.isEmpty() ? 1000000 : pixelSnappedLastLine.x())),
leviw@chromium.orgc38fcdf2012-02-24 03:55:53 +00001586 pixelSnappedBox.y(),
leviw@chromium.org890e9b02011-07-07 23:17:55 +00001587 BSTop, outlineColor, outlineStyle,
1588 outlineWidth,
leviw@chromium.orgc38fcdf2012-02-24 03:55:53 +00001589 (!lastline.isEmpty() && paintOffset.x() + lastline.x() + 1 < pixelSnappedBox.maxX() + outlineWidth) ? -outlineWidth : outlineWidth,
leviw@chromium.org890e9b02011-07-07 23:17:55 +00001590 antialias);
hyatt@apple.comced257d2009-01-29 01:33:16 +00001591
hyatt@apple.comaa0cba02011-02-01 21:39:47 +00001592 if (lastline.maxX() < thisline.maxX())
hyatt@apple.come68a9c02009-02-12 19:28:24 +00001593 drawLineForBoxSide(graphicsContext,
andersca@apple.com86298632013-11-10 19:32:33 +00001594 std::max(lastline.isEmpty() ? -1000000 : pixelSnappedLastLine.maxX(), pixelSnappedBox.x() - outlineWidth),
leviw@chromium.orgc38fcdf2012-02-24 03:55:53 +00001595 pixelSnappedBox.y() - outlineWidth,
1596 pixelSnappedBox.maxX() + outlineWidth,
1597 pixelSnappedBox.y(),
leviw@chromium.org890e9b02011-07-07 23:17:55 +00001598 BSTop, outlineColor, outlineStyle,
leviw@chromium.orgc38fcdf2012-02-24 03:55:53 +00001599 (!lastline.isEmpty() && pixelSnappedBox.x() - outlineWidth < paintOffset.x() + lastline.maxX()) ? -outlineWidth : outlineWidth,
leviw@chromium.org890e9b02011-07-07 23:17:55 +00001600 outlineWidth, antialias);
robert@webkit.org0ef594d2011-09-22 16:14:30 +00001601
1602 if (thisline.x() == thisline.maxX())
1603 drawLineForBoxSide(graphicsContext,
leviw@chromium.orgc38fcdf2012-02-24 03:55:53 +00001604 pixelSnappedBox.x() - outlineWidth,
1605 pixelSnappedBox.y() - outlineWidth,
1606 pixelSnappedBox.maxX() + outlineWidth,
1607 pixelSnappedBox.y(),
robert@webkit.org0ef594d2011-09-22 16:14:30 +00001608 BSTop, outlineColor, outlineStyle,
1609 outlineWidth,
1610 outlineWidth,
1611 antialias);
1612
hyatt@apple.comced257d2009-01-29 01:33:16 +00001613 // lower edge
1614 if (thisline.x() < nextline.x())
hyatt@apple.come68a9c02009-02-12 19:28:24 +00001615 drawLineForBoxSide(graphicsContext,
leviw@chromium.orgc38fcdf2012-02-24 03:55:53 +00001616 pixelSnappedBox.x() - outlineWidth,
1617 pixelSnappedBox.maxY(),
andersca@apple.com86298632013-11-10 19:32:33 +00001618 std::min(pixelSnappedBox.maxX() + outlineWidth, !nextline.isEmpty() ? pixelSnappedNextLine.x() + 1 : 1000000),
leviw@chromium.orgc38fcdf2012-02-24 03:55:53 +00001619 pixelSnappedBox.maxY() + outlineWidth,
leviw@chromium.org890e9b02011-07-07 23:17:55 +00001620 BSBottom, outlineColor, outlineStyle,
1621 outlineWidth,
leviw@chromium.orgc38fcdf2012-02-24 03:55:53 +00001622 (!nextline.isEmpty() && paintOffset.x() + nextline.x() + 1 < pixelSnappedBox.maxX() + outlineWidth) ? -outlineWidth : outlineWidth,
leviw@chromium.org890e9b02011-07-07 23:17:55 +00001623 antialias);
hyatt@apple.comced257d2009-01-29 01:33:16 +00001624
hyatt@apple.comaa0cba02011-02-01 21:39:47 +00001625 if (nextline.maxX() < thisline.maxX())
hyatt@apple.come68a9c02009-02-12 19:28:24 +00001626 drawLineForBoxSide(graphicsContext,
andersca@apple.com86298632013-11-10 19:32:33 +00001627 std::max(!nextline.isEmpty() ? pixelSnappedNextLine.maxX() : -1000000, pixelSnappedBox.x() - outlineWidth),
leviw@chromium.orgc38fcdf2012-02-24 03:55:53 +00001628 pixelSnappedBox.maxY(),
1629 pixelSnappedBox.maxX() + outlineWidth,
1630 pixelSnappedBox.maxY() + outlineWidth,
leviw@chromium.org890e9b02011-07-07 23:17:55 +00001631 BSBottom, outlineColor, outlineStyle,
leviw@chromium.orgc38fcdf2012-02-24 03:55:53 +00001632 (!nextline.isEmpty() && pixelSnappedBox.x() - outlineWidth < paintOffset.x() + nextline.maxX()) ? -outlineWidth : outlineWidth,
leviw@chromium.org890e9b02011-07-07 23:17:55 +00001633 outlineWidth, antialias);
robert@webkit.org0ef594d2011-09-22 16:14:30 +00001634
1635 if (thisline.x() == thisline.maxX())
1636 drawLineForBoxSide(graphicsContext,
leviw@chromium.orgc38fcdf2012-02-24 03:55:53 +00001637 pixelSnappedBox.x() - outlineWidth,
1638 pixelSnappedBox.maxY(),
1639 pixelSnappedBox.maxX() + outlineWidth,
1640 pixelSnappedBox.maxY() + outlineWidth,
robert@webkit.org0ef594d2011-09-22 16:14:30 +00001641 BSBottom, outlineColor, outlineStyle,
1642 outlineWidth,
1643 outlineWidth,
1644 antialias);
hyatt@apple.comced257d2009-01-29 01:33:16 +00001645}
1646
commit-queue@webkit.org85192c52014-01-26 06:25:55 +00001647#if ENABLE(DASHBOARD_SUPPORT)
jianli@chromium.orgbd81dfe2012-10-10 00:06:59 +00001648void RenderInline::addAnnotatedRegions(Vector<AnnotatedRegionValue>& regions)
bdakin@apple.come3d43bb2009-02-05 00:19:31 +00001649{
1650 // Convert the style regions to absolute coordinates.
akling@apple.com827be9c2013-10-29 02:58:43 +00001651 if (style().visibility() != VISIBLE)
bdakin@apple.come3d43bb2009-02-05 00:19:31 +00001652 return;
1653
akling@apple.com827be9c2013-10-29 02:58:43 +00001654 const Vector<StyleDashboardRegion>& styleRegions = style().dashboardRegions();
bdakin@apple.come3d43bb2009-02-05 00:19:31 +00001655 unsigned i, count = styleRegions.size();
1656 for (i = 0; i < count; i++) {
1657 StyleDashboardRegion styleRegion = styleRegions[i];
1658
leviw@chromium.orgfc300232011-08-18 19:23:22 +00001659 LayoutRect linesBoundingBox = this->linesBoundingBox();
1660 LayoutUnit w = linesBoundingBox.width();
1661 LayoutUnit h = linesBoundingBox.height();
bdakin@apple.come3d43bb2009-02-05 00:19:31 +00001662
jianli@chromium.orgbd81dfe2012-10-10 00:06:59 +00001663 AnnotatedRegionValue region;
bdakin@apple.come3d43bb2009-02-05 00:19:31 +00001664 region.label = styleRegion.label;
leviw@chromium.orgfc300232011-08-18 19:23:22 +00001665 region.bounds = LayoutRect(linesBoundingBox.x() + styleRegion.offset.left().value(),
bdakin@apple.come3d43bb2009-02-05 00:19:31 +00001666 linesBoundingBox.y() + styleRegion.offset.top().value(),
1667 w - styleRegion.offset.left().value() - styleRegion.offset.right().value(),
1668 h - styleRegion.offset.top().value() - styleRegion.offset.bottom().value());
1669 region.type = styleRegion.type;
1670
1671 RenderObject* container = containingBlock();
1672 if (!container)
1673 container = this;
1674
1675 region.clip = region.bounds;
1676 container->computeAbsoluteRepaintRect(region.clip);
1677 if (region.clip.height() < 0) {
1678 region.clip.setHeight(0);
1679 region.clip.setWidth(0);
1680 }
1681
1682 FloatPoint absPos = container->localToAbsolute();
1683 region.bounds.setX(absPos.x() + region.bounds.x());
1684 region.bounds.setY(absPos.y() + region.bounds.y());
1685
bdakin@apple.come3d43bb2009-02-05 00:19:31 +00001686 regions.append(region);
1687 }
1688}
1689#endif
1690
weinigc24ab182006-10-30 22:41:29 +00001691} // namespace WebCore