1 | /* |
2 | * Copyright 2006 The Android Open Source Project |
3 | * |
4 | * Use of this source code is governed by a BSD-style license that can be |
5 | * found in the LICENSE file. |
6 | */ |
7 | |
8 | |
9 | #include "include/core/SkPath.h" |
10 | #include "include/core/SkRegion.h" |
11 | #include "include/core/SkStrokeRec.h" |
12 | #include "include/effects/Sk2DPathEffect.h" |
13 | #include "src/core/SkReadBuffer.h" |
14 | #include "src/core/SkWriteBuffer.h" |
15 | |
16 | Sk2DPathEffect::Sk2DPathEffect(const SkMatrix& mat) : fMatrix(mat) { |
17 | // Calling invert will set the type mask on both matrices, making them thread safe. |
18 | fMatrixIsInvertible = fMatrix.invert(&fInverse); |
19 | } |
20 | |
21 | bool Sk2DPathEffect::onFilterPath(SkPath* dst, const SkPath& src, |
22 | SkStrokeRec*, const SkRect*) const { |
23 | if (!fMatrixIsInvertible) { |
24 | return false; |
25 | } |
26 | |
27 | SkPath tmp; |
28 | SkIRect ir; |
29 | |
30 | src.transform(fInverse, &tmp); |
31 | tmp.getBounds().round(&ir); |
32 | if (!ir.isEmpty()) { |
33 | this->begin(ir, dst); |
34 | |
35 | SkRegion rgn; |
36 | rgn.setPath(tmp, SkRegion(ir)); |
37 | SkRegion::Iterator iter(rgn); |
38 | for (; !iter.done(); iter.next()) { |
39 | const SkIRect& rect = iter.rect(); |
40 | for (int y = rect.fTop; y < rect.fBottom; ++y) { |
41 | this->nextSpan(rect.fLeft, y, rect.width(), dst); |
42 | } |
43 | } |
44 | |
45 | this->end(dst); |
46 | } |
47 | return true; |
48 | } |
49 | |
50 | void Sk2DPathEffect::nextSpan(int x, int y, int count, SkPath* path) const { |
51 | if (!fMatrixIsInvertible) { |
52 | return; |
53 | } |
54 | |
55 | const SkMatrix& mat = this->getMatrix(); |
56 | SkPoint src, dst; |
57 | |
58 | src.set(SkIntToScalar(x) + SK_ScalarHalf, SkIntToScalar(y) + SK_ScalarHalf); |
59 | do { |
60 | mat.mapPoints(&dst, &src, 1); |
61 | this->next(dst, x++, y, path); |
62 | src.fX += SK_Scalar1; |
63 | } while (--count > 0); |
64 | } |
65 | |
66 | void Sk2DPathEffect::begin(const SkIRect& uvBounds, SkPath* dst) const {} |
67 | void Sk2DPathEffect::next(const SkPoint& loc, int u, int v, SkPath* dst) const {} |
68 | void Sk2DPathEffect::end(SkPath* dst) const {} |
69 | |
70 | /////////////////////////////////////////////////////////////////////////////// |
71 | |
72 | void Sk2DPathEffect::flatten(SkWriteBuffer& buffer) const { |
73 | this->INHERITED::flatten(buffer); |
74 | buffer.writeMatrix(fMatrix); |
75 | } |
76 | |
77 | /////////////////////////////////////////////////////////////////////////////// |
78 | |
79 | bool SkLine2DPathEffect::onFilterPath(SkPath* dst, const SkPath& src, |
80 | SkStrokeRec* rec, const SkRect* cullRect) const { |
81 | if (this->INHERITED::onFilterPath(dst, src, rec, cullRect)) { |
82 | rec->setStrokeStyle(fWidth); |
83 | return true; |
84 | } |
85 | return false; |
86 | } |
87 | |
88 | void SkLine2DPathEffect::nextSpan(int u, int v, int ucount, SkPath* dst) const { |
89 | if (ucount > 1) { |
90 | SkPoint src[2], dstP[2]; |
91 | |
92 | src[0].set(SkIntToScalar(u) + SK_ScalarHalf, SkIntToScalar(v) + SK_ScalarHalf); |
93 | src[1].set(SkIntToScalar(u+ucount) + SK_ScalarHalf, SkIntToScalar(v) + SK_ScalarHalf); |
94 | this->getMatrix().mapPoints(dstP, src, 2); |
95 | |
96 | dst->moveTo(dstP[0]); |
97 | dst->lineTo(dstP[1]); |
98 | } |
99 | } |
100 | |
101 | sk_sp<SkFlattenable> SkLine2DPathEffect::CreateProc(SkReadBuffer& buffer) { |
102 | SkMatrix matrix; |
103 | buffer.readMatrix(&matrix); |
104 | SkScalar width = buffer.readScalar(); |
105 | return SkLine2DPathEffect::Make(width, matrix); |
106 | } |
107 | |
108 | void SkLine2DPathEffect::flatten(SkWriteBuffer &buffer) const { |
109 | buffer.writeMatrix(this->getMatrix()); |
110 | buffer.writeScalar(fWidth); |
111 | } |
112 | |
113 | /////////////////////////////////////////////////////////////////////////////// |
114 | |
115 | SkPath2DPathEffect::SkPath2DPathEffect(const SkMatrix& m, const SkPath& p) |
116 | : INHERITED(m), fPath(p) { |
117 | } |
118 | |
119 | sk_sp<SkFlattenable> SkPath2DPathEffect::CreateProc(SkReadBuffer& buffer) { |
120 | SkMatrix matrix; |
121 | buffer.readMatrix(&matrix); |
122 | SkPath path; |
123 | buffer.readPath(&path); |
124 | return SkPath2DPathEffect::Make(matrix, path); |
125 | } |
126 | |
127 | void SkPath2DPathEffect::flatten(SkWriteBuffer& buffer) const { |
128 | buffer.writeMatrix(this->getMatrix()); |
129 | buffer.writePath(fPath); |
130 | } |
131 | |
132 | void SkPath2DPathEffect::next(const SkPoint& loc, int u, int v, |
133 | SkPath* dst) const { |
134 | dst->addPath(fPath, loc.fX, loc.fY); |
135 | } |
136 | |