blob: 9e84b2f2bc4e07cf03d70064de3de184b3585fe5 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
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
reed@android.com8a1c16f2008-12-17 15:59:43 +00009
10#include "SkPathEffect.h"
11#include "SkPath.h"
djsollen@google.comc73dd5c2012-08-07 15:54:32 +000012#include "SkFlattenableBuffers.h"
reed@google.comfd4be262012-05-25 01:04:12 +000013#include "SkPaintDefaults.h"
14
15// must be < 0, since ==0 means hairline, and >0 means normal stroke
16#define kStrokeRec_FillStyleWidth (-SK_Scalar1)
17
18SkStrokeRec::SkStrokeRec(InitStyle s) {
19 fWidth = (kFill_InitStyle == s) ? kStrokeRec_FillStyleWidth : 0;
20 fMiterLimit = SkPaintDefaults_MiterLimit;
21 fCap = SkPaint::kDefault_Cap;
22 fJoin = SkPaint::kDefault_Join;
23 fStrokeAndFill = false;
24}
25
26SkStrokeRec::SkStrokeRec(const SkStrokeRec& src) {
27 memcpy(this, &src, sizeof(src));
28}
29
30SkStrokeRec::SkStrokeRec(const SkPaint& paint) {
31 switch (paint.getStyle()) {
32 case SkPaint::kFill_Style:
33 fWidth = kStrokeRec_FillStyleWidth;
34 fStrokeAndFill = false;
35 break;
36 case SkPaint::kStroke_Style:
37 fWidth = paint.getStrokeWidth();
38 fStrokeAndFill = false;
39 break;
40 case SkPaint::kStrokeAndFill_Style:
reed@google.com8b06f1a2012-05-29 12:03:46 +000041 if (0 == paint.getStrokeWidth()) {
42 // hairline+fill == fill
43 fWidth = kStrokeRec_FillStyleWidth;
44 fStrokeAndFill = false;
45 } else {
46 fWidth = paint.getStrokeWidth();
47 fStrokeAndFill = true;
48 }
reed@google.comfd4be262012-05-25 01:04:12 +000049 break;
50 default:
51 SkASSERT(!"unknown paint style");
52 // fall back on just fill
53 fWidth = kStrokeRec_FillStyleWidth;
54 fStrokeAndFill = false;
55 break;
56 }
57
58 // copy these from the paint, regardless of our "style"
59 fMiterLimit = paint.getStrokeMiter();
60 fCap = paint.getStrokeCap();
61 fJoin = paint.getStrokeJoin();
62}
63
64SkStrokeRec::Style SkStrokeRec::getStyle() const {
65 if (fWidth < 0) {
66 return kFill_Style;
67 } else if (0 == fWidth) {
68 return kHairline_Style;
69 } else {
70 return fStrokeAndFill ? kStrokeAndFill_Style : kStroke_Style;
71 }
72}
73
74void SkStrokeRec::setFillStyle() {
75 fWidth = kStrokeRec_FillStyleWidth;
reed@google.com8b06f1a2012-05-29 12:03:46 +000076 fStrokeAndFill = false;
77}
78
79void SkStrokeRec::setHairlineStyle() {
80 fWidth = 0;
81 fStrokeAndFill = false;
82}
83
84void SkStrokeRec::setStrokeStyle(SkScalar width, bool strokeAndFill) {
85 if (strokeAndFill && (0 == width)) {
86 // hairline+fill == fill
87 this->setFillStyle();
88 } else {
89 fWidth = width;
90 fStrokeAndFill = strokeAndFill;
91 }
reed@google.comfd4be262012-05-25 01:04:12 +000092}
93
94#include "SkStroke.h"
95
96bool SkStrokeRec::applyToPath(SkPath* dst, const SkPath& src) const {
97 if (fWidth <= 0) { // hairline or fill
98 return false;
99 }
100
101 SkStroke stroker;
102 stroker.setCap(fCap);
103 stroker.setJoin(fJoin);
104 stroker.setMiterLimit(fMiterLimit);
105 stroker.setWidth(fWidth);
106 stroker.setDoFill(fStrokeAndFill);
107 stroker.strokePath(src, dst);
108 return true;
109}
110
111///////////////////////////////////////////////////////////////////////////////
reed@android.com8a1c16f2008-12-17 15:59:43 +0000112
robertphillips@google.com0456e0b2012-06-27 14:03:26 +0000113SK_DEFINE_INST_COUNT(SkPathEffect)
114
reed@google.come4f10a72012-05-15 20:47:50 +0000115void SkPathEffect::computeFastBounds(SkRect* dst, const SkRect& src) {
116 *dst = src;
117}
118
skia.committer@gmail.com687c57c2012-11-29 02:01:19 +0000119bool SkPathEffect::asPoints(PointData* results, const SkPath& src,
robertphillips@google.com629ab542012-11-28 17:18:11 +0000120 const SkStrokeRec&, const SkMatrix&) const {
121 return false;
122}
123
reed@google.comfeb8cc82011-04-19 20:11:25 +0000124///////////////////////////////////////////////////////////////////////////////
reed@android.com8a1c16f2008-12-17 15:59:43 +0000125
126SkPairPathEffect::SkPairPathEffect(SkPathEffect* pe0, SkPathEffect* pe1)
reed@google.comfeb8cc82011-04-19 20:11:25 +0000127 : fPE0(pe0), fPE1(pe1) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000128 SkASSERT(pe0);
129 SkASSERT(pe1);
130 fPE0->ref();
131 fPE1->ref();
132}
133
reed@google.comfeb8cc82011-04-19 20:11:25 +0000134SkPairPathEffect::~SkPairPathEffect() {
reed@google.com6bac9472011-06-21 19:24:00 +0000135 SkSafeUnref(fPE0);
136 SkSafeUnref(fPE1);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000137}
138
139/*
140 Format: [oe0-factory][pe1-factory][pe0-size][pe0-data][pe1-data]
141*/
djsollen@google.com54924242012-03-29 15:18:04 +0000142void SkPairPathEffect::flatten(SkFlattenableWriteBuffer& buffer) const {
143 this->INHERITED::flatten(buffer);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000144 buffer.writeFlattenable(fPE0);
145 buffer.writeFlattenable(fPE1);
146}
147
reed@google.comfeb8cc82011-04-19 20:11:25 +0000148SkPairPathEffect::SkPairPathEffect(SkFlattenableReadBuffer& buffer) {
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000149 fPE0 = buffer.readFlattenableT<SkPathEffect>();
150 fPE1 = buffer.readFlattenableT<SkPathEffect>();
reed@google.com6bac9472011-06-21 19:24:00 +0000151 // either of these may fail, so we have to check for nulls later on
reed@android.com8a1c16f2008-12-17 15:59:43 +0000152}
153
reed@google.comfeb8cc82011-04-19 20:11:25 +0000154///////////////////////////////////////////////////////////////////////////////
reed@android.com8a1c16f2008-12-17 15:59:43 +0000155
reed@google.comfeb8cc82011-04-19 20:11:25 +0000156bool SkComposePathEffect::filterPath(SkPath* dst, const SkPath& src,
reed@google.comfd4be262012-05-25 01:04:12 +0000157 SkStrokeRec* rec) {
reed@google.com6bac9472011-06-21 19:24:00 +0000158 // we may have failed to unflatten these, so we have to check
159 if (!fPE0 || !fPE1) {
160 return false;
161 }
162
reed@android.com8a1c16f2008-12-17 15:59:43 +0000163 SkPath tmp;
164 const SkPath* ptr = &src;
165
reed@google.comfd4be262012-05-25 01:04:12 +0000166 if (fPE1->filterPath(&tmp, src, rec)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000167 ptr = &tmp;
reed@google.comfeb8cc82011-04-19 20:11:25 +0000168 }
reed@google.comfd4be262012-05-25 01:04:12 +0000169 return fPE0->filterPath(dst, *ptr, rec);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000170}
171
reed@google.comfeb8cc82011-04-19 20:11:25 +0000172///////////////////////////////////////////////////////////////////////////////
reed@android.com8a1c16f2008-12-17 15:59:43 +0000173
reed@google.comfeb8cc82011-04-19 20:11:25 +0000174bool SkSumPathEffect::filterPath(SkPath* dst, const SkPath& src,
reed@google.comfd4be262012-05-25 01:04:12 +0000175 SkStrokeRec* rec) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000176 // use bit-or so that we always call both, even if the first one succeeds
reed@google.comfd4be262012-05-25 01:04:12 +0000177 return fPE0->filterPath(dst, src, rec) | fPE1->filterPath(dst, src, rec);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000178}