| 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 HOLDERS AND CONTRIBUTORS | |
| 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
| 19 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
| 20 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, | |
| 21 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
| 23 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
| 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
| 25 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
| 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | |
| 27 * OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 28 */ | |
| 29 | |
| 30 #include "config.h" | |
| 31 #include "core/rendering/shapes/Shape.h" | |
| 32 | |
| 33 #include "core/css/BasicShapeFunctions.h" | |
| 34 #include "core/fetch/ImageResource.h" | |
| 35 #include "core/rendering/shapes/BoxShape.h" | |
| 36 #include "core/rendering/shapes/PolygonShape.h" | |
| 37 #include "core/rendering/shapes/RasterShape.h" | |
| 38 #include "core/rendering/shapes/RectangleShape.h" | |
| 39 #include "core/rendering/style/RenderStyle.h" | |
| 40 #include "platform/LengthFunctions.h" | |
| 41 #include "platform/geometry/FloatSize.h" | |
| 42 #include "platform/graphics/GraphicsContext.h" | |
| 43 #include "platform/graphics/GraphicsTypes.h" | |
| 44 #include "platform/graphics/ImageBuffer.h" | |
| 45 #include "wtf/MathExtras.h" | |
| 46 #include "wtf/OwnPtr.h" | |
| 47 | |
| 48 namespace blink { | |
| 49 | |
| 50 static PassOwnPtr<Shape> createInsetShape(const FloatRoundedRect& bounds) | |
| 51 { | |
| 52 ASSERT(bounds.rect().width() >= 0 && bounds.rect().height() >= 0); | |
| 53 return adoptPtr(new BoxShape(bounds)); | |
| 54 } | |
| 55 | |
| 56 static PassOwnPtr<Shape> createCircleShape(const FloatPoint& center, float radiu
s) | |
| 57 { | |
| 58 ASSERT(radius >= 0); | |
| 59 return adoptPtr(new RectangleShape(FloatRect(center.x() - radius, center.y()
- radius, radius*2, radius*2), FloatSize(radius, radius))); | |
| 60 } | |
| 61 | |
| 62 static PassOwnPtr<Shape> createEllipseShape(const FloatPoint& center, const Floa
tSize& radii) | |
| 63 { | |
| 64 ASSERT(radii.width() >= 0 && radii.height() >= 0); | |
| 65 return adoptPtr(new RectangleShape(FloatRect(center.x() - radii.width(), cen
ter.y() - radii.height(), radii.width()*2, radii.height()*2), radii)); | |
| 66 } | |
| 67 | |
| 68 static PassOwnPtr<Shape> createPolygonShape(PassOwnPtr<Vector<FloatPoint> > vert
ices, WindRule fillRule) | |
| 69 { | |
| 70 return adoptPtr(new PolygonShape(vertices, fillRule)); | |
| 71 } | |
| 72 | |
| 73 static inline FloatRect physicalRectToLogical(const FloatRect& rect, float logic
alBoxHeight) | |
| 74 { | |
| 75 return rect; | |
| 76 } | |
| 77 | |
| 78 static inline FloatPoint physicalPointToLogical(const FloatPoint& point, float l
ogicalBoxHeight) | |
| 79 { | |
| 80 return point; | |
| 81 } | |
| 82 | |
| 83 static inline FloatSize physicalSizeToLogical(const FloatSize& size) | |
| 84 { | |
| 85 return size; | |
| 86 } | |
| 87 | |
| 88 PassOwnPtr<Shape> Shape::createShape(const BasicShape* basicShape, const LayoutS
ize& logicalBoxSize, float margin) | |
| 89 { | |
| 90 ASSERT(basicShape); | |
| 91 | |
| 92 float boxWidth = logicalBoxSize.width().toFloat(); | |
| 93 float boxHeight = logicalBoxSize.height().toFloat(); | |
| 94 OwnPtr<Shape> shape; | |
| 95 | |
| 96 switch (basicShape->type()) { | |
| 97 | |
| 98 case BasicShape::BasicShapeCircleType: { | |
| 99 const BasicShapeCircle* circle = toBasicShapeCircle(basicShape); | |
| 100 FloatPoint center = floatPointForCenterCoordinate(circle->centerX(), cir
cle->centerY(), FloatSize(boxWidth, boxHeight)); | |
| 101 float radius = circle->floatValueForRadiusInBox(FloatSize(boxWidth, boxH
eight)); | |
| 102 FloatPoint logicalCenter = physicalPointToLogical(center, logicalBoxSize
.height().toFloat()); | |
| 103 | |
| 104 shape = createCircleShape(logicalCenter, radius); | |
| 105 break; | |
| 106 } | |
| 107 | |
| 108 case BasicShape::BasicShapeEllipseType: { | |
| 109 const BasicShapeEllipse* ellipse = toBasicShapeEllipse(basicShape); | |
| 110 FloatPoint center = floatPointForCenterCoordinate(ellipse->centerX(), el
lipse->centerY(), FloatSize(boxWidth, boxHeight)); | |
| 111 float radiusX = ellipse->floatValueForRadiusInBox(ellipse->radiusX(), ce
nter.x(), boxWidth); | |
| 112 float radiusY = ellipse->floatValueForRadiusInBox(ellipse->radiusY(), ce
nter.y(), boxHeight); | |
| 113 FloatPoint logicalCenter = physicalPointToLogical(center, logicalBoxSize
.height().toFloat()); | |
| 114 | |
| 115 shape = createEllipseShape(logicalCenter, FloatSize(radiusX, radiusY)); | |
| 116 break; | |
| 117 } | |
| 118 | |
| 119 case BasicShape::BasicShapePolygonType: { | |
| 120 const BasicShapePolygon* polygon = toBasicShapePolygon(basicShape); | |
| 121 const Vector<Length>& values = polygon->values(); | |
| 122 size_t valuesSize = values.size(); | |
| 123 ASSERT(!(valuesSize % 2)); | |
| 124 OwnPtr<Vector<FloatPoint> > vertices = adoptPtr(new Vector<FloatPoint>(v
aluesSize / 2)); | |
| 125 for (unsigned i = 0; i < valuesSize; i += 2) { | |
| 126 FloatPoint vertex( | |
| 127 floatValueForLength(values.at(i), boxWidth), | |
| 128 floatValueForLength(values.at(i + 1), boxHeight)); | |
| 129 (*vertices)[i / 2] = physicalPointToLogical(vertex, logicalBoxSize.h
eight().toFloat()); | |
| 130 } | |
| 131 shape = createPolygonShape(vertices.release(), polygon->windRule()); | |
| 132 break; | |
| 133 } | |
| 134 | |
| 135 case BasicShape::BasicShapeInsetType: { | |
| 136 const BasicShapeInset& inset = *toBasicShapeInset(basicShape); | |
| 137 float left = floatValueForLength(inset.left(), boxWidth); | |
| 138 float top = floatValueForLength(inset.top(), boxHeight); | |
| 139 float right = floatValueForLength(inset.right(), boxWidth); | |
| 140 float bottom = floatValueForLength(inset.bottom(), boxHeight); | |
| 141 FloatRect rect(left, top, std::max<float>(boxWidth - left - right, 0), s
td::max<float>(boxHeight - top - bottom, 0)); | |
| 142 FloatRect logicalRect = physicalRectToLogical(rect, logicalBoxSize.heigh
t().toFloat()); | |
| 143 | |
| 144 FloatSize boxSize(boxWidth, boxHeight); | |
| 145 FloatSize topLeftRadius = physicalSizeToLogical(floatSizeForLengthSize(i
nset.topLeftRadius(), boxSize)); | |
| 146 FloatSize topRightRadius = physicalSizeToLogical(floatSizeForLengthSize(
inset.topRightRadius(), boxSize)); | |
| 147 FloatSize bottomLeftRadius = physicalSizeToLogical(floatSizeForLengthSiz
e(inset.bottomLeftRadius(), boxSize)); | |
| 148 FloatSize bottomRightRadius = physicalSizeToLogical(floatSizeForLengthSi
ze(inset.bottomRightRadius(), boxSize)); | |
| 149 FloatRoundedRect::Radii cornerRadii(topLeftRadius, topRightRadius, botto
mLeftRadius, bottomRightRadius); | |
| 150 | |
| 151 cornerRadii.scale(calcBorderRadiiConstraintScaleFor(logicalRect, cornerR
adii)); | |
| 152 | |
| 153 shape = createInsetShape(FloatRoundedRect(logicalRect, cornerRadii)); | |
| 154 break; | |
| 155 } | |
| 156 | |
| 157 default: | |
| 158 ASSERT_NOT_REACHED(); | |
| 159 } | |
| 160 | |
| 161 shape->m_margin = margin; | |
| 162 | |
| 163 return shape.release(); | |
| 164 } | |
| 165 | |
| 166 PassOwnPtr<Shape> Shape::createEmptyRasterShape(float margin) | |
| 167 { | |
| 168 OwnPtr<RasterShapeIntervals> intervals = adoptPtr(new RasterShapeIntervals(0
, 0)); | |
| 169 OwnPtr<RasterShape> rasterShape = adoptPtr(new RasterShape(intervals.release
(), IntSize())); | |
| 170 rasterShape->m_margin = margin; | |
| 171 return rasterShape.release(); | |
| 172 } | |
| 173 | |
| 174 PassOwnPtr<Shape> Shape::createRasterShape(Image* image, float threshold, const
LayoutRect& imageR, const LayoutRect& marginR, float margin) | |
| 175 { | |
| 176 IntRect imageRect = pixelSnappedIntRect(imageR); | |
| 177 IntRect marginRect = pixelSnappedIntRect(marginR); | |
| 178 | |
| 179 OwnPtr<RasterShapeIntervals> intervals = adoptPtr(new RasterShapeIntervals(m
arginRect.height(), -marginRect.y())); | |
| 180 OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(imageRect.size()); | |
| 181 | |
| 182 if (imageBuffer) { | |
| 183 GraphicsContext* graphicsContext = imageBuffer->context(); | |
| 184 graphicsContext->drawImage(image, IntRect(IntPoint(), imageRect.size()))
; | |
| 185 | |
| 186 RefPtr<Uint8ClampedArray> pixelArray = imageBuffer->getImageData(Unmulti
plied, IntRect(IntPoint(), imageRect.size())); | |
| 187 unsigned pixelArrayOffset = 3; // Each pixel is four bytes: RGBA. | |
| 188 uint8_t alphaPixelThreshold = threshold * 255; | |
| 189 | |
| 190 ASSERT(static_cast<unsigned>(imageRect.width() * imageRect.height() * 4)
== pixelArray->length()); | |
| 191 | |
| 192 int minBufferY = std::max(0, marginRect.y() - imageRect.y()); | |
| 193 int maxBufferY = std::min(imageRect.height(), marginRect.maxY() - imageR
ect.y()); | |
| 194 | |
| 195 for (int y = minBufferY; y < maxBufferY; ++y) { | |
| 196 int startX = -1; | |
| 197 for (int x = 0; x < imageRect.width(); ++x, pixelArrayOffset += 4) { | |
| 198 uint8_t alpha = pixelArray->item(pixelArrayOffset); | |
| 199 bool alphaAboveThreshold = alpha > alphaPixelThreshold; | |
| 200 if (startX == -1 && alphaAboveThreshold) { | |
| 201 startX = x; | |
| 202 } else if (startX != -1 && (!alphaAboveThreshold || x == imageRe
ct.width() - 1)) { | |
| 203 int endX = alphaAboveThreshold ? x + 1 : x; | |
| 204 intervals->intervalAt(y + imageRect.y()).unite(IntShapeInter
val(startX + imageRect.x(), endX + imageRect.x())); | |
| 205 startX = -1; | |
| 206 } | |
| 207 } | |
| 208 } | |
| 209 } | |
| 210 | |
| 211 OwnPtr<RasterShape> rasterShape = adoptPtr(new RasterShape(intervals.release
(), marginRect.size())); | |
| 212 rasterShape->m_margin = margin; | |
| 213 return rasterShape.release(); | |
| 214 } | |
| 215 | |
| 216 PassOwnPtr<Shape> Shape::createLayoutBoxShape(const RoundedRect& roundedRect, fl
oat margin) | |
| 217 { | |
| 218 FloatRect rect(0, 0, roundedRect.rect().width(), roundedRect.rect().height()
); | |
| 219 FloatRoundedRect bounds(rect, roundedRect.radii()); | |
| 220 OwnPtr<Shape> shape = createInsetShape(bounds); | |
| 221 shape->m_margin = margin; | |
| 222 | |
| 223 return shape.release(); | |
| 224 } | |
| 225 | |
| 226 } // namespace blink | |
| OLD | NEW |