2 * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above
9 * copyright notice, this list of conditions and the following
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.
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
31 #include "core/rendering/shapes/ShapeInfo.h"
33 #include "core/rendering/RenderBlock.h"
34 #include "core/rendering/RenderImage.h"
38 template<class RenderType>
39 void ShapeInfo<RenderType>::setReferenceBoxLogicalSize(LayoutSize newReferenceBoxLogicalSize)
41 bool isHorizontalWritingMode = this->styleForWritingMode()->isHorizontalWritingMode();
42 switch (referenceBox()) {
44 if (isHorizontalWritingMode)
45 newReferenceBoxLogicalSize.expand(m_renderer.marginWidth(), m_renderer.marginHeight());
47 newReferenceBoxLogicalSize.expand(m_renderer.marginHeight(), m_renderer.marginWidth());
52 if (isHorizontalWritingMode)
53 newReferenceBoxLogicalSize.shrink(m_renderer.borderWidth(), m_renderer.borderHeight());
55 newReferenceBoxLogicalSize.shrink(m_renderer.borderHeight(), m_renderer.borderWidth());
58 if (isHorizontalWritingMode)
59 newReferenceBoxLogicalSize.shrink(m_renderer.borderAndPaddingWidth(), m_renderer.borderAndPaddingHeight());
61 newReferenceBoxLogicalSize.shrink(m_renderer.borderAndPaddingHeight(), m_renderer.borderAndPaddingWidth());
68 if (m_referenceBoxLogicalSize == newReferenceBoxLogicalSize)
71 m_referenceBoxLogicalSize = newReferenceBoxLogicalSize;
74 bool checkShapeImageOrigin(Document& document, ImageResource& imageResource)
76 if (imageResource.isAccessAllowed(document.securityOrigin()))
79 const KURL& url = imageResource.url();
80 String urlString = url.isNull() ? "''" : url.elidedString();
81 document.addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, "Unsafe attempt to load URL " + urlString + ".");
86 static void getShapeImageAndRect(const ShapeValue* shapeValue, const RenderBox* renderBox, const LayoutSize& referenceBoxSize, Image*& image, LayoutRect& rect)
88 ASSERT(shapeValue->isImageValid());
89 StyleImage* styleImage = shapeValue->image();
91 const IntSize& imageSize = renderBox->calculateImageIntrinsicDimensions(styleImage, roundedIntSize(referenceBoxSize), RenderImage::ScaleByEffectiveZoom);
92 styleImage->setContainerSizeForRenderer(renderBox, imageSize, renderBox->style()->effectiveZoom());
94 image = styleImage->cachedImage()->imageForRenderer(renderBox);
95 if (renderBox->isRenderImage())
96 rect = toRenderImage(renderBox)->replacedContentRect();
98 rect = LayoutRect(LayoutPoint(), imageSize);
101 static LayoutRect getShapeImageMarginRect(const RenderBox& renderBox, const LayoutSize& referenceBoxLogicalSize)
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);
108 template<class RenderType>
109 const Shape& ShapeInfo<RenderType>::computedShape() const
111 if (Shape* shape = m_shape.get())
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();
121 switch (shapeValue->type()) {
122 case ShapeValue::Shape:
123 ASSERT(shapeValue->shape());
124 m_shape = Shape::createShape(shapeValue->shape(), m_referenceBoxLogicalSize, writingMode, margin, padding);
126 case ShapeValue::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);
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);
139 case ShapeValue::Outside:
140 // Outside should have already resolved to a different shape value.
141 ASSERT_NOT_REACHED();
148 template<class RenderType>
149 SegmentList ShapeInfo<RenderType>::computeSegmentsForLine(LayoutUnit lineTop, LayoutUnit lineHeight) const
151 ASSERT(lineHeight >= 0);
152 SegmentList segments;
154 getIntervals((lineTop - logicalTopOffset()), std::min(lineHeight, shapeLogicalBottom() - lineTop), segments);
156 for (size_t i = 0; i < segments.size(); i++) {
157 segments[i].logicalLeft += logicalLeftOffset();
158 segments[i].logicalRight += logicalLeftOffset();
164 template<class RenderType>
165 inline LayoutUnit borderBeforeInWritingMode(const RenderType& renderer, WritingMode writingMode)
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();
174 ASSERT_NOT_REACHED();
175 return renderer.borderBefore();
178 template<class RenderType>
179 inline LayoutUnit borderAndPaddingBeforeInWritingMode(const RenderType& renderer, WritingMode writingMode)
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();
188 ASSERT_NOT_REACHED();
189 return renderer.borderAndPaddingBefore();
192 template<class RenderType>
193 LayoutUnit ShapeInfo<RenderType>::logicalTopOffset() const
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;
203 ASSERT_NOT_REACHED();
207 template<class RenderType>
208 inline LayoutUnit borderStartWithStyleForWritingMode(const RenderType& renderer, const RenderStyle* style)
210 if (style->isHorizontalWritingMode()) {
211 if (style->isLeftToRightDirection())
212 return renderer.borderLeft();
214 return renderer.borderRight();
216 if (style->isLeftToRightDirection())
217 return renderer.borderTop();
219 return renderer.borderBottom();
222 template<class RenderType>
223 inline LayoutUnit borderAndPaddingStartWithStyleForWritingMode(const RenderType& renderer, const RenderStyle* style)
225 if (style->isHorizontalWritingMode()) {
226 if (style->isLeftToRightDirection())
227 return renderer.borderLeft() + renderer.paddingLeft();
229 return renderer.borderRight() + renderer.paddingRight();
231 if (style->isLeftToRightDirection())
232 return renderer.borderTop() + renderer.paddingTop();
234 return renderer.borderBottom() + renderer.paddingBottom();
237 template<class RenderType>
238 LayoutUnit ShapeInfo<RenderType>::logicalLeftOffset() const
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;
248 ASSERT_NOT_REACHED();
252 template class ShapeInfo<RenderBlock>;
253 template class ShapeInfo<RenderBox>;