blob: f3cca1653f046a3d75713fed16fcfcfa9401f2a5 [file] [log] [blame]
sugoi@google.com5f74cf82012-12-17 21:16:45 +00001/*
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
14SkStrokeRec::SkStrokeRec(InitStyle s) {
reed05d90442015-02-12 13:35:52 -080015 fResScale = 1;
sugoi@google.com5f74cf82012-12-17 21:16:45 +000016 fWidth = (kFill_InitStyle == s) ? kStrokeRec_FillStyleWidth : 0;
17 fMiterLimit = SkPaintDefaults_MiterLimit;
18 fCap = SkPaint::kDefault_Cap;
19 fJoin = SkPaint::kDefault_Join;
20 fStrokeAndFill = false;
21}
22
reed05d90442015-02-12 13:35:52 -080023SkStrokeRec::SkStrokeRec(const SkPaint& paint, SkScalar resScale) {
24 this->init(paint, paint.getStyle(), resScale);
egdaniele61c4112014-06-12 10:24:21 -070025}
26
reed05d90442015-02-12 13:35:52 -080027SkStrokeRec::SkStrokeRec(const SkPaint& paint, SkPaint::Style styleOverride, SkScalar resScale) {
28 this->init(paint, styleOverride, resScale);
egdaniele61c4112014-06-12 10:24:21 -070029}
30
reed05d90442015-02-12 13:35:52 -080031void SkStrokeRec::init(const SkPaint& paint, SkPaint::Style style, SkScalar resScale) {
32 fResScale = resScale;
33
egdaniele61c4112014-06-12 10:24:21 -070034 switch (style) {
sugoi@google.com5f74cf82012-12-17 21:16:45 +000035 case SkPaint::kFill_Style:
36 fWidth = kStrokeRec_FillStyleWidth;
37 fStrokeAndFill = false;
38 break;
39 case SkPaint::kStroke_Style:
40 fWidth = paint.getStrokeWidth();
41 fStrokeAndFill = false;
42 break;
43 case SkPaint::kStrokeAndFill_Style:
44 if (0 == paint.getStrokeWidth()) {
45 // hairline+fill == fill
46 fWidth = kStrokeRec_FillStyleWidth;
47 fStrokeAndFill = false;
48 } else {
49 fWidth = paint.getStrokeWidth();
50 fStrokeAndFill = true;
51 }
52 break;
53 default:
mtklein@google.com330313a2013-08-22 15:37:26 +000054 SkDEBUGFAIL("unknown paint style");
sugoi@google.com5f74cf82012-12-17 21:16:45 +000055 // fall back on just fill
56 fWidth = kStrokeRec_FillStyleWidth;
57 fStrokeAndFill = false;
58 break;
59 }
60
61 // copy these from the paint, regardless of our "style"
62 fMiterLimit = paint.getStrokeMiter();
63 fCap = paint.getStrokeCap();
64 fJoin = paint.getStrokeJoin();
65}
66
67SkStrokeRec::Style SkStrokeRec::getStyle() const {
68 if (fWidth < 0) {
69 return kFill_Style;
70 } else if (0 == fWidth) {
71 return kHairline_Style;
72 } else {
73 return fStrokeAndFill ? kStrokeAndFill_Style : kStroke_Style;
74 }
75}
76
77void SkStrokeRec::setFillStyle() {
78 fWidth = kStrokeRec_FillStyleWidth;
79 fStrokeAndFill = false;
80}
81
82void SkStrokeRec::setHairlineStyle() {
83 fWidth = 0;
84 fStrokeAndFill = false;
85}
86
87void SkStrokeRec::setStrokeStyle(SkScalar width, bool strokeAndFill) {
88 if (strokeAndFill && (0 == width)) {
89 // hairline+fill == fill
90 this->setFillStyle();
91 } else {
92 fWidth = width;
93 fStrokeAndFill = strokeAndFill;
94 }
95}
96
97#include "SkStroke.h"
98
halcanary9d524f22016-03-29 09:03:52 -070099#ifdef SK_DEBUG
caryclark04e4d082015-02-20 06:33:57 -0800100 // enables tweaking these values at runtime from SampleApp
101 bool gDebugStrokerErrorSet = false;
102 SkScalar gDebugStrokerError;
103#endif
104
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000105bool SkStrokeRec::applyToPath(SkPath* dst, const SkPath& src) const {
106 if (fWidth <= 0) { // hairline or fill
107 return false;
108 }
109
110 SkStroke stroker;
jvanverth897c9932015-11-20 13:32:32 -0800111 stroker.setCap((SkPaint::Cap)fCap);
112 stroker.setJoin((SkPaint::Join)fJoin);
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000113 stroker.setMiterLimit(fMiterLimit);
114 stroker.setWidth(fWidth);
115 stroker.setDoFill(fStrokeAndFill);
caryclarka76b7a32015-05-22 06:26:52 -0700116#ifdef SK_DEBUG
caryclark04e4d082015-02-20 06:33:57 -0800117 stroker.setResScale(gDebugStrokerErrorSet ? gDebugStrokerError : fResScale);
118#else
reed05d90442015-02-12 13:35:52 -0800119 stroker.setResScale(fResScale);
caryclarkfeff7d22014-10-09 05:36:03 -0700120#endif
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000121 stroker.strokePath(src, dst);
122 return true;
123}
cdalton20b373c2014-12-01 08:38:55 -0800124
125void SkStrokeRec::applyToPaint(SkPaint* paint) const {
126 if (fWidth < 0) { // fill
127 paint->setStyle(SkPaint::kFill_Style);
128 return;
129 }
130
131 paint->setStyle(fStrokeAndFill ? SkPaint::kStrokeAndFill_Style : SkPaint::kStroke_Style);
132 paint->setStrokeWidth(fWidth);
133 paint->setStrokeMiter(fMiterLimit);
jvanverth897c9932015-11-20 13:32:32 -0800134 paint->setStrokeCap((SkPaint::Cap)fCap);
135 paint->setStrokeJoin((SkPaint::Join)fJoin);
cdalton20b373c2014-12-01 08:38:55 -0800136}
bsalomon56686482016-04-29 07:07:03 -0700137
138static inline SkScalar get_inflation_bounds(SkPaint::Join join,
139 SkScalar strokeWidth,
140 SkScalar miterLimit) {
141 if (strokeWidth < 0) { // fill
142 return 0;
143 } else if (0 == strokeWidth) {
144 return SK_Scalar1;
145 }
146 // since we're stroked, outset the rect by the radius (and join type)
147 SkScalar radius = SkScalarHalf(strokeWidth);
148 if (SkPaint::kMiter_Join == join) {
149 if (miterLimit > SK_Scalar1) {
150 radius = SkScalarMul(miterLimit, radius);
151 }
152 }
153 return radius;
154}
155
156SkScalar SkStrokeRec::getInflationRadius() const {
157 return get_inflation_bounds((SkPaint::Join)fJoin, fWidth, fMiterLimit);
158}
159
160SkScalar SkStrokeRec::GetInflationRadius(const SkPaint& paint, SkPaint::Style style) {
161 SkScalar width = SkPaint::kFill_Style == style ? -SK_Scalar1 : paint.getStrokeWidth();
162 return get_inflation_bounds(paint.getStrokeJoin(), width, paint.getStrokeMiter());
163
164}