1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/2d/PathSkia.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,245 @@ 1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- 1.5 + * This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "PathSkia.h" 1.10 +#include <math.h> 1.11 +#include "DrawTargetSkia.h" 1.12 +#include "Logging.h" 1.13 +#include "HelpersSkia.h" 1.14 +#include "PathHelpers.h" 1.15 + 1.16 +namespace mozilla { 1.17 +namespace gfx { 1.18 + 1.19 +PathBuilderSkia::PathBuilderSkia(const Matrix& aTransform, const SkPath& aPath, FillRule aFillRule) 1.20 + : mPath(aPath) 1.21 +{ 1.22 + SkMatrix matrix; 1.23 + GfxMatrixToSkiaMatrix(aTransform, matrix); 1.24 + mPath.transform(matrix); 1.25 + SetFillRule(aFillRule); 1.26 +} 1.27 + 1.28 +PathBuilderSkia::PathBuilderSkia(FillRule aFillRule) 1.29 +{ 1.30 + SetFillRule(aFillRule); 1.31 +} 1.32 + 1.33 +void 1.34 +PathBuilderSkia::SetFillRule(FillRule aFillRule) 1.35 +{ 1.36 + mFillRule = aFillRule; 1.37 + if (mFillRule == FillRule::FILL_WINDING) { 1.38 + mPath.setFillType(SkPath::kWinding_FillType); 1.39 + } else { 1.40 + mPath.setFillType(SkPath::kEvenOdd_FillType); 1.41 + } 1.42 +} 1.43 + 1.44 +void 1.45 +PathBuilderSkia::MoveTo(const Point &aPoint) 1.46 +{ 1.47 + mPath.moveTo(SkFloatToScalar(aPoint.x), SkFloatToScalar(aPoint.y)); 1.48 +} 1.49 + 1.50 +void 1.51 +PathBuilderSkia::LineTo(const Point &aPoint) 1.52 +{ 1.53 + if (!mPath.countPoints()) { 1.54 + MoveTo(aPoint); 1.55 + } else { 1.56 + mPath.lineTo(SkFloatToScalar(aPoint.x), SkFloatToScalar(aPoint.y)); 1.57 + } 1.58 +} 1.59 + 1.60 +void 1.61 +PathBuilderSkia::BezierTo(const Point &aCP1, 1.62 + const Point &aCP2, 1.63 + const Point &aCP3) 1.64 +{ 1.65 + if (!mPath.countPoints()) { 1.66 + MoveTo(aCP1); 1.67 + } 1.68 + mPath.cubicTo(SkFloatToScalar(aCP1.x), SkFloatToScalar(aCP1.y), 1.69 + SkFloatToScalar(aCP2.x), SkFloatToScalar(aCP2.y), 1.70 + SkFloatToScalar(aCP3.x), SkFloatToScalar(aCP3.y)); 1.71 +} 1.72 + 1.73 +void 1.74 +PathBuilderSkia::QuadraticBezierTo(const Point &aCP1, 1.75 + const Point &aCP2) 1.76 +{ 1.77 + if (!mPath.countPoints()) { 1.78 + MoveTo(aCP1); 1.79 + } 1.80 + mPath.quadTo(SkFloatToScalar(aCP1.x), SkFloatToScalar(aCP1.y), 1.81 + SkFloatToScalar(aCP2.x), SkFloatToScalar(aCP2.y)); 1.82 +} 1.83 + 1.84 +void 1.85 +PathBuilderSkia::Close() 1.86 +{ 1.87 + mPath.close(); 1.88 +} 1.89 + 1.90 +void 1.91 +PathBuilderSkia::Arc(const Point &aOrigin, float aRadius, float aStartAngle, 1.92 + float aEndAngle, bool aAntiClockwise) 1.93 +{ 1.94 + ArcToBezier(this, aOrigin, Size(aRadius, aRadius), aStartAngle, aEndAngle, aAntiClockwise); 1.95 +} 1.96 + 1.97 +Point 1.98 +PathBuilderSkia::CurrentPoint() const 1.99 +{ 1.100 + int pointCount = mPath.countPoints(); 1.101 + if (!pointCount) { 1.102 + return Point(0, 0); 1.103 + } 1.104 + SkPoint point = mPath.getPoint(pointCount - 1); 1.105 + return Point(SkScalarToFloat(point.fX), SkScalarToFloat(point.fY)); 1.106 +} 1.107 + 1.108 +TemporaryRef<Path> 1.109 +PathBuilderSkia::Finish() 1.110 +{ 1.111 + RefPtr<PathSkia> path = new PathSkia(mPath, mFillRule); 1.112 + return path; 1.113 +} 1.114 + 1.115 +void 1.116 +PathBuilderSkia::AppendPath(const SkPath &aPath) 1.117 +{ 1.118 + mPath.addPath(aPath); 1.119 +} 1.120 + 1.121 +TemporaryRef<PathBuilder> 1.122 +PathSkia::CopyToBuilder(FillRule aFillRule) const 1.123 +{ 1.124 + return TransformedCopyToBuilder(Matrix(), aFillRule); 1.125 +} 1.126 + 1.127 +TemporaryRef<PathBuilder> 1.128 +PathSkia::TransformedCopyToBuilder(const Matrix &aTransform, FillRule aFillRule) const 1.129 +{ 1.130 + RefPtr<PathBuilderSkia> builder = new PathBuilderSkia(aTransform, mPath, aFillRule); 1.131 + return builder; 1.132 +} 1.133 + 1.134 +bool 1.135 +PathSkia::ContainsPoint(const Point &aPoint, const Matrix &aTransform) const 1.136 +{ 1.137 + Matrix inverse = aTransform; 1.138 + inverse.Invert(); 1.139 + Point transformed = inverse * aPoint; 1.140 + 1.141 + Rect bounds = GetBounds(aTransform); 1.142 + 1.143 + if (aPoint.x < bounds.x || aPoint.y < bounds.y || 1.144 + aPoint.x > bounds.XMost() || aPoint.y > bounds.YMost()) { 1.145 + return false; 1.146 + } 1.147 + 1.148 + SkRegion pointRect; 1.149 + pointRect.setRect(int32_t(SkFloatToScalar(transformed.x - 1)), 1.150 + int32_t(SkFloatToScalar(transformed.y - 1)), 1.151 + int32_t(SkFloatToScalar(transformed.x + 1)), 1.152 + int32_t(SkFloatToScalar(transformed.y + 1))); 1.153 + 1.154 + SkRegion pathRegion; 1.155 + 1.156 + return pathRegion.setPath(mPath, pointRect); 1.157 +} 1.158 + 1.159 +bool 1.160 +PathSkia::StrokeContainsPoint(const StrokeOptions &aStrokeOptions, 1.161 + const Point &aPoint, 1.162 + const Matrix &aTransform) const 1.163 +{ 1.164 + Matrix inverse = aTransform; 1.165 + inverse.Invert(); 1.166 + Point transformed = inverse * aPoint; 1.167 + 1.168 + SkPaint paint; 1.169 + StrokeOptionsToPaint(paint, aStrokeOptions); 1.170 + 1.171 + SkPath strokePath; 1.172 + paint.getFillPath(mPath, &strokePath); 1.173 + 1.174 + Rect bounds = aTransform.TransformBounds(SkRectToRect(strokePath.getBounds())); 1.175 + 1.176 + if (aPoint.x < bounds.x || aPoint.y < bounds.y || 1.177 + aPoint.x > bounds.XMost() || aPoint.y > bounds.YMost()) { 1.178 + return false; 1.179 + } 1.180 + 1.181 + SkRegion pointRect; 1.182 + pointRect.setRect(int32_t(SkFloatToScalar(transformed.x - 1)), 1.183 + int32_t(SkFloatToScalar(transformed.y - 1)), 1.184 + int32_t(SkFloatToScalar(transformed.x + 1)), 1.185 + int32_t(SkFloatToScalar(transformed.y + 1))); 1.186 + 1.187 + SkRegion pathRegion; 1.188 + 1.189 + return pathRegion.setPath(strokePath, pointRect); 1.190 +} 1.191 + 1.192 +Rect 1.193 +PathSkia::GetBounds(const Matrix &aTransform) const 1.194 +{ 1.195 + Rect bounds = SkRectToRect(mPath.getBounds()); 1.196 + return aTransform.TransformBounds(bounds); 1.197 +} 1.198 + 1.199 +Rect 1.200 +PathSkia::GetStrokedBounds(const StrokeOptions &aStrokeOptions, 1.201 + const Matrix &aTransform) const 1.202 +{ 1.203 + SkPaint paint; 1.204 + StrokeOptionsToPaint(paint, aStrokeOptions); 1.205 + 1.206 + SkPath result; 1.207 + paint.getFillPath(mPath, &result); 1.208 + 1.209 + Rect bounds = SkRectToRect(result.getBounds()); 1.210 + return aTransform.TransformBounds(bounds); 1.211 +} 1.212 + 1.213 +void 1.214 +PathSkia::StreamToSink(PathSink *aSink) const 1.215 +{ 1.216 + SkPath::RawIter iter(mPath); 1.217 + 1.218 + SkPoint points[4]; 1.219 + SkPath::Verb currentVerb; 1.220 + while ((currentVerb = iter.next(points)) != SkPath::kDone_Verb) { 1.221 + switch (currentVerb) { 1.222 + case SkPath::kMove_Verb: 1.223 + aSink->MoveTo(SkPointToPoint(points[0])); 1.224 + break; 1.225 + case SkPath::kLine_Verb: 1.226 + aSink->LineTo(SkPointToPoint(points[1])); 1.227 + break; 1.228 + case SkPath::kCubic_Verb: 1.229 + aSink->BezierTo(SkPointToPoint(points[1]), 1.230 + SkPointToPoint(points[2]), 1.231 + SkPointToPoint(points[3])); 1.232 + break; 1.233 + case SkPath::kQuad_Verb: 1.234 + aSink->QuadraticBezierTo(SkPointToPoint(points[1]), 1.235 + SkPointToPoint(points[2])); 1.236 + break; 1.237 + case SkPath::kClose_Verb: 1.238 + aSink->Close(); 1.239 + break; 1.240 + default: 1.241 + MOZ_ASSERT(false); 1.242 + // Unexpected verb found in path! 1.243 + } 1.244 + } 1.245 +} 1.246 + 1.247 +} 1.248 +}