Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / rendering / RenderBoxModelObject.cpp
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4  *           (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
5  *           (C) 2005, 2006 Samuel Weinig (sam.weinig@gmail.com)
6  * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
7  * Copyright (C) 2010 Google Inc. All rights reserved.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public License
20  * along with this library; see the file COPYING.LIB.  If not, write to
21  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22  * Boston, MA 02110-1301, USA.
23  *
24  */
25
26 #include "config.h"
27 #include "core/rendering/RenderBoxModelObject.h"
28
29 #include "core/page/scrolling/ScrollingConstraints.h"
30 #include "core/rendering/ImageQualityController.h"
31 #include "core/rendering/RenderBlock.h"
32 #include "core/rendering/RenderFlowThread.h"
33 #include "core/rendering/RenderGeometryMap.h"
34 #include "core/rendering/RenderInline.h"
35 #include "core/rendering/RenderLayer.h"
36 #include "core/rendering/RenderObjectInlines.h"
37 #include "core/rendering/RenderRegion.h"
38 #include "core/rendering/RenderTextFragment.h"
39 #include "core/rendering/RenderView.h"
40 #include "core/rendering/compositing/CompositedLayerMapping.h"
41 #include "core/rendering/compositing/RenderLayerCompositor.h"
42 #include "core/rendering/style/BorderEdge.h"
43 #include "core/rendering/style/ShadowList.h"
44 #include "platform/LengthFunctions.h"
45 #include "platform/geometry/TransformState.h"
46 #include "platform/graphics/DrawLooperBuilder.h"
47 #include "platform/graphics/GraphicsContextStateSaver.h"
48 #include "platform/graphics/Path.h"
49 #include "wtf/CurrentTime.h"
50
51 namespace blink {
52
53 // The HashMap for storing continuation pointers.
54 // An inline can be split with blocks occuring in between the inline content.
55 // When this occurs we need a pointer to the next object. We can basically be
56 // split into a sequence of inlines and blocks. The continuation will either be
57 // an anonymous block (that houses other blocks) or it will be an inline flow.
58 // <b><i><p>Hello</p></i></b>. In this example the <i> will have a block as
59 // its continuation but the <b> will just have an inline as its continuation.
60 typedef WillBeHeapHashMap<RawPtrWillBeMember<const RenderBoxModelObject>, RawPtrWillBeMember<RenderBoxModelObject> > ContinuationMap;
61 static OwnPtrWillBePersistent<ContinuationMap>* continuationMap = 0;
62
63 // This HashMap is similar to the continuation map, but connects first-letter
64 // renderers to their remaining text fragments.
65 typedef WillBeHeapHashMap<RawPtrWillBeMember<const RenderBoxModelObject>, RawPtrWillBeMember<RenderTextFragment> > FirstLetterRemainingTextMap;
66 static OwnPtrWillBePersistent<FirstLetterRemainingTextMap>* firstLetterRemainingTextMap = 0;
67
68 void RenderBoxModelObject::setSelectionState(SelectionState state)
69 {
70     if (state == SelectionInside && selectionState() != SelectionNone)
71         return;
72
73     if ((state == SelectionStart && selectionState() == SelectionEnd)
74         || (state == SelectionEnd && selectionState() == SelectionStart))
75         RenderObject::setSelectionState(SelectionBoth);
76     else
77         RenderObject::setSelectionState(state);
78
79     // FIXME: We should consider whether it is OK propagating to ancestor RenderInlines.
80     // This is a workaround for http://webkit.org/b/32123
81     // The containing block can be null in case of an orphaned tree.
82     RenderBlock* containingBlock = this->containingBlock();
83     if (containingBlock && !containingBlock->isRenderView())
84         containingBlock->setSelectionState(state);
85 }
86
87 void RenderBoxModelObject::contentChanged(ContentChangeType changeType)
88 {
89     if (!hasLayer())
90         return;
91
92     layer()->contentChanged(changeType);
93 }
94
95 bool RenderBoxModelObject::hasAcceleratedCompositing() const
96 {
97     return view()->compositor()->hasAcceleratedCompositing();
98 }
99
100 RenderBoxModelObject::RenderBoxModelObject(ContainerNode* node)
101     : RenderLayerModelObject(node)
102 {
103 }
104
105 RenderBoxModelObject::~RenderBoxModelObject()
106 {
107 }
108
109 void RenderBoxModelObject::willBeDestroyed()
110 {
111     ImageQualityController::remove(this);
112
113     // A continuation of this RenderObject should be destroyed at subclasses.
114     ASSERT(!continuation());
115
116     // If this is a first-letter object with a remaining text fragment then the
117     // entry needs to be cleared from the map.
118     if (firstLetterRemainingText())
119         setFirstLetterRemainingText(0);
120
121     RenderLayerModelObject::willBeDestroyed();
122 }
123
124 bool RenderBoxModelObject::calculateHasBoxDecorations() const
125 {
126     RenderStyle* styleToUse = style();
127     ASSERT(styleToUse);
128     return hasBackground() || styleToUse->hasBorder() || styleToUse->hasAppearance() || styleToUse->boxShadow();
129 }
130
131 void RenderBoxModelObject::updateFromStyle()
132 {
133     RenderLayerModelObject::updateFromStyle();
134
135     RenderStyle* styleToUse = style();
136     setHasBoxDecorationBackground(calculateHasBoxDecorations());
137     setInline(styleToUse->isDisplayInlineType());
138     setPositionState(styleToUse->position());
139     setHorizontalWritingMode(styleToUse->isHorizontalWritingMode());
140 }
141
142 static LayoutSize accumulateInFlowPositionOffsets(const RenderObject* child)
143 {
144     if (!child->isAnonymousBlock() || !child->isRelPositioned())
145         return LayoutSize();
146     LayoutSize offset;
147     RenderObject* p = toRenderBlock(child)->inlineElementContinuation();
148     while (p && p->isRenderInline()) {
149         if (p->isRelPositioned()) {
150             RenderInline* renderInline = toRenderInline(p);
151             offset += renderInline->offsetForInFlowPosition();
152         }
153         p = p->parent();
154     }
155     return offset;
156 }
157
158 bool RenderBoxModelObject::hasAutoHeightOrContainingBlockWithAutoHeight() const
159 {
160     Length logicalHeightLength = style()->logicalHeight();
161     if (logicalHeightLength.isAuto())
162         return true;
163
164     // For percentage heights: The percentage is calculated with respect to the height of the generated box's
165     // containing block. If the height of the containing block is not specified explicitly (i.e., it depends
166     // on content height), and this element is not absolutely positioned, the value computes to 'auto'.
167     if (!logicalHeightLength.isPercent() || isOutOfFlowPositioned() || document().inQuirksMode())
168         return false;
169
170     // Anonymous block boxes are ignored when resolving percentage values that would refer to it:
171     // the closest non-anonymous ancestor box is used instead.
172     RenderBlock* cb = containingBlock();
173     while (cb->isAnonymous())
174         cb = cb->containingBlock();
175
176     // Matching RenderBox::percentageLogicalHeightIsResolvableFromBlock() by
177     // ignoring table cell's attribute value, where it says that table cells violate
178     // what the CSS spec says to do with heights. Basically we
179     // don't care if the cell specified a height or not.
180     if (cb->isTableCell())
181         return false;
182
183     // Match RenderBox::availableLogicalHeightUsing by special casing
184     // the render view. The available height is taken from the frame.
185     if (cb->isRenderView())
186         return false;
187
188     if (cb->isOutOfFlowPositioned() && !cb->style()->logicalTop().isAuto() && !cb->style()->logicalBottom().isAuto())
189         return false;
190
191     // If the height of the containing block computes to 'auto', then it hasn't been 'specified explicitly'.
192     return cb->hasAutoHeightOrContainingBlockWithAutoHeight();
193 }
194
195 LayoutSize RenderBoxModelObject::relativePositionOffset() const
196 {
197     LayoutSize offset = accumulateInFlowPositionOffsets(this);
198
199     RenderBlock* containingBlock = this->containingBlock();
200
201     // Objects that shrink to avoid floats normally use available line width when computing containing block width.  However
202     // in the case of relative positioning using percentages, we can't do this.  The offset should always be resolved using the
203     // available width of the containing block.  Therefore we don't use containingBlockLogicalWidthForContent() here, but instead explicitly
204     // call availableWidth on our containing block.
205     if (!style()->left().isAuto()) {
206         if (!style()->right().isAuto() && !containingBlock->style()->isLeftToRightDirection())
207             offset.setWidth(-valueForLength(style()->right(), containingBlock->availableWidth()));
208         else
209             offset.expand(valueForLength(style()->left(), containingBlock->availableWidth()), 0);
210     } else if (!style()->right().isAuto()) {
211         offset.expand(-valueForLength(style()->right(), containingBlock->availableWidth()), 0);
212     }
213
214     // If the containing block of a relatively positioned element does not
215     // specify a height, a percentage top or bottom offset should be resolved as
216     // auto. An exception to this is if the containing block has the WinIE quirk
217     // where <html> and <body> assume the size of the viewport. In this case,
218     // calculate the percent offset based on this height.
219     // See <https://bugs.webkit.org/show_bug.cgi?id=26396>.
220     if (!style()->top().isAuto()
221         && (!containingBlock->hasAutoHeightOrContainingBlockWithAutoHeight()
222             || !style()->top().isPercent()
223             || containingBlock->stretchesToViewport()))
224         offset.expand(0, valueForLength(style()->top(), containingBlock->availableHeight()));
225
226     else if (!style()->bottom().isAuto()
227         && (!containingBlock->hasAutoHeightOrContainingBlockWithAutoHeight()
228             || !style()->bottom().isPercent()
229             || containingBlock->stretchesToViewport()))
230         offset.expand(0, -valueForLength(style()->bottom(), containingBlock->availableHeight()));
231
232     return offset;
233 }
234
235 LayoutPoint RenderBoxModelObject::adjustedPositionRelativeToOffsetParent(const LayoutPoint& startPoint) const
236 {
237     // If the element is the HTML body element or doesn't have a parent
238     // return 0 and stop this algorithm.
239     if (isBody() || !parent())
240         return LayoutPoint();
241
242     LayoutPoint referencePoint = startPoint;
243     referencePoint.move(parent()->columnOffset(referencePoint));
244
245     // If the offsetParent of the element is null, or is the HTML body element,
246     // return the distance between the canvas origin and the left border edge
247     // of the element and stop this algorithm.
248     Element* element = offsetParent();
249     if (!element)
250         return referencePoint;
251
252     if (const RenderBoxModelObject* offsetParent = element->renderBoxModelObject()) {
253         if (offsetParent->isBox() && !offsetParent->isBody())
254             referencePoint.move(-toRenderBox(offsetParent)->borderLeft(), -toRenderBox(offsetParent)->borderTop());
255         if (!isOutOfFlowPositioned() || flowThreadContainingBlock()) {
256             if (isRelPositioned())
257                 referencePoint.move(relativePositionOffset());
258
259             RenderObject* current;
260             for (current = parent(); current != offsetParent && current->parent(); current = current->parent()) {
261                 // FIXME: What are we supposed to do inside SVG content?
262                 if (!isOutOfFlowPositioned()) {
263                     if (current->isBox() && !current->isTableRow())
264                         referencePoint.moveBy(toRenderBox(current)->topLeftLocation());
265                     referencePoint.move(current->parent()->columnOffset(referencePoint));
266                 }
267             }
268
269             if (offsetParent->isBox() && offsetParent->isBody() && !offsetParent->isPositioned())
270                 referencePoint.moveBy(toRenderBox(offsetParent)->topLeftLocation());
271         }
272     }
273
274     return referencePoint;
275 }
276
277 LayoutSize RenderBoxModelObject::offsetForInFlowPosition() const
278 {
279     return isRelPositioned() ? relativePositionOffset() : LayoutSize();
280 }
281
282 LayoutUnit RenderBoxModelObject::offsetLeft() const
283 {
284     // Note that RenderInline and RenderBox override this to pass a different
285     // startPoint to adjustedPositionRelativeToOffsetParent.
286     return adjustedPositionRelativeToOffsetParent(LayoutPoint()).x();
287 }
288
289 LayoutUnit RenderBoxModelObject::offsetTop() const
290 {
291     // Note that RenderInline and RenderBox override this to pass a different
292     // startPoint to adjustedPositionRelativeToOffsetParent.
293     return adjustedPositionRelativeToOffsetParent(LayoutPoint()).y();
294 }
295
296 int RenderBoxModelObject::pixelSnappedOffsetWidth() const
297 {
298     return snapSizeToPixel(offsetWidth(), offsetLeft());
299 }
300
301 int RenderBoxModelObject::pixelSnappedOffsetHeight() const
302 {
303     return snapSizeToPixel(offsetHeight(), offsetTop());
304 }
305
306 LayoutUnit RenderBoxModelObject::computedCSSPadding(const Length& padding) const
307 {
308     LayoutUnit w = 0;
309     if (padding.isPercent())
310         w = containingBlockLogicalWidthForContent();
311     return minimumValueForLength(padding, w);
312 }
313
314 static inline int resolveWidthForRatio(int height, const FloatSize& intrinsicRatio)
315 {
316     return ceilf(height * intrinsicRatio.width() / intrinsicRatio.height());
317 }
318
319 static inline int resolveHeightForRatio(int width, const FloatSize& intrinsicRatio)
320 {
321     return ceilf(width * intrinsicRatio.height() / intrinsicRatio.width());
322 }
323
324 static inline IntSize resolveAgainstIntrinsicWidthOrHeightAndRatio(const IntSize& size, const FloatSize& intrinsicRatio, int useWidth, int useHeight)
325 {
326     if (intrinsicRatio.isEmpty()) {
327         if (useWidth)
328             return IntSize(useWidth, size.height());
329         return IntSize(size.width(), useHeight);
330     }
331
332     if (useWidth)
333         return IntSize(useWidth, resolveHeightForRatio(useWidth, intrinsicRatio));
334     return IntSize(resolveWidthForRatio(useHeight, intrinsicRatio), useHeight);
335 }
336
337 static inline IntSize resolveAgainstIntrinsicRatio(const IntSize& size, const FloatSize& intrinsicRatio)
338 {
339     // Two possible solutions: (size.width(), solutionHeight) or (solutionWidth, size.height())
340     // "... must be assumed to be the largest dimensions..." = easiest answer: the rect with the largest surface area.
341
342     int solutionWidth = resolveWidthForRatio(size.height(), intrinsicRatio);
343     int solutionHeight = resolveHeightForRatio(size.width(), intrinsicRatio);
344     if (solutionWidth <= size.width()) {
345         if (solutionHeight <= size.height()) {
346             // If both solutions fit, choose the one covering the larger area.
347             int areaOne = solutionWidth * size.height();
348             int areaTwo = size.width() * solutionHeight;
349             if (areaOne < areaTwo)
350                 return IntSize(size.width(), solutionHeight);
351             return IntSize(solutionWidth, size.height());
352         }
353
354         // Only the first solution fits.
355         return IntSize(solutionWidth, size.height());
356     }
357
358     // Only the second solution fits, assert that.
359     ASSERT(solutionHeight <= size.height());
360     return IntSize(size.width(), solutionHeight);
361 }
362
363 IntSize RenderBoxModelObject::calculateImageIntrinsicDimensions(StyleImage* image, const IntSize& positioningAreaSize, ScaleByEffectiveZoomOrNot shouldScaleOrNot) const
364 {
365     // A generated image without a fixed size, will always return the container size as intrinsic size.
366     if (image->isGeneratedImage() && image->usesImageContainerSize())
367         return IntSize(positioningAreaSize.width(), positioningAreaSize.height());
368
369     Length intrinsicWidth;
370     Length intrinsicHeight;
371     FloatSize intrinsicRatio;
372     image->computeIntrinsicDimensions(this, intrinsicWidth, intrinsicHeight, intrinsicRatio);
373
374     ASSERT(!intrinsicWidth.isPercent());
375     ASSERT(!intrinsicHeight.isPercent());
376
377     IntSize resolvedSize(intrinsicWidth.value(), intrinsicHeight.value());
378     IntSize minimumSize(resolvedSize.width() > 0 ? 1 : 0, resolvedSize.height() > 0 ? 1 : 0);
379     if (shouldScaleOrNot == ScaleByEffectiveZoom)
380         resolvedSize.scale(style()->effectiveZoom());
381     resolvedSize.clampToMinimumSize(minimumSize);
382
383     if (!resolvedSize.isEmpty())
384         return resolvedSize;
385
386     // If the image has one of either an intrinsic width or an intrinsic height:
387     // * and an intrinsic aspect ratio, then the missing dimension is calculated from the given dimension and the ratio.
388     // * and no intrinsic aspect ratio, then the missing dimension is assumed to be the size of the rectangle that
389     //   establishes the coordinate system for the 'background-position' property.
390     if (resolvedSize.width() > 0 || resolvedSize.height() > 0)
391         return resolveAgainstIntrinsicWidthOrHeightAndRatio(positioningAreaSize, intrinsicRatio, resolvedSize.width(), resolvedSize.height());
392
393     // If the image has no intrinsic dimensions and has an intrinsic ratio the dimensions must be assumed to be the
394     // largest dimensions at that ratio such that neither dimension exceeds the dimensions of the rectangle that
395     // establishes the coordinate system for the 'background-position' property.
396     if (!intrinsicRatio.isEmpty())
397         return resolveAgainstIntrinsicRatio(positioningAreaSize, intrinsicRatio);
398
399     // If the image has no intrinsic ratio either, then the dimensions must be assumed to be the rectangle that
400     // establishes the coordinate system for the 'background-position' property.
401     return positioningAreaSize;
402 }
403
404 bool RenderBoxModelObject::boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance bleedAvoidance, InlineFlowBox* inlineFlowBox) const
405 {
406     if (bleedAvoidance != BackgroundBleedNone)
407         return false;
408
409     if (style()->hasAppearance())
410         return false;
411
412     const ShadowList* shadowList = style()->boxShadow();
413     if (!shadowList)
414         return false;
415
416     bool hasOneNormalBoxShadow = false;
417     size_t shadowCount = shadowList->shadows().size();
418     for (size_t i = 0; i < shadowCount; ++i) {
419         const ShadowData& currentShadow = shadowList->shadows()[i];
420         if (currentShadow.style() != Normal)
421             continue;
422
423         if (hasOneNormalBoxShadow)
424             return false;
425         hasOneNormalBoxShadow = true;
426
427         if (currentShadow.spread())
428             return false;
429     }
430
431     if (!hasOneNormalBoxShadow)
432         return false;
433
434     Color backgroundColor = resolveColor(CSSPropertyBackgroundColor);
435     if (backgroundColor.hasAlpha())
436         return false;
437
438     const FillLayer* lastBackgroundLayer = &style()->backgroundLayers();
439     for (const FillLayer* next = lastBackgroundLayer->next(); next; next = lastBackgroundLayer->next())
440         lastBackgroundLayer = next;
441
442     if (lastBackgroundLayer->clip() != BorderFillBox)
443         return false;
444
445     if (lastBackgroundLayer->image() && style()->hasBorderRadius())
446         return false;
447
448     if (inlineFlowBox && !inlineFlowBox->boxShadowCanBeAppliedToBackground(*lastBackgroundLayer))
449         return false;
450
451     if (hasOverflowClip() && lastBackgroundLayer->attachment() == LocalBackgroundAttachment)
452         return false;
453
454     return true;
455 }
456
457
458
459 LayoutUnit RenderBoxModelObject::containingBlockLogicalWidthForContent() const
460 {
461     return containingBlock()->availableLogicalWidth();
462 }
463
464 RenderBoxModelObject* RenderBoxModelObject::continuation() const
465 {
466     if (!continuationMap)
467         return 0;
468     return (*continuationMap)->get(this);
469 }
470
471 void RenderBoxModelObject::setContinuation(RenderBoxModelObject* continuation)
472 {
473     if (continuation) {
474         if (!continuationMap)
475             continuationMap = new OwnPtrWillBePersistent<ContinuationMap>(adoptPtrWillBeNoop(new ContinuationMap));
476         (*continuationMap)->set(this, continuation);
477     } else {
478         if (continuationMap)
479             (*continuationMap)->remove(this);
480     }
481 }
482
483 void RenderBoxModelObject::computeLayerHitTestRects(LayerHitTestRects& rects) const
484 {
485     RenderLayerModelObject::computeLayerHitTestRects(rects);
486
487     // If there is a continuation then we need to consult it here, since this is
488     // the root of the tree walk and it wouldn't otherwise get picked up.
489     // Continuations should always be siblings in the tree, so any others should
490     // get picked up already by the tree walk.
491     if (continuation())
492         continuation()->computeLayerHitTestRects(rects);
493 }
494
495 RenderTextFragment* RenderBoxModelObject::firstLetterRemainingText() const
496 {
497     if (!firstLetterRemainingTextMap)
498         return 0;
499     return (*firstLetterRemainingTextMap)->get(this);
500 }
501
502 void RenderBoxModelObject::setFirstLetterRemainingText(RenderTextFragment* remainingText)
503 {
504     if (remainingText) {
505         if (!firstLetterRemainingTextMap)
506             firstLetterRemainingTextMap = new OwnPtrWillBePersistent<FirstLetterRemainingTextMap>(adoptPtrWillBeNoop(new FirstLetterRemainingTextMap));
507         (*firstLetterRemainingTextMap)->set(this, remainingText);
508     } else if (firstLetterRemainingTextMap) {
509         (*firstLetterRemainingTextMap)->remove(this);
510     }
511 }
512
513 LayoutRect RenderBoxModelObject::localCaretRectForEmptyElement(LayoutUnit width, LayoutUnit textIndentOffset)
514 {
515     ASSERT(!slowFirstChild());
516
517     // FIXME: This does not take into account either :first-line or :first-letter
518     // However, as soon as some content is entered, the line boxes will be
519     // constructed and this kludge is not called any more. So only the caret size
520     // of an empty :first-line'd block is wrong. I think we can live with that.
521     RenderStyle* currentStyle = firstLineStyle();
522
523     enum CaretAlignment { alignLeft, alignRight, alignCenter };
524
525     CaretAlignment alignment = alignLeft;
526
527     switch (currentStyle->textAlign()) {
528     case LEFT:
529     case WEBKIT_LEFT:
530         break;
531     case CENTER:
532     case WEBKIT_CENTER:
533         alignment = alignCenter;
534         break;
535     case RIGHT:
536     case WEBKIT_RIGHT:
537         alignment = alignRight;
538         break;
539     case JUSTIFY:
540     case TASTART:
541         if (!currentStyle->isLeftToRightDirection())
542             alignment = alignRight;
543         break;
544     case TAEND:
545         if (currentStyle->isLeftToRightDirection())
546             alignment = alignRight;
547         break;
548     }
549
550     LayoutUnit x = borderLeft() + paddingLeft();
551     LayoutUnit maxX = width - borderRight() - paddingRight();
552
553     switch (alignment) {
554     case alignLeft:
555         if (currentStyle->isLeftToRightDirection())
556             x += textIndentOffset;
557         break;
558     case alignCenter:
559         x = (x + maxX) / 2;
560         if (currentStyle->isLeftToRightDirection())
561             x += textIndentOffset / 2;
562         else
563             x -= textIndentOffset / 2;
564         break;
565     case alignRight:
566         x = maxX - caretWidth;
567         if (!currentStyle->isLeftToRightDirection())
568             x -= textIndentOffset;
569         break;
570     }
571     x = std::min(x, std::max<LayoutUnit>(maxX - caretWidth, 0));
572
573     LayoutUnit height = style()->fontMetrics().height();
574     LayoutUnit verticalSpace = lineHeight(true, currentStyle->isHorizontalWritingMode() ? HorizontalLine : VerticalLine,  PositionOfInteriorLineBoxes) - height;
575     LayoutUnit y = paddingTop() + borderTop() + (verticalSpace / 2);
576     return currentStyle->isHorizontalWritingMode() ? LayoutRect(x, y, caretWidth, height) : LayoutRect(y, x, height, caretWidth);
577 }
578
579 void RenderBoxModelObject::mapAbsoluteToLocalPoint(MapCoordinatesFlags mode, TransformState& transformState) const
580 {
581     RenderObject* o = container();
582     if (!o)
583         return;
584
585     if (o->isRenderFlowThread())
586         transformState.move(o->columnOffset(LayoutPoint(transformState.mappedPoint())));
587
588     o->mapAbsoluteToLocalPoint(mode, transformState);
589
590     LayoutSize containerOffset = offsetFromContainer(o, LayoutPoint());
591
592     if (!style()->hasOutOfFlowPosition() && o->hasColumns()) {
593         RenderBlock* block = toRenderBlock(o);
594         LayoutPoint point(roundedLayoutPoint(transformState.mappedPoint()));
595         point -= containerOffset;
596         block->adjustForColumnRect(containerOffset, point);
597     }
598
599     bool preserve3D = mode & UseTransforms && (o->style()->preserves3D() || style()->preserves3D());
600     if (mode & UseTransforms && shouldUseTransformFromContainer(o)) {
601         TransformationMatrix t;
602         getTransformFromContainer(o, containerOffset, t);
603         transformState.applyTransform(t, preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
604     } else
605         transformState.move(containerOffset.width(), containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
606 }
607
608 const RenderObject* RenderBoxModelObject::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
609 {
610     ASSERT(ancestorToStopAt != this);
611
612     bool ancestorSkipped;
613     RenderObject* container = this->container(ancestorToStopAt, &ancestorSkipped);
614     if (!container)
615         return 0;
616
617     bool isInline = isRenderInline();
618     bool isFixedPos = !isInline && style()->position() == FixedPosition;
619     bool hasTransform = !isInline && hasLayer() && layer()->transform();
620
621     LayoutSize adjustmentForSkippedAncestor;
622     if (ancestorSkipped) {
623         // There can't be a transform between paintInvalidationContainer and o, because transforms create containers, so it should be safe
624         // to just subtract the delta between the ancestor and o.
625         adjustmentForSkippedAncestor = -ancestorToStopAt->offsetFromAncestorContainer(container);
626     }
627
628     bool offsetDependsOnPoint = false;
629     LayoutSize containerOffset = offsetFromContainer(container, LayoutPoint(), &offsetDependsOnPoint);
630
631     bool preserve3D = container->style()->preserves3D() || style()->preserves3D();
632     if (shouldUseTransformFromContainer(container)) {
633         TransformationMatrix t;
634         getTransformFromContainer(container, containerOffset, t);
635         t.translateRight(adjustmentForSkippedAncestor.width().toFloat(), adjustmentForSkippedAncestor.height().toFloat());
636         geometryMap.push(this, t, preserve3D, offsetDependsOnPoint, isFixedPos, hasTransform);
637     } else {
638         containerOffset += adjustmentForSkippedAncestor;
639         geometryMap.push(this, containerOffset, preserve3D, offsetDependsOnPoint, isFixedPos, hasTransform);
640     }
641
642     return ancestorSkipped ? ancestorToStopAt : container;
643 }
644
645 void RenderBoxModelObject::moveChildTo(RenderBoxModelObject* toBoxModelObject, RenderObject* child, RenderObject* beforeChild, bool fullRemoveInsert)
646 {
647     // We assume that callers have cleared their positioned objects list for child moves (!fullRemoveInsert) so the
648     // positioned renderer maps don't become stale. It would be too slow to do the map lookup on each call.
649     ASSERT(!fullRemoveInsert || !isRenderBlock() || !toRenderBlock(this)->hasPositionedObjects());
650
651     ASSERT(this == child->parent());
652     ASSERT(!beforeChild || toBoxModelObject == beforeChild->parent());
653     if (fullRemoveInsert && (toBoxModelObject->isRenderBlock() || toBoxModelObject->isRenderInline())) {
654         // Takes care of adding the new child correctly if toBlock and fromBlock
655         // have different kind of children (block vs inline).
656         toBoxModelObject->addChild(virtualChildren()->removeChildNode(this, child), beforeChild);
657     } else
658         toBoxModelObject->virtualChildren()->insertChildNode(toBoxModelObject, virtualChildren()->removeChildNode(this, child, fullRemoveInsert), beforeChild, fullRemoveInsert);
659 }
660
661 void RenderBoxModelObject::moveChildrenTo(RenderBoxModelObject* toBoxModelObject, RenderObject* startChild, RenderObject* endChild, RenderObject* beforeChild, bool fullRemoveInsert)
662 {
663     // This condition is rarely hit since this function is usually called on
664     // anonymous blocks which can no longer carry positioned objects (see r120761)
665     // or when fullRemoveInsert is false.
666     if (fullRemoveInsert && isRenderBlock()) {
667         RenderBlock* block = toRenderBlock(this);
668         block->removePositionedObjects(0);
669         if (block->isRenderBlockFlow())
670             toRenderBlockFlow(block)->removeFloatingObjects();
671     }
672
673     ASSERT(!beforeChild || toBoxModelObject == beforeChild->parent());
674     for (RenderObject* child = startChild; child && child != endChild; ) {
675         // Save our next sibling as moveChildTo will clear it.
676         RenderObject* nextSibling = child->nextSibling();
677         moveChildTo(toBoxModelObject, child, beforeChild, fullRemoveInsert);
678         child = nextSibling;
679     }
680 }
681
682 } // namespace blink