1 : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : * ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is Mozilla Corporation code.
16 : *
17 : * The Initial Developer of the Original Code is Mozilla Foundation.
18 : * Portions created by the Initial Developer are Copyright (C) 2011
19 : * the Initial Developer. All Rights Reserved.
20 : *
21 : * Contributor(s):
22 : * Matt Woodrow <mwoodrow@mozilla.com>
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either the GNU General Public License Version 2 or later (the "GPL"), or
26 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : #include "PathSkia.h"
39 : #include <math.h>
40 : #include "DrawTargetSkia.h"
41 : #include "Logging.h"
42 : #include "HelpersSkia.h"
43 : #include "PathHelpers.h"
44 :
45 : namespace mozilla {
46 : namespace gfx {
47 :
48 0 : PathBuilderSkia::PathBuilderSkia(const Matrix& aTransform, const SkPath& aPath, FillRule aFillRule)
49 0 : : mPath(aPath)
50 : {
51 : SkMatrix matrix;
52 0 : GfxMatrixToSkiaMatrix(aTransform, matrix);
53 0 : mPath.transform(matrix);
54 0 : SetFillRule(aFillRule);
55 0 : }
56 :
57 0 : PathBuilderSkia::PathBuilderSkia(FillRule aFillRule)
58 : {
59 0 : SetFillRule(aFillRule);
60 0 : }
61 :
62 : void
63 0 : PathBuilderSkia::SetFillRule(FillRule aFillRule)
64 : {
65 0 : mFillRule = aFillRule;
66 0 : if (mFillRule == FILL_WINDING) {
67 0 : mPath.setFillType(SkPath::kWinding_FillType);
68 : } else {
69 0 : mPath.setFillType(SkPath::kEvenOdd_FillType);
70 : }
71 0 : }
72 :
73 : void
74 0 : PathBuilderSkia::MoveTo(const Point &aPoint)
75 : {
76 0 : mPath.moveTo(SkFloatToScalar(aPoint.x), SkFloatToScalar(aPoint.y));
77 0 : }
78 :
79 : void
80 0 : PathBuilderSkia::LineTo(const Point &aPoint)
81 : {
82 0 : if (!mPath.countPoints()) {
83 0 : MoveTo(aPoint);
84 : } else {
85 0 : mPath.lineTo(SkFloatToScalar(aPoint.x), SkFloatToScalar(aPoint.y));
86 : }
87 0 : }
88 :
89 : void
90 0 : PathBuilderSkia::BezierTo(const Point &aCP1,
91 : const Point &aCP2,
92 : const Point &aCP3)
93 : {
94 0 : if (!mPath.countPoints()) {
95 0 : MoveTo(aCP1);
96 : }
97 : mPath.cubicTo(SkFloatToScalar(aCP1.x), SkFloatToScalar(aCP1.y),
98 : SkFloatToScalar(aCP2.x), SkFloatToScalar(aCP2.y),
99 0 : SkFloatToScalar(aCP3.x), SkFloatToScalar(aCP3.y));
100 0 : }
101 :
102 : void
103 0 : PathBuilderSkia::QuadraticBezierTo(const Point &aCP1,
104 : const Point &aCP2)
105 : {
106 0 : if (!mPath.countPoints()) {
107 0 : MoveTo(aCP1);
108 : }
109 : mPath.quadTo(SkFloatToScalar(aCP1.x), SkFloatToScalar(aCP1.y),
110 0 : SkFloatToScalar(aCP2.x), SkFloatToScalar(aCP2.y));
111 0 : }
112 :
113 : void
114 0 : PathBuilderSkia::Close()
115 : {
116 0 : mPath.close();
117 0 : }
118 :
119 : void
120 0 : PathBuilderSkia::Arc(const Point &aOrigin, float aRadius, float aStartAngle,
121 : float aEndAngle, bool aAntiClockwise)
122 : {
123 0 : ArcToBezier(this, aOrigin, aRadius, aStartAngle, aEndAngle, aAntiClockwise);
124 0 : }
125 :
126 : Point
127 0 : PathBuilderSkia::CurrentPoint() const
128 : {
129 0 : int pointCount = mPath.countPoints();
130 0 : if (!pointCount) {
131 0 : return Point(0, 0);
132 : }
133 0 : SkPoint point = mPath.getPoint(pointCount - 1);
134 0 : return Point(SkScalarToFloat(point.fX), SkScalarToFloat(point.fY));
135 : }
136 :
137 : TemporaryRef<Path>
138 0 : PathBuilderSkia::Finish()
139 : {
140 0 : RefPtr<PathSkia> path = new PathSkia(mPath, mFillRule);
141 0 : return path;
142 : }
143 :
144 : TemporaryRef<PathBuilder>
145 0 : PathSkia::CopyToBuilder(FillRule aFillRule) const
146 : {
147 0 : return TransformedCopyToBuilder(Matrix(), aFillRule);
148 : }
149 :
150 : TemporaryRef<PathBuilder>
151 0 : PathSkia::TransformedCopyToBuilder(const Matrix &aTransform, FillRule aFillRule) const
152 : {
153 0 : RefPtr<PathBuilderSkia> builder = new PathBuilderSkia(aTransform, mPath, aFillRule);
154 0 : return builder;
155 : }
156 :
157 : bool
158 0 : PathSkia::ContainsPoint(const Point &aPoint, const Matrix &aTransform) const
159 : {
160 0 : Matrix inverse = aTransform;
161 0 : inverse.Invert();
162 0 : Point transformed = inverse * aPoint;
163 :
164 0 : Rect bounds = GetBounds(aTransform);
165 :
166 0 : if (aPoint.x < bounds.x || aPoint.y < bounds.y ||
167 0 : aPoint.x > bounds.XMost() || aPoint.y > bounds.YMost()) {
168 0 : return false;
169 : }
170 :
171 0 : SkRegion pointRect;
172 : pointRect.setRect(SkFloatToScalar(transformed.x - 1), SkFloatToScalar(transformed.y - 1),
173 0 : SkFloatToScalar(transformed.x + 1), SkFloatToScalar(transformed.y + 1));
174 :
175 0 : SkRegion pathRegion;
176 :
177 0 : return pathRegion.setPath(mPath, pointRect);
178 : }
179 :
180 0 : static Rect SkRectToRect(const SkRect& aBounds)
181 : {
182 : return Rect(SkScalarToFloat(aBounds.fLeft),
183 : SkScalarToFloat(aBounds.fTop),
184 : SkScalarToFloat(aBounds.fRight - aBounds.fLeft),
185 0 : SkScalarToFloat(aBounds.fBottom - aBounds.fTop));
186 : }
187 :
188 : Rect
189 0 : PathSkia::GetBounds(const Matrix &aTransform) const
190 : {
191 0 : Rect bounds = SkRectToRect(mPath.getBounds());
192 0 : return aTransform.TransformBounds(bounds);
193 : }
194 :
195 : Rect
196 0 : PathSkia::GetStrokedBounds(const StrokeOptions &aStrokeOptions,
197 : const Matrix &aTransform) const
198 : {
199 0 : SkPaint paint;
200 0 : StrokeOptionsToPaint(paint, aStrokeOptions);
201 :
202 0 : SkPath result;
203 0 : paint.getFillPath(mPath, &result);
204 :
205 0 : Rect bounds = SkRectToRect(result.getBounds());
206 0 : return aTransform.TransformBounds(bounds);
207 : }
208 :
209 : }
210 : }
|