Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / rendering / shapes / ShapeInfo.cpp
1 /*
2  * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above
9  *    copyright notice, this list of conditions and the following
10  *    disclaimer.
11  * 2. Redistributions in binary form must reproduce the above
12  *    copyright notice, this list of conditions and the following
13  *    disclaimer in the documentation and/or other materials
14  *    provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
21  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
25  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
26  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 #include "config.h"
31 #include "core/rendering/shapes/ShapeInfo.h"
32
33 #include "core/rendering/RenderBlock.h"
34 #include "core/rendering/RenderImage.h"
35
36 namespace WebCore {
37
38 template<class RenderType>
39 void ShapeInfo<RenderType>::setReferenceBoxLogicalSize(LayoutSize newReferenceBoxLogicalSize)
40 {
41     bool isHorizontalWritingMode = this->styleForWritingMode()->isHorizontalWritingMode();
42     switch (referenceBox()) {
43     case MarginBox:
44         if (isHorizontalWritingMode)
45             newReferenceBoxLogicalSize.expand(m_renderer.marginWidth(), m_renderer.marginHeight());
46         else
47             newReferenceBoxLogicalSize.expand(m_renderer.marginHeight(), m_renderer.marginWidth());
48         break;
49     case BorderBox:
50         break;
51     case PaddingBox:
52         if (isHorizontalWritingMode)
53             newReferenceBoxLogicalSize.shrink(m_renderer.borderWidth(), m_renderer.borderHeight());
54         else
55             newReferenceBoxLogicalSize.shrink(m_renderer.borderHeight(), m_renderer.borderWidth());
56         break;
57     case ContentBox:
58         if (isHorizontalWritingMode)
59             newReferenceBoxLogicalSize.shrink(m_renderer.borderAndPaddingWidth(), m_renderer.borderAndPaddingHeight());
60         else
61             newReferenceBoxLogicalSize.shrink(m_renderer.borderAndPaddingHeight(), m_renderer.borderAndPaddingWidth());
62         break;
63     case BoxMissing:
64         ASSERT_NOT_REACHED();
65         break;
66     }
67
68     if (m_referenceBoxLogicalSize == newReferenceBoxLogicalSize)
69         return;
70     markShapeAsDirty();
71     m_referenceBoxLogicalSize = newReferenceBoxLogicalSize;
72 }
73
74 bool checkShapeImageOrigin(Document& document, ImageResource& imageResource)
75 {
76     if (imageResource.isAccessAllowed(document.securityOrigin()))
77         return true;
78
79     const KURL& url = imageResource.url();
80     String urlString = url.isNull() ? "''" : url.elidedString();
81     document.addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, "Unsafe attempt to load URL " + urlString + ".");
82
83     return false;
84 }
85
86 static void getShapeImageAndRect(const ShapeValue* shapeValue, const RenderBox* renderBox, const LayoutSize& referenceBoxSize, Image*& image, LayoutRect& rect)
87 {
88     ASSERT(shapeValue->isImageValid());
89     StyleImage* styleImage = shapeValue->image();
90
91     const IntSize& imageSize = renderBox->calculateImageIntrinsicDimensions(styleImage, roundedIntSize(referenceBoxSize), RenderImage::ScaleByEffectiveZoom);
92     styleImage->setContainerSizeForRenderer(renderBox, imageSize, renderBox->style()->effectiveZoom());
93
94     image = styleImage->cachedImage()->imageForRenderer(renderBox);
95     if (renderBox->isRenderImage())
96         rect = toRenderImage(renderBox)->replacedContentRect();
97     else
98         rect = LayoutRect(LayoutPoint(), imageSize);
99 }
100
101 static LayoutRect getShapeImageMarginRect(const RenderBox& renderBox, const LayoutSize& referenceBoxLogicalSize)
102 {
103     LayoutPoint marginBoxOrigin(-renderBox.marginLogicalLeft() - renderBox.borderAndPaddingLogicalLeft(), -renderBox.marginBefore() - renderBox.borderBefore() - renderBox.paddingBefore());
104     LayoutSize marginBoxSizeDelta(renderBox.marginLogicalWidth() + renderBox.borderAndPaddingLogicalWidth(), renderBox.marginLogicalHeight() + renderBox.borderAndPaddingLogicalHeight());
105     return LayoutRect(marginBoxOrigin, referenceBoxLogicalSize + marginBoxSizeDelta);
106 }
107
108 template<class RenderType>
109 const Shape& ShapeInfo<RenderType>::computedShape() const
110 {
111     if (Shape* shape = m_shape.get())
112         return *shape;
113
114     WritingMode writingMode = this->styleForWritingMode()->writingMode();
115     Length margin = m_renderer.style()->shapeMargin();
116     Length padding = m_renderer.style()->shapePadding();
117     float shapeImageThreshold = m_renderer.style()->shapeImageThreshold();
118     const ShapeValue* shapeValue = this->shapeValue();
119     ASSERT(shapeValue);
120
121     switch (shapeValue->type()) {
122     case ShapeValue::Shape:
123         ASSERT(shapeValue->shape());
124         m_shape = Shape::createShape(shapeValue->shape(), m_referenceBoxLogicalSize, writingMode, margin, padding);
125         break;
126     case ShapeValue::Image: {
127         Image* image;
128         LayoutRect imageRect;
129         getShapeImageAndRect(shapeValue, &m_renderer, m_referenceBoxLogicalSize, image, imageRect);
130         const LayoutRect& marginRect = getShapeImageMarginRect(m_renderer, m_referenceBoxLogicalSize);
131         m_shape = Shape::createRasterShape(image, shapeImageThreshold, imageRect, marginRect, writingMode, margin, padding);
132         break;
133     }
134     case ShapeValue::Box: {
135         const RoundedRect& shapeRect = m_renderer.style()->getRoundedBorderFor(LayoutRect(LayoutPoint(), m_referenceBoxLogicalSize), m_renderer.view());
136         m_shape = Shape::createLayoutBoxShape(shapeRect, writingMode, margin, padding);
137         break;
138     }
139     case ShapeValue::Outside:
140         // Outside should have already resolved to a different shape value.
141         ASSERT_NOT_REACHED();
142     }
143
144     ASSERT(m_shape);
145     return *m_shape;
146 }
147
148 template<class RenderType>
149 SegmentList ShapeInfo<RenderType>::computeSegmentsForLine(LayoutUnit lineTop, LayoutUnit lineHeight) const
150 {
151     ASSERT(lineHeight >= 0);
152     SegmentList segments;
153
154     getIntervals((lineTop - logicalTopOffset()), std::min(lineHeight, shapeLogicalBottom() - lineTop), segments);
155
156     for (size_t i = 0; i < segments.size(); i++) {
157         segments[i].logicalLeft += logicalLeftOffset();
158         segments[i].logicalRight += logicalLeftOffset();
159     }
160
161     return segments;
162 }
163
164 template<class RenderType>
165 inline LayoutUnit borderBeforeInWritingMode(const RenderType& renderer, WritingMode writingMode)
166 {
167     switch (writingMode) {
168     case TopToBottomWritingMode: return renderer.borderTop();
169     case BottomToTopWritingMode: return renderer.borderBottom();
170     case LeftToRightWritingMode: return renderer.borderLeft();
171     case RightToLeftWritingMode: return renderer.borderRight();
172     }
173
174     ASSERT_NOT_REACHED();
175     return renderer.borderBefore();
176 }
177
178 template<class RenderType>
179 inline LayoutUnit borderAndPaddingBeforeInWritingMode(const RenderType& renderer, WritingMode writingMode)
180 {
181     switch (writingMode) {
182     case TopToBottomWritingMode: return renderer.borderTop() + renderer.paddingTop();
183     case BottomToTopWritingMode: return renderer.borderBottom() + renderer.paddingBottom();
184     case LeftToRightWritingMode: return renderer.borderLeft() + renderer.paddingLeft();
185     case RightToLeftWritingMode: return renderer.borderRight() + renderer.paddingRight();
186     }
187
188     ASSERT_NOT_REACHED();
189     return renderer.borderAndPaddingBefore();
190 }
191
192 template<class RenderType>
193 LayoutUnit ShapeInfo<RenderType>::logicalTopOffset() const
194 {
195     switch (referenceBox()) {
196     case MarginBox: return -m_renderer.marginBefore(styleForWritingMode());
197     case BorderBox: return LayoutUnit();
198     case PaddingBox: return borderBeforeInWritingMode(m_renderer, styleForWritingMode()->writingMode());
199     case ContentBox: return borderAndPaddingBeforeInWritingMode(m_renderer, styleForWritingMode()->writingMode());
200     case BoxMissing: break;
201     }
202
203     ASSERT_NOT_REACHED();
204     return LayoutUnit();
205 }
206
207 template<class RenderType>
208 inline LayoutUnit borderStartWithStyleForWritingMode(const RenderType& renderer, const RenderStyle* style)
209 {
210     if (style->isHorizontalWritingMode()) {
211         if (style->isLeftToRightDirection())
212             return renderer.borderLeft();
213
214         return renderer.borderRight();
215     }
216     if (style->isLeftToRightDirection())
217         return renderer.borderTop();
218
219     return renderer.borderBottom();
220 }
221
222 template<class RenderType>
223 inline LayoutUnit borderAndPaddingStartWithStyleForWritingMode(const RenderType& renderer, const RenderStyle* style)
224 {
225     if (style->isHorizontalWritingMode()) {
226         if (style->isLeftToRightDirection())
227             return renderer.borderLeft() + renderer.paddingLeft();
228
229         return renderer.borderRight() + renderer.paddingRight();
230     }
231     if (style->isLeftToRightDirection())
232         return renderer.borderTop() + renderer.paddingTop();
233
234     return renderer.borderBottom() + renderer.paddingBottom();
235 }
236
237 template<class RenderType>
238 LayoutUnit ShapeInfo<RenderType>::logicalLeftOffset() const
239 {
240     switch (referenceBox()) {
241     case MarginBox: return -m_renderer.marginStart(styleForWritingMode());
242     case BorderBox: return LayoutUnit();
243     case PaddingBox: return borderStartWithStyleForWritingMode(m_renderer, styleForWritingMode());
244     case ContentBox: return borderAndPaddingStartWithStyleForWritingMode(m_renderer, styleForWritingMode());
245     case BoxMissing: break;
246     }
247
248     ASSERT_NOT_REACHED();
249     return LayoutUnit();
250 }
251
252 template class ShapeInfo<RenderBlock>;
253 template class ShapeInfo<RenderBox>;
254 }