| OLD | NEW |
| (Empty) |
| 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/ShapeOutsideInfo.h" | |
| 32 | |
| 33 #include "core/inspector/ConsoleMessage.h" | |
| 34 #include "core/rendering/RenderBlockFlow.h" | |
| 35 #include "core/rendering/RenderBox.h" | |
| 36 #include "core/rendering/RenderImage.h" | |
| 37 #include "platform/LengthFunctions.h" | |
| 38 #include "public/platform/Platform.h" | |
| 39 | |
| 40 namespace blink { | |
| 41 | |
| 42 CSSBoxType referenceBox(const ShapeValue& shapeValue) | |
| 43 { | |
| 44 if (shapeValue.cssBox() == BoxMissing) | |
| 45 return MarginBox; | |
| 46 return shapeValue.cssBox(); | |
| 47 } | |
| 48 | |
| 49 void ShapeOutsideInfo::setReferenceBoxLogicalSize(LayoutSize newReferenceBoxLogi
calSize) | |
| 50 { | |
| 51 switch (referenceBox(*m_renderer.style()->shapeOutside())) { | |
| 52 case MarginBox: | |
| 53 newReferenceBoxLogicalSize.expand(m_renderer.marginWidth(), m_renderer.m
arginHeight()); | |
| 54 break; | |
| 55 case BorderBox: | |
| 56 break; | |
| 57 case PaddingBox: | |
| 58 newReferenceBoxLogicalSize.shrink(m_renderer.borderWidth(), m_renderer.b
orderHeight()); | |
| 59 break; | |
| 60 case ContentBox: | |
| 61 newReferenceBoxLogicalSize.shrink(m_renderer.borderAndPaddingWidth(), m_
renderer.borderAndPaddingHeight()); | |
| 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 static LayoutRect getShapeImageMarginRect(const RenderBox& renderBox, const Layo
utSize& referenceBoxLogicalSize) | |
| 75 { | |
| 76 LayoutPoint marginBoxOrigin(-renderBox.marginLogicalLeft() - renderBox.borde
rAndPaddingLogicalLeft(), -renderBox.marginBefore() - renderBox.borderBefore() -
renderBox.paddingBefore()); | |
| 77 LayoutSize marginBoxSizeDelta(renderBox.marginLogicalWidth() + renderBox.bor
derAndPaddingLogicalWidth(), renderBox.marginLogicalHeight() + renderBox.borderA
ndPaddingLogicalHeight()); | |
| 78 return LayoutRect(marginBoxOrigin, referenceBoxLogicalSize + marginBoxSizeDe
lta); | |
| 79 } | |
| 80 | |
| 81 static bool isValidRasterShapeRect(const LayoutRect& rect) | |
| 82 { | |
| 83 static double maxImageSizeBytes = 0; | |
| 84 if (!maxImageSizeBytes) { | |
| 85 size_t size32MaxBytes = 0xFFFFFFFF / 4; // Some platforms don't limit m
axDecodedImageBytes. | |
| 86 maxImageSizeBytes = std::min(size32MaxBytes, Platform::current()->maxDec
odedImageBytes()); | |
| 87 } | |
| 88 return (rect.width().toFloat() * rect.height().toFloat() * 4.0) < maxImageSi
zeBytes; | |
| 89 } | |
| 90 | |
| 91 PassOwnPtr<Shape> ShapeOutsideInfo::createShapeForImage(StyleImage* styleImage,
float shapeImageThreshold, float margin) const | |
| 92 { | |
| 93 const IntSize& imageSize = m_renderer.calculateImageIntrinsicDimensions(styl
eImage, roundedIntSize(m_referenceBoxLogicalSize), RenderImage::ScaleByEffective
Zoom); | |
| 94 styleImage->setContainerSizeForRenderer(&m_renderer, imageSize, m_renderer.s
tyle()->effectiveZoom()); | |
| 95 | |
| 96 const LayoutRect& marginRect = getShapeImageMarginRect(m_renderer, m_referen
ceBoxLogicalSize); | |
| 97 const LayoutRect& imageRect = (m_renderer.isRenderImage()) | |
| 98 ? toRenderImage(m_renderer).replacedContentRect() | |
| 99 : LayoutRect(LayoutPoint(), imageSize); | |
| 100 | |
| 101 if (!isValidRasterShapeRect(marginRect) || !isValidRasterShapeRect(imageRect
)) { | |
| 102 m_renderer.document().addConsoleMessage(ConsoleMessage::create(Rendering
MessageSource, ErrorMessageLevel, "The shape-outside image is too large.")); | |
| 103 return Shape::createEmptyRasterShape(margin); | |
| 104 } | |
| 105 | |
| 106 ASSERT(!styleImage->isPendingImage()); | |
| 107 RefPtr<Image> image = styleImage->image(const_cast<RenderBox*>(&m_renderer),
imageSize); | |
| 108 | |
| 109 return Shape::createRasterShape(image.get(), shapeImageThreshold, imageRect,
marginRect, margin); | |
| 110 } | |
| 111 | |
| 112 const Shape& ShapeOutsideInfo::computedShape() const | |
| 113 { | |
| 114 if (Shape* shape = m_shape.get()) | |
| 115 return *shape; | |
| 116 | |
| 117 const RenderStyle& style = *m_renderer.style(); | |
| 118 ASSERT(m_renderer.containingBlock()); | |
| 119 LayoutUnit maximumValue = m_renderer.containingBlock() ? m_renderer.containi
ngBlock()->contentWidth() : LayoutUnit(); | |
| 120 float margin = floatValueForLength(m_renderer.style()->shapeMargin(), maximu
mValue.toFloat()); | |
| 121 | |
| 122 float shapeImageThreshold = style.shapeImageThreshold(); | |
| 123 ASSERT(style.shapeOutside()); | |
| 124 const ShapeValue& shapeValue = *style.shapeOutside(); | |
| 125 | |
| 126 switch (shapeValue.type()) { | |
| 127 case ShapeValue::Shape: | |
| 128 ASSERT(shapeValue.shape()); | |
| 129 m_shape = Shape::createShape(shapeValue.shape(), m_referenceBoxLogicalSi
ze, margin); | |
| 130 break; | |
| 131 case ShapeValue::Image: | |
| 132 ASSERT(shapeValue.isImageValid()); | |
| 133 m_shape = createShapeForImage(shapeValue.image(), shapeImageThreshold, m
argin); | |
| 134 break; | |
| 135 case ShapeValue::Box: { | |
| 136 const RoundedRect& shapeRect = style.getRoundedBorderFor(LayoutRect(Layo
utPoint(), m_referenceBoxLogicalSize), m_renderer.view()); | |
| 137 m_shape = Shape::createLayoutBoxShape(shapeRect, margin); | |
| 138 break; | |
| 139 } | |
| 140 } | |
| 141 | |
| 142 ASSERT(m_shape); | |
| 143 return *m_shape; | |
| 144 } | |
| 145 | |
| 146 LayoutUnit ShapeOutsideInfo::logicalTopOffset() const | |
| 147 { | |
| 148 switch (referenceBox(*m_renderer.style()->shapeOutside())) { | |
| 149 case MarginBox: return -m_renderer.marginBefore(m_renderer.containingBlock()
->style()); | |
| 150 case BorderBox: return LayoutUnit(); | |
| 151 case PaddingBox: return m_renderer.borderBefore(); | |
| 152 case ContentBox: return m_renderer.borderAndPaddingBefore(); | |
| 153 case BoxMissing: break; | |
| 154 } | |
| 155 | |
| 156 ASSERT_NOT_REACHED(); | |
| 157 return LayoutUnit(); | |
| 158 } | |
| 159 | |
| 160 inline LayoutUnit borderStartWithStyle(const RenderBox& renderer, const RenderSt
yle* style) | |
| 161 { | |
| 162 if (style->isLeftToRightDirection()) | |
| 163 return renderer.borderLeft(); | |
| 164 return renderer.borderRight(); | |
| 165 } | |
| 166 | |
| 167 inline LayoutUnit borderAndPaddingStartWithStyle(const RenderBox& renderer, cons
t RenderStyle* style) | |
| 168 { | |
| 169 if (style->isLeftToRightDirection()) | |
| 170 return renderer.borderLeft() + renderer.paddingLeft(); | |
| 171 | |
| 172 return renderer.borderRight() + renderer.paddingRight(); | |
| 173 } | |
| 174 | |
| 175 LayoutUnit ShapeOutsideInfo::logicalLeftOffset() const | |
| 176 { | |
| 177 switch (referenceBox(*m_renderer.style()->shapeOutside())) { | |
| 178 case MarginBox: return -m_renderer.marginStart(m_renderer.containingBlock()-
>style()); | |
| 179 case BorderBox: return LayoutUnit(); | |
| 180 case PaddingBox: return borderStartWithStyle(m_renderer, m_renderer.containi
ngBlock()->style()); | |
| 181 case ContentBox: return borderAndPaddingStartWithStyle(m_renderer, m_rendere
r.containingBlock()->style()); | |
| 182 case BoxMissing: break; | |
| 183 } | |
| 184 | |
| 185 ASSERT_NOT_REACHED(); | |
| 186 return LayoutUnit(); | |
| 187 } | |
| 188 | |
| 189 | |
| 190 bool ShapeOutsideInfo::isEnabledFor(const RenderBox& box) | |
| 191 { | |
| 192 ShapeValue* shapeValue = box.style()->shapeOutside(); | |
| 193 if (!shapeValue) | |
| 194 return false; | |
| 195 | |
| 196 switch (shapeValue->type()) { | |
| 197 case ShapeValue::Shape: | |
| 198 return shapeValue->shape(); | |
| 199 case ShapeValue::Image: | |
| 200 return shapeValue->isImageValid(); | |
| 201 case ShapeValue::Box: | |
| 202 return true; | |
| 203 } | |
| 204 | |
| 205 return false; | |
| 206 } | |
| 207 | |
| 208 ShapeOutsideDeltas ShapeOutsideInfo::computeDeltasForContainingBlockLine(const R
enderBlockFlow& containingBlock, const FloatingObject& floatingObject, LayoutUni
t lineTop, LayoutUnit lineHeight) | |
| 209 { | |
| 210 // FIXME(sky): Remove this. | |
| 211 return ShapeOutsideDeltas(); | |
| 212 } | |
| 213 | |
| 214 LayoutRect ShapeOutsideInfo::computedShapePhysicalBoundingBox() const | |
| 215 { | |
| 216 LayoutRect physicalBoundingBox = computedShape().shapeMarginLogicalBoundingB
ox(); | |
| 217 physicalBoundingBox.setX(physicalBoundingBox.x() + logicalLeftOffset()); | |
| 218 | |
| 219 // FIXME(sky): Doing this twice doesn't seem right, but it's what the old co
de did. | |
| 220 physicalBoundingBox.setY(physicalBoundingBox.y() + logicalTopOffset()); | |
| 221 physicalBoundingBox.setY(physicalBoundingBox.y() + logicalTopOffset()); | |
| 222 | |
| 223 return physicalBoundingBox; | |
| 224 } | |
| 225 | |
| 226 FloatPoint ShapeOutsideInfo::shapeToRendererPoint(FloatPoint point) const | |
| 227 { | |
| 228 return FloatPoint(point.x() + logicalLeftOffset(), point.y() + logicalTopOff
set()); | |
| 229 } | |
| 230 | |
| 231 FloatSize ShapeOutsideInfo::shapeToRendererSize(FloatSize size) const | |
| 232 { | |
| 233 return size; | |
| 234 } | |
| 235 | |
| 236 } // namespace blink | |
| OLD | NEW |