15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * are met:
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 1. Redistributions of source code must retain the above
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    copyright notice, this list of conditions and the following
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    disclaimer.
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 2. Redistributions in binary form must reproduce the above
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    copyright notice, this list of conditions and the following
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    disclaimer in the documentation and/or other materials
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    provided with the distribution.
1553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) *
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THE POSSIBILITY OF SUCH DAMAGE.
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
31591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "core/rendering/shapes/Shape.h"
3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
3309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "core/css/BasicShapeFunctions.h"
34e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)#include "core/fetch/ImageResource.h"
35a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "core/rendering/shapes/BoxShape.h"
36591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "core/rendering/shapes/PolygonShape.h"
37e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)#include "core/rendering/shapes/RasterShape.h"
38591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "core/rendering/shapes/RectangleShape.h"
39d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "core/rendering/style/RenderStyle.h"
40bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)#include "platform/LengthFunctions.h"
411e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/geometry/FloatSize.h"
425d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)#include "platform/graphics/GraphicsContext.h"
43e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#include "platform/graphics/GraphicsTypes.h"
44a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/ImageBuffer.h"
45591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "wtf/MathExtras.h"
46591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "wtf/OwnPtr.h"
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
48c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)static PassOwnPtr<Shape> createInsetShape(const FloatRoundedRect& bounds)
51a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles){
52a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    ASSERT(bounds.rect().width() >= 0 && bounds.rect().height() >= 0);
5309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return adoptPtr(new BoxShape(bounds));
54a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)}
55a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
56591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochstatic PassOwnPtr<Shape> createCircleShape(const FloatPoint& center, float radius)
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(radius >= 0);
59591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    return adoptPtr(new RectangleShape(FloatRect(center.x() - radius, center.y() - radius, radius*2, radius*2), FloatSize(radius, radius)));
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
62591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochstatic PassOwnPtr<Shape> createEllipseShape(const FloatPoint& center, const FloatSize& radii)
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(radii.width() >= 0 && radii.height() >= 0);
65591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    return adoptPtr(new RectangleShape(FloatRect(center.x() - radii.width(), center.y() - radii.height(), radii.width()*2, radii.height()*2), radii));
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
68591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochstatic PassOwnPtr<Shape> createPolygonShape(PassOwnPtr<Vector<FloatPoint> > vertices, WindRule fillRule)
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
70591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    return adoptPtr(new PolygonShape(vertices, fillRule));
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
73926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)static inline FloatRect physicalRectToLogical(const FloatRect& rect, float logicalBoxHeight, WritingMode writingMode)
74926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
75926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (isHorizontalWritingMode(writingMode))
76926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return rect;
77926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (isFlippedBlocksWritingMode(writingMode))
78926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return FloatRect(rect.y(), logicalBoxHeight - rect.maxX(), rect.height(), rect.width());
79926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return rect.transposedRect();
80926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
81926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
82926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)static inline FloatPoint physicalPointToLogical(const FloatPoint& point, float logicalBoxHeight, WritingMode writingMode)
83926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
84926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (isHorizontalWritingMode(writingMode))
85926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return point;
86926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (isFlippedBlocksWritingMode(writingMode))
87926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return FloatPoint(point.y(), logicalBoxHeight - point.x());
88926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return point.transposedPoint();
89926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
90926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
91926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)static inline FloatSize physicalSizeToLogical(const FloatSize& size, WritingMode writingMode)
92926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
93926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (isHorizontalWritingMode(writingMode))
94926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return size;
95926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return size.transposedSize();
96926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
986f543c786fc42989f552b4daa774ca5ff32fa697Ben MurdochPassOwnPtr<Shape> Shape::createShape(const BasicShape* basicShape, const LayoutSize& logicalBoxSize, WritingMode writingMode, float margin)
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
100926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ASSERT(basicShape);
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool horizontalWritingMode = isHorizontalWritingMode(writingMode);
10343e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)    float boxWidth = horizontalWritingMode ? logicalBoxSize.width().toFloat() : logicalBoxSize.height().toFloat();
10443e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)    float boxHeight = horizontalWritingMode ? logicalBoxSize.height().toFloat() : logicalBoxSize.width().toFloat();
105591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    OwnPtr<Shape> shape;
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (basicShape->type()) {
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    case BasicShape::BasicShapeCircleType: {
110197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        const BasicShapeCircle* circle = toBasicShapeCircle(basicShape);
11109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        FloatPoint center = floatPointForCenterCoordinate(circle->centerX(), circle->centerY(), FloatSize(boxWidth, boxHeight));
11209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        float radius = circle->floatValueForRadiusInBox(FloatSize(boxWidth, boxHeight));
11343e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)        FloatPoint logicalCenter = physicalPointToLogical(center, logicalBoxSize.height().toFloat(), writingMode);
11409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
11509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        shape = createCircleShape(logicalCenter, radius);
11609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        break;
11709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
11809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
11909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    case BasicShape::BasicShapeEllipseType: {
120197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        const BasicShapeEllipse* ellipse = toBasicShapeEllipse(basicShape);
12109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        FloatPoint center = floatPointForCenterCoordinate(ellipse->centerX(), ellipse->centerY(), FloatSize(boxWidth, boxHeight));
12209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        float radiusX = ellipse->floatValueForRadiusInBox(ellipse->radiusX(), center.x(), boxWidth);
12309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        float radiusY = ellipse->floatValueForRadiusInBox(ellipse->radiusY(), center.y(), boxHeight);
12443e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)        FloatPoint logicalCenter = physicalPointToLogical(center, logicalBoxSize.height().toFloat(), writingMode);
12509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
12609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        shape = createEllipseShape(logicalCenter, FloatSize(radiusX, radiusY));
12709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        break;
12809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
12909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
1305267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    case BasicShape::BasicShapePolygonType: {
131197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        const BasicShapePolygon* polygon = toBasicShapePolygon(basicShape);
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const Vector<Length>& values = polygon->values();
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        size_t valuesSize = values.size();
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(!(valuesSize % 2));
13553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        OwnPtr<Vector<FloatPoint> > vertices = adoptPtr(new Vector<FloatPoint>(valuesSize / 2));
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (unsigned i = 0; i < valuesSize; i += 2) {
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            FloatPoint vertex(
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                floatValueForLength(values.at(i), boxWidth),
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                floatValueForLength(values.at(i + 1), boxHeight));
14043e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)            (*vertices)[i / 2] = physicalPointToLogical(vertex, logicalBoxSize.height().toFloat(), writingMode);
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
142591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        shape = createPolygonShape(vertices.release(), polygon->windRule());
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    case BasicShape::BasicShapeInsetType: {
147197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        const BasicShapeInset& inset = *toBasicShapeInset(basicShape);
14809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        float left = floatValueForLength(inset.left(), boxWidth);
14909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        float top = floatValueForLength(inset.top(), boxHeight);
15009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        float right = floatValueForLength(inset.right(), boxWidth);
15109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        float bottom = floatValueForLength(inset.bottom(), boxHeight);
152d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        FloatRect rect(left, top, std::max<float>(boxWidth - left - right, 0), std::max<float>(boxHeight - top - bottom, 0));
15343e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)        FloatRect logicalRect = physicalRectToLogical(rect, logicalBoxSize.height().toFloat(), writingMode);
15409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
15509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        FloatSize boxSize(boxWidth, boxHeight);
156d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        FloatSize topLeftRadius = physicalSizeToLogical(floatSizeForLengthSize(inset.topLeftRadius(), boxSize), writingMode);
157d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        FloatSize topRightRadius = physicalSizeToLogical(floatSizeForLengthSize(inset.topRightRadius(), boxSize), writingMode);
158d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        FloatSize bottomLeftRadius = physicalSizeToLogical(floatSizeForLengthSize(inset.bottomLeftRadius(), boxSize), writingMode);
159d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        FloatSize bottomRightRadius = physicalSizeToLogical(floatSizeForLengthSize(inset.bottomRightRadius(), boxSize), writingMode);
160d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        FloatRoundedRect::Radii cornerRadii(topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
161d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
162d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        cornerRadii.scale(calcBorderRadiiConstraintScaleFor(logicalRect, cornerRadii));
16309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
16409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        shape = createInsetShape(FloatRoundedRect(logicalRect, cornerRadii));
16509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        break;
16609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
16709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    default:
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT_NOT_REACHED();
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
172591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    shape->m_writingMode = writingMode;
1736f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    shape->m_margin = margin;
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
175591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    return shape.release();
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
178197021e6b966cfb06891637935ef33fff06433d1Ben MurdochPassOwnPtr<Shape> Shape::createEmptyRasterShape(WritingMode writingMode, float margin)
179197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch{
180197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    OwnPtr<RasterShapeIntervals> intervals = adoptPtr(new RasterShapeIntervals(0, 0));
181197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    OwnPtr<RasterShape> rasterShape = adoptPtr(new RasterShape(intervals.release(), IntSize()));
182197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    rasterShape->m_writingMode = writingMode;
183197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    rasterShape->m_margin = margin;
184197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    return rasterShape.release();
185197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch}
186197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
1876f543c786fc42989f552b4daa774ca5ff32fa697Ben MurdochPassOwnPtr<Shape> Shape::createRasterShape(Image* image, float threshold, const LayoutRect& imageR, const LayoutRect& marginR, WritingMode writingMode, float margin)
188e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles){
189d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    IntRect imageRect = pixelSnappedIntRect(imageR);
190d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    IntRect marginRect = pixelSnappedIntRect(marginR);
191197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
192d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    OwnPtr<RasterShapeIntervals> intervals = adoptPtr(new RasterShapeIntervals(marginRect.height(), -marginRect.y()));
193d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(imageRect.size());
194e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
195e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    if (imageBuffer) {
196e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        GraphicsContext* graphicsContext = imageBuffer->context();
197d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        graphicsContext->drawImage(image, IntRect(IntPoint(), imageRect.size()));
198e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
199197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        RefPtr<Uint8ClampedArray> pixelArray = imageBuffer->getImageData(Unmultiplied, IntRect(IntPoint(), imageRect.size()));
200e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        unsigned pixelArrayOffset = 3; // Each pixel is four bytes: RGBA.
201e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        uint8_t alphaPixelThreshold = threshold * 255;
202e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
203d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        ASSERT(static_cast<unsigned>(imageRect.width() * imageRect.height() * 4) == pixelArray->length());
204d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
205d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        int minBufferY = std::max(0, marginRect.y() - imageRect.y());
206d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        int maxBufferY = std::min(imageRect.height(), marginRect.maxY() - imageRect.y());
207e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
208d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        for (int y = minBufferY; y < maxBufferY; ++y) {
209e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            int startX = -1;
210d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            for (int x = 0; x < imageRect.width(); ++x, pixelArrayOffset += 4) {
211e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                uint8_t alpha = pixelArray->item(pixelArrayOffset);
212d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                bool alphaAboveThreshold = alpha > alphaPixelThreshold;
213d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                if (startX == -1 && alphaAboveThreshold) {
214e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                    startX = x;
215d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                } else if (startX != -1 && (!alphaAboveThreshold || x == imageRect.width() - 1)) {
21610f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch                    int endX = alphaAboveThreshold ? x + 1 : x;
21710f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch                    intervals->intervalAt(y + imageRect.y()).unite(IntShapeInterval(startX + imageRect.x(), endX + imageRect.x()));
218e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                    startX = -1;
219e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                }
220e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            }
221e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        }
222e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    }
223e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
224d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    OwnPtr<RasterShape> rasterShape = adoptPtr(new RasterShape(intervals.release(), marginRect.size()));
225e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    rasterShape->m_writingMode = writingMode;
2266f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    rasterShape->m_margin = margin;
227e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    return rasterShape.release();
228e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)}
229e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
2306f543c786fc42989f552b4daa774ca5ff32fa697Ben MurdochPassOwnPtr<Shape> Shape::createLayoutBoxShape(const RoundedRect& roundedRect, WritingMode writingMode, float margin)
231a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles){
23209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    FloatRect rect(0, 0, roundedRect.rect().width(), roundedRect.rect().height());
23309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    FloatRoundedRect bounds(rect, roundedRect.radii());
23409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    OwnPtr<Shape> shape = createInsetShape(bounds);
235a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    shape->m_writingMode = writingMode;
2366f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    shape->m_margin = margin;
237a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
238a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    return shape.release();
239a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)}
240a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
241c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink
242