Line data Source code
1 : /*
2 : * Copyright 2012 Google Inc.
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 : #include "SkStrokeRec.h"
9 : #include "SkPaintDefaults.h"
10 :
11 : // must be < 0, since ==0 means hairline, and >0 means normal stroke
12 : #define kStrokeRec_FillStyleWidth (-SK_Scalar1)
13 :
14 0 : SkStrokeRec::SkStrokeRec(InitStyle s) {
15 0 : fResScale = 1;
16 0 : fWidth = (kFill_InitStyle == s) ? kStrokeRec_FillStyleWidth : 0;
17 0 : fMiterLimit = SkPaintDefaults_MiterLimit;
18 0 : fCap = SkPaint::kDefault_Cap;
19 0 : fJoin = SkPaint::kDefault_Join;
20 0 : fStrokeAndFill = false;
21 0 : }
22 :
23 15 : SkStrokeRec::SkStrokeRec(const SkPaint& paint, SkScalar resScale) {
24 15 : this->init(paint, paint.getStyle(), resScale);
25 15 : }
26 :
27 0 : SkStrokeRec::SkStrokeRec(const SkPaint& paint, SkPaint::Style styleOverride, SkScalar resScale) {
28 0 : this->init(paint, styleOverride, resScale);
29 0 : }
30 :
31 15 : void SkStrokeRec::init(const SkPaint& paint, SkPaint::Style style, SkScalar resScale) {
32 15 : fResScale = resScale;
33 :
34 15 : switch (style) {
35 : case SkPaint::kFill_Style:
36 0 : fWidth = kStrokeRec_FillStyleWidth;
37 0 : fStrokeAndFill = false;
38 0 : break;
39 : case SkPaint::kStroke_Style:
40 15 : fWidth = paint.getStrokeWidth();
41 15 : fStrokeAndFill = false;
42 15 : break;
43 : case SkPaint::kStrokeAndFill_Style:
44 0 : if (0 == paint.getStrokeWidth()) {
45 : // hairline+fill == fill
46 0 : fWidth = kStrokeRec_FillStyleWidth;
47 0 : fStrokeAndFill = false;
48 : } else {
49 0 : fWidth = paint.getStrokeWidth();
50 0 : fStrokeAndFill = true;
51 : }
52 0 : break;
53 : default:
54 0 : SkDEBUGFAIL("unknown paint style");
55 : // fall back on just fill
56 0 : fWidth = kStrokeRec_FillStyleWidth;
57 0 : fStrokeAndFill = false;
58 0 : break;
59 : }
60 :
61 : // copy these from the paint, regardless of our "style"
62 15 : fMiterLimit = paint.getStrokeMiter();
63 15 : fCap = paint.getStrokeCap();
64 15 : fJoin = paint.getStrokeJoin();
65 15 : }
66 :
67 15 : SkStrokeRec::Style SkStrokeRec::getStyle() const {
68 15 : if (fWidth < 0) {
69 0 : return kFill_Style;
70 15 : } else if (0 == fWidth) {
71 0 : return kHairline_Style;
72 : } else {
73 15 : return fStrokeAndFill ? kStrokeAndFill_Style : kStroke_Style;
74 : }
75 : }
76 :
77 0 : void SkStrokeRec::setFillStyle() {
78 0 : fWidth = kStrokeRec_FillStyleWidth;
79 0 : fStrokeAndFill = false;
80 0 : }
81 :
82 0 : void SkStrokeRec::setHairlineStyle() {
83 0 : fWidth = 0;
84 0 : fStrokeAndFill = false;
85 0 : }
86 :
87 0 : void SkStrokeRec::setStrokeStyle(SkScalar width, bool strokeAndFill) {
88 0 : if (strokeAndFill && (0 == width)) {
89 : // hairline+fill == fill
90 0 : this->setFillStyle();
91 : } else {
92 0 : fWidth = width;
93 0 : fStrokeAndFill = strokeAndFill;
94 : }
95 0 : }
96 :
97 : #include "SkStroke.h"
98 :
99 : #ifdef SK_DEBUG
100 : // enables tweaking these values at runtime from SampleApp
101 : bool gDebugStrokerErrorSet = false;
102 : SkScalar gDebugStrokerError;
103 : #endif
104 :
105 15 : bool SkStrokeRec::applyToPath(SkPath* dst, const SkPath& src) const {
106 15 : if (fWidth <= 0) { // hairline or fill
107 0 : return false;
108 : }
109 :
110 15 : SkStroke stroker;
111 15 : stroker.setCap((SkPaint::Cap)fCap);
112 15 : stroker.setJoin((SkPaint::Join)fJoin);
113 15 : stroker.setMiterLimit(fMiterLimit);
114 15 : stroker.setWidth(fWidth);
115 15 : stroker.setDoFill(fStrokeAndFill);
116 : #ifdef SK_DEBUG
117 15 : stroker.setResScale(gDebugStrokerErrorSet ? gDebugStrokerError : fResScale);
118 : #else
119 : stroker.setResScale(fResScale);
120 : #endif
121 15 : stroker.strokePath(src, dst);
122 15 : return true;
123 : }
124 :
125 0 : void SkStrokeRec::applyToPaint(SkPaint* paint) const {
126 0 : if (fWidth < 0) { // fill
127 0 : paint->setStyle(SkPaint::kFill_Style);
128 0 : return;
129 : }
130 :
131 0 : paint->setStyle(fStrokeAndFill ? SkPaint::kStrokeAndFill_Style : SkPaint::kStroke_Style);
132 0 : paint->setStrokeWidth(fWidth);
133 0 : paint->setStrokeMiter(fMiterLimit);
134 0 : paint->setStrokeCap((SkPaint::Cap)fCap);
135 0 : paint->setStrokeJoin((SkPaint::Join)fJoin);
136 : }
137 :
138 15 : static inline SkScalar get_inflation_bounds(SkPaint::Join join,
139 : SkScalar strokeWidth,
140 : SkScalar miterLimit) {
141 15 : if (strokeWidth < 0) { // fill
142 0 : return 0;
143 15 : } else if (0 == strokeWidth) {
144 0 : return SK_Scalar1;
145 : }
146 : // since we're stroked, outset the rect by the radius (and join type)
147 15 : SkScalar radius = SkScalarHalf(strokeWidth);
148 15 : if (SkPaint::kMiter_Join == join) {
149 15 : if (miterLimit > SK_Scalar1) {
150 15 : radius *= miterLimit;
151 : }
152 : }
153 15 : return radius;
154 : }
155 :
156 0 : SkScalar SkStrokeRec::getInflationRadius() const {
157 0 : return get_inflation_bounds((SkPaint::Join)fJoin, fWidth, fMiterLimit);
158 : }
159 :
160 15 : SkScalar SkStrokeRec::GetInflationRadius(const SkPaint& paint, SkPaint::Style style) {
161 15 : SkScalar width = SkPaint::kFill_Style == style ? -SK_Scalar1 : paint.getStrokeWidth();
162 15 : return get_inflation_bounds(paint.getStrokeJoin(), width, paint.getStrokeMiter());
163 :
164 : }
|