1926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/*
2926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
3926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) *
4926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * Redistribution and use in source and binary forms, with or without
5926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * modification, are permitted provided that the following conditions
6926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * are met:
7926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) *
8926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * 1. Redistributions of source code must retain the above
9926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) *    copyright notice, this list of conditions and the following
10926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) *    disclaimer.
11926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * 2. Redistributions in binary form must reproduce the above
12926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) *    copyright notice, this list of conditions and the following
13926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) *    disclaimer in the documentation and/or other materials
14926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) *    provided with the distribution.
15926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) *
16926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
17926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
20926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
21926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
25926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
26926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * SUCH DAMAGE.
28926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
29926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
30926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)#include "config.h"
31591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "core/rendering/shapes/ShapeOutsideInfo.h"
32926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
33e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#include "core/inspector/ConsoleMessage.h"
3406f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)#include "core/rendering/FloatingObjects.h"
35f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)#include "core/rendering/RenderBlockFlow.h"
3653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderBox.h"
37a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include "core/rendering/RenderImage.h"
386f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch#include "platform/LengthFunctions.h"
39197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "public/platform/Platform.h"
40926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
41c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
42a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
43a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben MurdochCSSBoxType referenceBox(const ShapeValue& shapeValue)
44a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch{
45a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    if (shapeValue.cssBox() == BoxMissing)
46a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        return MarginBox;
47a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    return shapeValue.cssBox();
48a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}
49a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
50a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochvoid ShapeOutsideInfo::setReferenceBoxLogicalSize(LayoutSize newReferenceBoxLogicalSize)
51a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch{
52a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    bool isHorizontalWritingMode = m_renderer.containingBlock()->style()->isHorizontalWritingMode();
53a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    switch (referenceBox(*m_renderer.style()->shapeOutside())) {
54a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    case MarginBox:
55a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        if (isHorizontalWritingMode)
56a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            newReferenceBoxLogicalSize.expand(m_renderer.marginWidth(), m_renderer.marginHeight());
57a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        else
58a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            newReferenceBoxLogicalSize.expand(m_renderer.marginHeight(), m_renderer.marginWidth());
59a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        break;
60a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    case BorderBox:
61a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        break;
62a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    case PaddingBox:
63a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        if (isHorizontalWritingMode)
64a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            newReferenceBoxLogicalSize.shrink(m_renderer.borderWidth(), m_renderer.borderHeight());
65a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        else
66a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            newReferenceBoxLogicalSize.shrink(m_renderer.borderHeight(), m_renderer.borderWidth());
67a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        break;
68a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    case ContentBox:
69a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        if (isHorizontalWritingMode)
70a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            newReferenceBoxLogicalSize.shrink(m_renderer.borderAndPaddingWidth(), m_renderer.borderAndPaddingHeight());
71a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        else
72a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            newReferenceBoxLogicalSize.shrink(m_renderer.borderAndPaddingHeight(), m_renderer.borderAndPaddingWidth());
73a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        break;
74a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    case BoxMissing:
75a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        ASSERT_NOT_REACHED();
76a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        break;
77a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
78a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
79a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    if (m_referenceBoxLogicalSize == newReferenceBoxLogicalSize)
80a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        return;
81a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    markShapeAsDirty();
82a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    m_referenceBoxLogicalSize = newReferenceBoxLogicalSize;
83a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}
84a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
85f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liustatic bool checkShapeImageOrigin(Document& document, const StyleImage& styleImage)
86a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch{
87f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    if (styleImage.isGeneratedImage())
88f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        return true;
89f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
90f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    ASSERT(styleImage.cachedImage());
91f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    ImageResource& imageResource = *(styleImage.cachedImage());
92a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    if (imageResource.isAccessAllowed(document.securityOrigin()))
93a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        return true;
94a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
95a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    const KURL& url = imageResource.url();
96a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    String urlString = url.isNull() ? "''" : url.elidedString();
97e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    document.addConsoleMessage(ConsoleMessage::create(SecurityMessageSource, ErrorMessageLevel, "Unsafe attempt to load URL " + urlString + "."));
98a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
99a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    return false;
100a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}
101a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
102a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochstatic LayoutRect getShapeImageMarginRect(const RenderBox& renderBox, const LayoutSize& referenceBoxLogicalSize)
103a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch{
104a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    LayoutPoint marginBoxOrigin(-renderBox.marginLogicalLeft() - renderBox.borderAndPaddingLogicalLeft(), -renderBox.marginBefore() - renderBox.borderBefore() - renderBox.paddingBefore());
105a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    LayoutSize marginBoxSizeDelta(renderBox.marginLogicalWidth() + renderBox.borderAndPaddingLogicalWidth(), renderBox.marginLogicalHeight() + renderBox.borderAndPaddingLogicalHeight());
106a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    return LayoutRect(marginBoxOrigin, referenceBoxLogicalSize + marginBoxSizeDelta);
107a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}
108a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
109197021e6b966cfb06891637935ef33fff06433d1Ben Murdochstatic bool isValidRasterShapeRect(const LayoutRect& rect)
110197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch{
111197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    static double maxImageSizeBytes = 0;
112197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (!maxImageSizeBytes) {
113197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        size_t size32MaxBytes =  0xFFFFFFFF / 4; // Some platforms don't limit maxDecodedImageBytes.
114e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        maxImageSizeBytes = std::min(size32MaxBytes, Platform::current()->maxDecodedImageBytes());
115197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    }
116197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    return (rect.width().toFloat() * rect.height().toFloat() * 4.0) < maxImageSizeBytes;
117197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch}
118197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
119f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)PassOwnPtr<Shape> ShapeOutsideInfo::createShapeForImage(StyleImage* styleImage, float shapeImageThreshold, WritingMode writingMode, float margin) const
120f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles){
121f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    const IntSize& imageSize = m_renderer.calculateImageIntrinsicDimensions(styleImage, roundedIntSize(m_referenceBoxLogicalSize), RenderImage::ScaleByEffectiveZoom);
122f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    styleImage->setContainerSizeForRenderer(&m_renderer, imageSize, m_renderer.style()->effectiveZoom());
123f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
124f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    const LayoutRect& marginRect = getShapeImageMarginRect(m_renderer, m_referenceBoxLogicalSize);
125f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    const LayoutRect& imageRect = (m_renderer.isRenderImage())
126197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        ? toRenderImage(m_renderer).replacedContentRect()
127f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        : LayoutRect(LayoutPoint(), imageSize);
128f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
129197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (!isValidRasterShapeRect(marginRect) || !isValidRasterShapeRect(imageRect)) {
130e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        m_renderer.document().addConsoleMessage(ConsoleMessage::create(RenderingMessageSource, ErrorMessageLevel, "The shape-outside image is too large."));
131197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return Shape::createEmptyRasterShape(writingMode, margin);
132197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    }
133197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
134f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    ASSERT(!styleImage->isPendingImage());
135f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    RefPtr<Image> image = styleImage->image(const_cast<RenderBox*>(&m_renderer), imageSize);
136f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
137f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    return Shape::createRasterShape(image.get(), shapeImageThreshold, imageRect, marginRect, writingMode, margin);
138f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)}
139f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
140a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochconst Shape& ShapeOutsideInfo::computedShape() const
141a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch{
142a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    if (Shape* shape = m_shape.get())
143a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        return *shape;
144a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
145f542a0e9557608d421c9d165487573efa35a5f91Ben Murdoch    TemporaryChange<bool> isInComputingShape(m_isComputingShape, true);
146f542a0e9557608d421c9d165487573efa35a5f91Ben Murdoch
147a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    const RenderStyle& style = *m_renderer.style();
148a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    ASSERT(m_renderer.containingBlock());
149a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    const RenderStyle& containingBlockStyle = *m_renderer.containingBlock()->style();
150a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
151a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    WritingMode writingMode = containingBlockStyle.writingMode();
1526f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    LayoutUnit maximumValue = m_renderer.containingBlock() ? m_renderer.containingBlock()->contentWidth() : LayoutUnit();
1536f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    float margin = floatValueForLength(m_renderer.style()->shapeMargin(), maximumValue.toFloat());
1546f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch
155a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    float shapeImageThreshold = style.shapeImageThreshold();
156a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    ASSERT(style.shapeOutside());
157a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    const ShapeValue& shapeValue = *style.shapeOutside();
158a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
159a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    switch (shapeValue.type()) {
160a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    case ShapeValue::Shape:
161a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        ASSERT(shapeValue.shape());
162a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        m_shape = Shape::createShape(shapeValue.shape(), m_referenceBoxLogicalSize, writingMode, margin);
163a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        break;
164f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    case ShapeValue::Image:
165f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        ASSERT(shapeValue.isImageValid());
166f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        m_shape = createShapeForImage(shapeValue.image(), shapeImageThreshold, writingMode, margin);
167a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        break;
168a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    case ShapeValue::Box: {
169a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        const RoundedRect& shapeRect = style.getRoundedBorderFor(LayoutRect(LayoutPoint(), m_referenceBoxLogicalSize), m_renderer.view());
170a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        m_shape = Shape::createLayoutBoxShape(shapeRect, writingMode, margin);
171a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        break;
172a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
173a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
174a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
175a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    ASSERT(m_shape);
176a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    return *m_shape;
177a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}
178a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
179a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochinline LayoutUnit borderBeforeInWritingMode(const RenderBox& renderer, WritingMode writingMode)
180a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch{
181a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    switch (writingMode) {
182a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    case TopToBottomWritingMode: return renderer.borderTop();
183a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    case BottomToTopWritingMode: return renderer.borderBottom();
184a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    case LeftToRightWritingMode: return renderer.borderLeft();
185a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    case RightToLeftWritingMode: return renderer.borderRight();
186a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
187a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
188a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    ASSERT_NOT_REACHED();
189a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    return renderer.borderBefore();
190a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}
191a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
192a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochinline LayoutUnit borderAndPaddingBeforeInWritingMode(const RenderBox& renderer, WritingMode writingMode)
193a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch{
194a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    switch (writingMode) {
195a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    case TopToBottomWritingMode: return renderer.borderTop() + renderer.paddingTop();
196a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    case BottomToTopWritingMode: return renderer.borderBottom() + renderer.paddingBottom();
197a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    case LeftToRightWritingMode: return renderer.borderLeft() + renderer.paddingLeft();
198a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    case RightToLeftWritingMode: return renderer.borderRight() + renderer.paddingRight();
199a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
200a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
201a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    ASSERT_NOT_REACHED();
202a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    return renderer.borderAndPaddingBefore();
203a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}
204a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
205a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben MurdochLayoutUnit ShapeOutsideInfo::logicalTopOffset() const
206a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch{
207a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    switch (referenceBox(*m_renderer.style()->shapeOutside())) {
208a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    case MarginBox: return -m_renderer.marginBefore(m_renderer.containingBlock()->style());
209a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    case BorderBox: return LayoutUnit();
210a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    case PaddingBox: return borderBeforeInWritingMode(m_renderer, m_renderer.containingBlock()->style()->writingMode());
211a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    case ContentBox: return borderAndPaddingBeforeInWritingMode(m_renderer, m_renderer.containingBlock()->style()->writingMode());
212a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    case BoxMissing: break;
213a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
214a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
215a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    ASSERT_NOT_REACHED();
216a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    return LayoutUnit();
217a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}
218a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
219a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochinline LayoutUnit borderStartWithStyleForWritingMode(const RenderBox& renderer, const RenderStyle* style)
220a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch{
221a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    if (style->isHorizontalWritingMode()) {
222a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        if (style->isLeftToRightDirection())
223a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            return renderer.borderLeft();
224a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
225a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        return renderer.borderRight();
226a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
227a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    if (style->isLeftToRightDirection())
228a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        return renderer.borderTop();
229a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
230a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    return renderer.borderBottom();
231a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}
232a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
233a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochinline LayoutUnit borderAndPaddingStartWithStyleForWritingMode(const RenderBox& renderer, const RenderStyle* style)
234a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch{
235a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    if (style->isHorizontalWritingMode()) {
236a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        if (style->isLeftToRightDirection())
237a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            return renderer.borderLeft() + renderer.paddingLeft();
238a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
239a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        return renderer.borderRight() + renderer.paddingRight();
240a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
241a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    if (style->isLeftToRightDirection())
242a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        return renderer.borderTop() + renderer.paddingTop();
243a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
244a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    return renderer.borderBottom() + renderer.paddingBottom();
245a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}
246a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
247a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben MurdochLayoutUnit ShapeOutsideInfo::logicalLeftOffset() const
248a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch{
249a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    switch (referenceBox(*m_renderer.style()->shapeOutside())) {
250a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    case MarginBox: return -m_renderer.marginStart(m_renderer.containingBlock()->style());
251a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    case BorderBox: return LayoutUnit();
252a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    case PaddingBox: return borderStartWithStyleForWritingMode(m_renderer, m_renderer.containingBlock()->style());
253a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    case ContentBox: return borderAndPaddingStartWithStyleForWritingMode(m_renderer, m_renderer.containingBlock()->style());
254a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    case BoxMissing: break;
255a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    }
256a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
257a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    ASSERT_NOT_REACHED();
258a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    return LayoutUnit();
259a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch}
260a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
261a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch
262d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)bool ShapeOutsideInfo::isEnabledFor(const RenderBox& box)
263926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
264d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    ShapeValue* shapeValue = box.style()->shapeOutside();
265d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (!box.isFloating() || !shapeValue)
266e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        return false;
267e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
268e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    switch (shapeValue->type()) {
269e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    case ShapeValue::Shape:
270e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        return shapeValue->shape();
271e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    case ShapeValue::Image:
272f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        return shapeValue->isImageValid() && checkShapeImageOrigin(box.document(), *(shapeValue->image()));
273a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    case ShapeValue::Box:
274a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        return true;
275e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    }
276e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
277e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    return false;
278926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
2799e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)ShapeOutsideDeltas ShapeOutsideInfo::computeDeltasForContainingBlockLine(const RenderBlockFlow& containingBlock, const FloatingObject& floatingObject, LayoutUnit lineTop, LayoutUnit lineHeight)
28002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch{
281e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    ASSERT(lineHeight >= 0);
282e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)
283d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    LayoutUnit borderBoxTop = containingBlock.logicalTopForFloat(&floatingObject) + containingBlock.marginBeforeForChild(&m_renderer);
284d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    LayoutUnit borderBoxLineTop = lineTop - borderBoxTop;
28502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
2869e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    if (isShapeDirty() || !m_shapeOutsideDeltas.isForLine(borderBoxLineTop, lineHeight)) {
2879e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)        LayoutUnit referenceBoxLineTop = borderBoxLineTop - logicalTopOffset();
288d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        LayoutUnit floatMarginBoxWidth = containingBlock.logicalWidthForFloat(&floatingObject);
289f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)
2909e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)        if (computedShape().lineOverlapsShapeMarginBounds(referenceBoxLineTop, lineHeight)) {
291e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)            LineSegment segment = computedShape().getExcludedInterval((borderBoxLineTop - logicalTopOffset()), std::min(lineHeight, shapeLogicalBottom() - borderBoxLineTop));
292e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)            if (segment.isValid) {
293d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                LayoutUnit logicalLeftMargin = containingBlock.style()->isLeftToRightDirection() ? containingBlock.marginStartForChild(&m_renderer) : containingBlock.marginEndForChild(&m_renderer);
294e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)                LayoutUnit rawLeftMarginBoxDelta = segment.logicalLeft + logicalLeftOffset() + logicalLeftMargin;
2959e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)                LayoutUnit leftMarginBoxDelta = clampTo<LayoutUnit>(rawLeftMarginBoxDelta, LayoutUnit(), floatMarginBoxWidth);
296f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)
297d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                LayoutUnit logicalRightMargin = containingBlock.style()->isLeftToRightDirection() ? containingBlock.marginEndForChild(&m_renderer) : containingBlock.marginStartForChild(&m_renderer);
298e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)                LayoutUnit rawRightMarginBoxDelta = segment.logicalRight + logicalLeftOffset() - containingBlock.logicalWidthForChild(&m_renderer) - logicalRightMargin;
2999e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)                LayoutUnit rightMarginBoxDelta = clampTo<LayoutUnit>(rawRightMarginBoxDelta, -floatMarginBoxWidth, LayoutUnit());
3009e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)
3019e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)                m_shapeOutsideDeltas = ShapeOutsideDeltas(leftMarginBoxDelta, rightMarginBoxDelta, true, borderBoxLineTop, lineHeight);
3029e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)                return m_shapeOutsideDeltas;
3031e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)            }
304926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
305926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
306f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        // Lines that do not overlap the shape should act as if the float
307f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        // wasn't there for layout purposes. So we set the deltas to remove the
308f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        // entire width of the float.
3099e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)        m_shapeOutsideDeltas = ShapeOutsideDeltas(floatMarginBoxWidth, -floatMarginBoxWidth, false, borderBoxLineTop, lineHeight);
3101e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    }
3119e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)
3129e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    return m_shapeOutsideDeltas;
313926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
314926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
315323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)LayoutRect ShapeOutsideInfo::computedShapePhysicalBoundingBox() const
316323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles){
317323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    LayoutRect physicalBoundingBox = computedShape().shapeMarginLogicalBoundingBox();
318323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    physicalBoundingBox.setX(physicalBoundingBox.x() + logicalLeftOffset());
319323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
320323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    if (m_renderer.style()->isFlippedBlocksWritingMode())
321323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        physicalBoundingBox.setY(m_renderer.logicalHeight() - physicalBoundingBox.maxY());
322323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    else
323323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        physicalBoundingBox.setY(physicalBoundingBox.y() + logicalTopOffset());
324323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
325323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    if (!m_renderer.style()->isHorizontalWritingMode())
326323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        physicalBoundingBox = physicalBoundingBox.transposedRect();
327323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    else
328323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        physicalBoundingBox.setY(physicalBoundingBox.y() + logicalTopOffset());
329323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
330323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    return physicalBoundingBox;
331323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)}
332323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
333323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)FloatPoint ShapeOutsideInfo::shapeToRendererPoint(FloatPoint point) const
334323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles){
335323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    FloatPoint result = FloatPoint(point.x() + logicalLeftOffset(), point.y() + logicalTopOffset());
336323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    if (m_renderer.style()->isFlippedBlocksWritingMode())
337323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        result.setY(m_renderer.logicalHeight() - result.y());
338323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    if (!m_renderer.style()->isHorizontalWritingMode())
339323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        result = result.transposedPoint();
340323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    return result;
341323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)}
342323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
343323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)FloatSize ShapeOutsideInfo::shapeToRendererSize(FloatSize size) const
344323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles){
345323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    if (!m_renderer.style()->isHorizontalWritingMode())
346323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        return size.transposedSize();
347323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    return size;
348323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)}
349323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
350e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)} // namespace blink
351