153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)/*
253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * Copyright (C) 2003, 2006 Apple Computer, Inc.  All rights reserved.
353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) *                     2006 Rob Buis <buis@kde.org>
453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * Copyright (C) 2013 Google Inc. All rights reserved.
68abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) * Copyright (C) 2013 Intel Corporation. All rights reserved.
753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) *
853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * Redistribution and use in source and binary forms, with or without
953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * modification, are permitted provided that the following conditions
1053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * are met:
1153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * 1. Redistributions of source code must retain the above copyright
1253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) *    notice, this list of conditions and the following disclaimer.
1353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright
1453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) *    notice, this list of conditions and the following disclaimer in the
1553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) *    documentation and/or other materials provided with the distribution.
1653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) *
1753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
1853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
2153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
2553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) */
2953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
3053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "config.h"
31a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/Path.h"
3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include <math.h>
341e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/geometry/FloatPoint.h"
351e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/geometry/FloatRect.h"
36a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/GraphicsContext.h"
37a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/skia/SkiaUtils.h"
381e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/transforms/AffineTransform.h"
39e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)#include "third_party/skia/include/core/SkPathMeasure.h"
40e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch#include "third_party/skia/include/pathops/SkPathOps.h"
417757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "wtf/MathExtras.h"
4253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
4353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)namespace WebCore {
4453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
4553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)Path::Path()
4653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    : m_path()
4753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
4853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
4953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
5053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)Path::Path(const Path& other)
5153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
5253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    m_path = SkPath(other.m_path);
5353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
5453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
5553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)Path::~Path()
5653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
5753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
5853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
5953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)Path& Path::operator=(const Path& other)
6053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
6153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    m_path = SkPath(other.m_path);
6253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    return *this;
6353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
6453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
6553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)bool Path::operator==(const Path& other) const
6653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
6753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    return m_path == other.m_path;
6853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
6953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
7053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)bool Path::contains(const FloatPoint& point, WindRule rule) const
7153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
7283750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch    return SkPathContainsPoint(m_path, point, rule == RULE_NONZERO ? SkPath::kWinding_FillType : SkPath::kEvenOdd_FillType);
7353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
7453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
75521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)bool Path::strokeContains(const FloatPoint& point, const StrokeData& strokeData) const
7653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
7753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    SkPaint paint;
78521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    strokeData.setupPaint(&paint);
7953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    SkPath strokePath;
8053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    paint.getFillPath(m_path, &strokePath);
8153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
8283750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch    return SkPathContainsPoint(strokePath, point, SkPath::kWinding_FillType);
8353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
8453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
8553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)FloatRect Path::boundingRect() const
8653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
8753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    return m_path.getBounds();
8853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
8953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
90521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)FloatRect Path::strokeBoundingRect(const StrokeData& strokeData) const
9153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
9253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    SkPaint paint;
93521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    strokeData.setupPaint(&paint);
9453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    SkPath boundingPath;
9553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    paint.getFillPath(m_path, &boundingPath);
9653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
97521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    return boundingPath.getBounds();
9853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
9953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
10053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)static FloatPoint* convertPathPoints(FloatPoint dst[], const SkPoint src[], int count)
10153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
10253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    for (int i = 0; i < count; i++) {
10353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        dst[i].setX(SkScalarToFloat(src[i].fX));
10453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        dst[i].setY(SkScalarToFloat(src[i].fY));
10553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    }
10653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    return dst;
10753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
10853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
10953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void Path::apply(void* info, PathApplierFunction function) const
11053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
11153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    SkPath::RawIter iter(m_path);
11253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    SkPoint pts[4];
11353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    PathElement pathElement;
11453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    FloatPoint pathPoints[3];
11553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
11653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    for (;;) {
11753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        switch (iter.next(pts)) {
11853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        case SkPath::kMove_Verb:
11953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            pathElement.type = PathElementMoveToPoint;
12053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            pathElement.points = convertPathPoints(pathPoints, &pts[0], 1);
12153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            break;
12253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        case SkPath::kLine_Verb:
12353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            pathElement.type = PathElementAddLineToPoint;
12453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            pathElement.points = convertPathPoints(pathPoints, &pts[1], 1);
12553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            break;
12653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        case SkPath::kQuad_Verb:
12753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            pathElement.type = PathElementAddQuadCurveToPoint;
12853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            pathElement.points = convertPathPoints(pathPoints, &pts[1], 2);
12953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            break;
13053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        case SkPath::kCubic_Verb:
13153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            pathElement.type = PathElementAddCurveToPoint;
13253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            pathElement.points = convertPathPoints(pathPoints, &pts[1], 3);
13353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            break;
13453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        case SkPath::kClose_Verb:
13553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            pathElement.type = PathElementCloseSubpath;
13653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            pathElement.points = convertPathPoints(pathPoints, 0, 0);
13753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            break;
13853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        case SkPath::kDone_Verb:
13953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            return;
1405267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        default: // place-holder for kConic_Verb, when that lands from skia
1415267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)            break;
14253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        }
14353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        function(info, &pathElement);
14453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    }
14553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
14653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
14753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void Path::transform(const AffineTransform& xform)
14853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
1491e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    m_path.transform(affineTransformToSkMatrix(xform));
15053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
15153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
15253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)float Path::length() const
15353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
154e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)    SkScalar length = 0;
155e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)    SkPathMeasure measure(m_path, false);
156e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)
157e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)    do {
158e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)        length += measure.getLength();
159e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)    } while (measure.nextContour());
160e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)
161e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)    return SkScalarToFloat(length);
16253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
16353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
16453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)FloatPoint Path::pointAtLength(float length, bool& ok) const
16553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
166e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)    FloatPoint point;
167e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)    float normal;
168e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)    ok = pointAndNormalAtLength(length, point, normal);
169e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)    return point;
17053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
17153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
17253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)float Path::normalAngleAtLength(float length, bool& ok) const
17353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
174e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)    FloatPoint point;
175e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)    float normal;
176e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)    ok = pointAndNormalAtLength(length, point, normal);
177e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)    return normal;
178e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)}
179e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)
180e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)bool Path::pointAndNormalAtLength(float length, FloatPoint& point, float& normal) const
181e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles){
182e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)    SkPathMeasure measure(m_path, false);
183e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)
184e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)    do {
185e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)        SkScalar contourLength = measure.getLength();
186e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)        if (length <= contourLength) {
187e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)            SkVector tangent;
188e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)            SkPoint position;
189e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)
190e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)            if (measure.getPosTan(length, &position, &tangent)) {
191e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)                normal = rad2deg(SkScalarToFloat(SkScalarATan2(tangent.fY, tangent.fX)));
192e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)                point = FloatPoint(SkScalarToFloat(position.fX), SkScalarToFloat(position.fY));
193e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)                return true;
194e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)            }
195e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)        }
196e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)        length -= contourLength;
197e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)    } while (measure.nextContour());
198e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)
199e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)    normal = 0;
200e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)    point = FloatPoint(0, 0);
201e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)    return false;
20253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
20353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
20453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void Path::clear()
20553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
20653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    m_path.reset();
20753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
20853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
20953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)bool Path::isEmpty() const
21053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
21153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    return m_path.isEmpty();
21253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
21353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
21453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)bool Path::hasCurrentPoint() const
21553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
21653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    return m_path.getPoints(0, 0);
21753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
21853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
21953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)FloatPoint Path::currentPoint() const
22053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
22153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (m_path.countPoints() > 0) {
22253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        SkPoint skResult;
22353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        m_path.getLastPt(&skResult);
22453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        FloatPoint result;
22553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        result.setX(SkScalarToFloat(skResult.fX));
22653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        result.setY(SkScalarToFloat(skResult.fY));
22753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        return result;
22853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    }
22953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
23053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    // FIXME: Why does this return quietNaN? Other ports return 0,0.
23153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    float quietNaN = std::numeric_limits<float>::quiet_NaN();
23253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    return FloatPoint(quietNaN, quietNaN);
23353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
23453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
235e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben MurdochWindRule Path::windRule() const
236e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch{
237e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    return m_path.getFillType() == SkPath::kEvenOdd_FillType
238e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        ? RULE_EVENODD
239e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        : RULE_NONZERO;
240e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch}
241e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
242e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdochvoid Path::setWindRule(const WindRule rule)
243e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch{
244e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    m_path.setFillType(rule == RULE_EVENODD
245e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        ? SkPath::kEvenOdd_FillType
246e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        : SkPath::kWinding_FillType);
247e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch}
248e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
24953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void Path::moveTo(const FloatPoint& point)
25053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
25153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    m_path.moveTo(point);
25253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
25353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
25453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void Path::addLineTo(const FloatPoint& point)
25553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
25653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    m_path.lineTo(point);
25753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
25853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
25953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void Path::addQuadCurveTo(const FloatPoint& cp, const FloatPoint& ep)
26053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
26153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    m_path.quadTo(cp, ep);
26253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
26353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
26453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void Path::addBezierCurveTo(const FloatPoint& p1, const FloatPoint& p2, const FloatPoint& ep)
26553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
26653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    m_path.cubicTo(p1, p2, ep);
26753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
26853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
26953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void Path::addArcTo(const FloatPoint& p1, const FloatPoint& p2, float radius)
27053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
27153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    m_path.arcTo(p1, p2, WebCoreFloatToSkScalar(radius));
27253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
27353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
27453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void Path::closeSubpath()
27553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
27653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    m_path.close();
27753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
27853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
2791e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)void Path::addEllipse(const FloatPoint& p, float radiusX, float radiusY, float startAngle, float endAngle, bool anticlockwise)
28053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
281e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)    ASSERT(ellipseIsRenderable(startAngle, endAngle));
2828abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    ASSERT(startAngle >= 0 && startAngle < 2 * piFloat);
2838abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    ASSERT((anticlockwise && (startAngle - endAngle) >= 0) || (!anticlockwise && (endAngle - startAngle) >= 0));
2848abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)
28553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    SkScalar cx = WebCoreFloatToSkScalar(p.x());
28653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    SkScalar cy = WebCoreFloatToSkScalar(p.y());
2871e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    SkScalar radiusXScalar = WebCoreFloatToSkScalar(radiusX);
2881e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    SkScalar radiusYScalar = WebCoreFloatToSkScalar(radiusY);
28953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
29053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    SkRect oval;
2911e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    oval.set(cx - radiusXScalar, cy - radiusYScalar, cx + radiusXScalar, cy + radiusYScalar);
29253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
293c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)    float sweep = endAngle - startAngle;
294c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)    SkScalar startDegrees = WebCoreFloatToSkScalar(startAngle * 180 / piFloat);
29553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    SkScalar sweepDegrees = WebCoreFloatToSkScalar(sweep * 180 / piFloat);
296e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)    SkScalar s360 = SkIntToScalar(360);
2978abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)
2988abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    // We can't use SkPath::addOval(), because addOval() makes new sub-path. addOval() calls moveTo() and close() internally.
2998abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)
3008abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    // Use s180, not s360, because SkPath::arcTo(oval, angle, s360, false) draws nothing.
3018abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    SkScalar s180 = SkIntToScalar(180);
302e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)    if (SkScalarNearlyEqual(sweepDegrees, s360)) {
3038abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)        // SkPath::arcTo can't handle the sweepAngle that is equal to or greater than 2Pi.
3048abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)        m_path.arcTo(oval, startDegrees, s180, false);
3058abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)        m_path.arcTo(oval, startDegrees + s180, s180, false);
3068abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)        return;
3078abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    }
308e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)    if (SkScalarNearlyEqual(sweepDegrees, -s360)) {
3098abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)        m_path.arcTo(oval, startDegrees, -s180, false);
3108abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)        m_path.arcTo(oval, startDegrees - s180, -s180, false);
31153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        return;
31253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    }
31353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
31453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    m_path.arcTo(oval, startDegrees, sweepDegrees, false);
31553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
31653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
3171e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)void Path::addArc(const FloatPoint& p, float radius, float startAngle, float endAngle, bool anticlockwise)
3181e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles){
3191e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    addEllipse(p, radius, radius, startAngle, endAngle, anticlockwise);
3201e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)}
3211e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
32253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void Path::addRect(const FloatRect& rect)
32353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
32453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    m_path.addRect(rect);
32553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
32653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
327c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)void Path::addEllipse(const FloatPoint& p, float radiusX, float radiusY, float rotation, float startAngle, float endAngle, bool anticlockwise)
328c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles){
329e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)    ASSERT(ellipseIsRenderable(startAngle, endAngle));
3308abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    ASSERT(startAngle >= 0 && startAngle < 2 * piFloat);
3318abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    ASSERT((anticlockwise && (startAngle - endAngle) >= 0) || (!anticlockwise && (endAngle - startAngle) >= 0));
3328abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)
333bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    if (!rotation) {
334bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        addEllipse(FloatPoint(p.x(), p.y()), radiusX, radiusY, startAngle, endAngle, anticlockwise);
335bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        return;
336c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)    }
337c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)
338c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)    // Add an arc after the relevant transform.
3391e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    AffineTransform ellipseTransform = AffineTransform::translation(p.x(), p.y()).rotate(rad2deg(rotation));
340c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)    ASSERT(ellipseTransform.isInvertible());
341c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)    AffineTransform inverseEllipseTransform = ellipseTransform.inverse();
342c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)    transform(inverseEllipseTransform);
3431e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    addEllipse(FloatPoint::zero(), radiusX, radiusY, startAngle, endAngle, anticlockwise);
344c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)    transform(ellipseTransform);
345c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)}
346c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)
34753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void Path::addEllipse(const FloatRect& rect)
34853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
34953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    m_path.addOval(rect);
35053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
35153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
35253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void Path::addRoundedRect(const RoundedRect& r)
35353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
35453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    addRoundedRect(r.rect(), r.radii().topLeft(), r.radii().topRight(), r.radii().bottomLeft(), r.radii().bottomRight());
35553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
35653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
3570019e4eead4d990e4304c54a9028aca9122fb256Ben Murdochvoid Path::addRoundedRect(const FloatRect& rect, const FloatSize& roundingRadii)
35853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
35953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (rect.isEmpty())
36053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        return;
36153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
36253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    FloatSize radius(roundingRadii);
36353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    FloatSize halfSize(rect.width() / 2, rect.height() / 2);
36453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
36553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    // Apply the SVG corner radius constraints, per the rect section of the SVG shapes spec: if
36602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch    // one of rx,ry is negative, then the other corner radius value is used. If both values are
36753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    // negative then rx = ry = 0. If rx is greater than half of the width of the rectangle
36853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    // then set rx to half of the width; ry is handled similarly.
36953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
37053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (radius.width() < 0)
37153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        radius.setWidth((radius.height() < 0) ? 0 : radius.height());
37253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
37353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (radius.height() < 0)
37453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        radius.setHeight(radius.width());
37553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
37653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (radius.width() > halfSize.width())
37753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        radius.setWidth(halfSize.width());
37853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
37953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (radius.height() > halfSize.height())
38053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        radius.setHeight(halfSize.height());
38153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
3820019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch    addPathForRoundedRect(rect, radius, radius, radius, radius);
38353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
38453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
3850019e4eead4d990e4304c54a9028aca9122fb256Ben Murdochvoid Path::addRoundedRect(const FloatRect& rect, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius)
38653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
38753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (rect.isEmpty())
38853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        return;
38953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
39053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (rect.width() < topLeftRadius.width() + topRightRadius.width()
39153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            || rect.width() < bottomLeftRadius.width() + bottomRightRadius.width()
39253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            || rect.height() < topLeftRadius.height() + bottomLeftRadius.height()
39353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            || rect.height() < topRightRadius.height() + bottomRightRadius.height()) {
39453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        // If all the radii cannot be accommodated, return a rect.
39553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        addRect(rect);
39653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        return;
39753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    }
39853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
3990019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch    addPathForRoundedRect(rect, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
40053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
40153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
4020019e4eead4d990e4304c54a9028aca9122fb256Ben Murdochvoid Path::addPathForRoundedRect(const FloatRect& rect, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius)
40353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
40453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    addBeziersForRoundedRect(rect, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
40553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
40653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
40753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)// Approximation of control point positions on a bezier to simulate a quarter of a circle.
40853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)// This is 1-kappa, where kappa = 4 * (sqrt(2) - 1) / 3
40953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)static const float gCircleControlPoint = 0.447715f;
41053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
41153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void Path::addBeziersForRoundedRect(const FloatRect& rect, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius)
41253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
41353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    moveTo(FloatPoint(rect.x() + topLeftRadius.width(), rect.y()));
41453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
41553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    addLineTo(FloatPoint(rect.maxX() - topRightRadius.width(), rect.y()));
41653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (topRightRadius.width() > 0 || topRightRadius.height() > 0)
41753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        addBezierCurveTo(FloatPoint(rect.maxX() - topRightRadius.width() * gCircleControlPoint, rect.y()),
41853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            FloatPoint(rect.maxX(), rect.y() + topRightRadius.height() * gCircleControlPoint),
41953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            FloatPoint(rect.maxX(), rect.y() + topRightRadius.height()));
42053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    addLineTo(FloatPoint(rect.maxX(), rect.maxY() - bottomRightRadius.height()));
42153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (bottomRightRadius.width() > 0 || bottomRightRadius.height() > 0)
42253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        addBezierCurveTo(FloatPoint(rect.maxX(), rect.maxY() - bottomRightRadius.height() * gCircleControlPoint),
42353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            FloatPoint(rect.maxX() - bottomRightRadius.width() * gCircleControlPoint, rect.maxY()),
42453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            FloatPoint(rect.maxX() - bottomRightRadius.width(), rect.maxY()));
42553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    addLineTo(FloatPoint(rect.x() + bottomLeftRadius.width(), rect.maxY()));
42653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (bottomLeftRadius.width() > 0 || bottomLeftRadius.height() > 0)
42753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        addBezierCurveTo(FloatPoint(rect.x() + bottomLeftRadius.width() * gCircleControlPoint, rect.maxY()),
42853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            FloatPoint(rect.x(), rect.maxY() - bottomLeftRadius.height() * gCircleControlPoint),
42953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            FloatPoint(rect.x(), rect.maxY() - bottomLeftRadius.height()));
43053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    addLineTo(FloatPoint(rect.x(), rect.y() + topLeftRadius.height()));
43153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (topLeftRadius.width() > 0 || topLeftRadius.height() > 0)
43253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        addBezierCurveTo(FloatPoint(rect.x(), rect.y() + topLeftRadius.height() * gCircleControlPoint),
43353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            FloatPoint(rect.x() + topLeftRadius.width() * gCircleControlPoint, rect.y()),
43453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            FloatPoint(rect.x() + topLeftRadius.width(), rect.y()));
43553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
43653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    closeSubpath();
43753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
43853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
43953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void Path::translate(const FloatSize& size)
44053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
44153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    m_path.offset(WebCoreFloatToSkScalar(size.width()), WebCoreFloatToSkScalar(size.height()));
44253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
44353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
444e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdochbool Path::unionPath(const Path& other)
445e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch{
446e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    return Op(m_path, other.m_path, kUnion_PathOp, &m_path);
447e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch}
448e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
449e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)#if !ASSERT_DISABLED
450e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)bool ellipseIsRenderable(float startAngle, float endAngle)
451e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles){
452e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)    return (std::abs(endAngle - startAngle) < 2 * piFloat)
453e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)        || WebCoreFloatNearlyEqual(std::abs(endAngle - startAngle), 2 * piFloat);
454e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)}
455e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)#endif
456e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)
45753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
458