1
2 /*
3 * Copyright 2006 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10 #include "SkPathEffect.h"
11 #include "SkPath.h"
12 #include "SkBuffer.h"
13
14 ///////////////////////////////////////////////////////////////////////////////
15
SkPairPathEffect(SkPathEffect * pe0,SkPathEffect * pe1)16 SkPairPathEffect::SkPairPathEffect(SkPathEffect* pe0, SkPathEffect* pe1)
17 : fPE0(pe0), fPE1(pe1) {
18 SkASSERT(pe0);
19 SkASSERT(pe1);
20 fPE0->ref();
21 fPE1->ref();
22 }
23
~SkPairPathEffect()24 SkPairPathEffect::~SkPairPathEffect() {
25 SkSafeUnref(fPE0);
26 SkSafeUnref(fPE1);
27 }
28
29 /*
30 Format: [oe0-factory][pe1-factory][pe0-size][pe0-data][pe1-data]
31 */
flatten(SkFlattenableWriteBuffer & buffer)32 void SkPairPathEffect::flatten(SkFlattenableWriteBuffer& buffer) {
33 buffer.writeFlattenable(fPE0);
34 buffer.writeFlattenable(fPE1);
35 }
36
SkPairPathEffect(SkFlattenableReadBuffer & buffer)37 SkPairPathEffect::SkPairPathEffect(SkFlattenableReadBuffer& buffer) {
38 fPE0 = (SkPathEffect*)buffer.readFlattenable();
39 fPE1 = (SkPathEffect*)buffer.readFlattenable();
40 // either of these may fail, so we have to check for nulls later on
41 }
42
43 ///////////////////////////////////////////////////////////////////////////////
44
filterPath(SkPath * dst,const SkPath & src,SkScalar * width)45 bool SkComposePathEffect::filterPath(SkPath* dst, const SkPath& src,
46 SkScalar* width) {
47 // we may have failed to unflatten these, so we have to check
48 if (!fPE0 || !fPE1) {
49 return false;
50 }
51
52 SkPath tmp;
53 const SkPath* ptr = &src;
54
55 if (fPE1->filterPath(&tmp, src, width)) {
56 ptr = &tmp;
57 }
58 return fPE0->filterPath(dst, *ptr, width);
59 }
60
61 ///////////////////////////////////////////////////////////////////////////////
62
filterPath(SkPath * dst,const SkPath & src,SkScalar * width)63 bool SkSumPathEffect::filterPath(SkPath* dst, const SkPath& src,
64 SkScalar* width) {
65 // use bit-or so that we always call both, even if the first one succeeds
66 return fPE0->filterPath(dst, src, width) | fPE1->filterPath(dst, src, width);
67 }
68
69 ///////////////////////////////////////////////////////////////////////////////
70
71 #include "SkStroke.h"
72
SkStrokePathEffect(const SkPaint & paint)73 SkStrokePathEffect::SkStrokePathEffect(const SkPaint& paint)
74 : fWidth(paint.getStrokeWidth()), fMiter(paint.getStrokeMiter()),
75 fStyle(SkToU8(paint.getStyle())), fJoin(SkToU8(paint.getStrokeJoin())),
76 fCap(SkToU8(paint.getStrokeCap())) {
77 }
78
SkStrokePathEffect(SkScalar width,SkPaint::Style style,SkPaint::Join join,SkPaint::Cap cap,SkScalar miter)79 SkStrokePathEffect::SkStrokePathEffect(SkScalar width, SkPaint::Style style,
80 SkPaint::Join join, SkPaint::Cap cap, SkScalar miter)
81 : fWidth(width), fMiter(miter), fStyle(SkToU8(style)),
82 fJoin(SkToU8(join)), fCap(SkToU8(cap)) {
83 if (miter < 0) { // signal they want the default
84 fMiter = SkIntToScalar(4);
85 }
86 }
87
filterPath(SkPath * dst,const SkPath & src,SkScalar * width)88 bool SkStrokePathEffect::filterPath(SkPath* dst, const SkPath& src,
89 SkScalar* width) {
90 if (fWidth < 0 || fStyle == SkPaint::kFill_Style) {
91 return false;
92 }
93
94 if (fStyle == SkPaint::kStroke_Style && fWidth == 0) { // hairline
95 *width = 0;
96 return true;
97 }
98
99 SkStroke stroke;
100
101 stroke.setWidth(fWidth);
102 stroke.setMiterLimit(fMiter);
103 stroke.setJoin((SkPaint::Join)fJoin);
104 stroke.setCap((SkPaint::Cap)fCap);
105 stroke.setDoFill(fStyle == SkPaint::kStrokeAndFill_Style);
106
107 stroke.strokePath(src, dst);
108 return true;
109 }
110
getFactory()111 SkFlattenable::Factory SkStrokePathEffect::getFactory() {
112 return CreateProc;
113 }
114
CreateProc(SkFlattenableReadBuffer & buffer)115 SkFlattenable* SkStrokePathEffect::CreateProc(SkFlattenableReadBuffer& buffer) {
116 return SkNEW_ARGS(SkStrokePathEffect, (buffer));
117 }
118
flatten(SkFlattenableWriteBuffer & buffer)119 void SkStrokePathEffect::flatten(SkFlattenableWriteBuffer& buffer) {
120 buffer.writeScalar(fWidth);
121 buffer.writeScalar(fMiter);
122 buffer.write8(fStyle);
123 buffer.write8(fJoin);
124 buffer.write8(fCap);
125 }
126
SkStrokePathEffect(SkFlattenableReadBuffer & buffer)127 SkStrokePathEffect::SkStrokePathEffect(SkFlattenableReadBuffer& buffer) {
128 fWidth = buffer.readScalar();
129 fMiter = buffer.readScalar();
130 fStyle = buffer.readU8();
131 fJoin = buffer.readU8();
132 fCap = buffer.readU8();
133 }
134
135 ///////////////////////////////////////////////////////////////////////////////
136
137 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkPathEffect)
138 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkComposePathEffect)
139 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkStrokePathEffect)
140 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSumPathEffect)
141 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
142
143