blob: 9cf7d8302f1388b0490e906945c3a2ea24909769 [file] [log] [blame]
egdanield58a0ba2014-06-11 10:30:05 -07001/*
2 * Copyright 2014 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#ifndef GrStrokeInfo_DEFINED
9#define GrStrokeInfo_DEFINED
10
egdanield58a0ba2014-06-11 10:30:05 -070011#include "SkPathEffect.h"
bungemanf3c15b72015-08-19 11:56:48 -070012#include "SkStrokeRec.h"
13#include "SkTemplates.h"
egdanield58a0ba2014-06-11 10:30:05 -070014
kkinnunen50b58e62015-05-18 23:02:07 -070015class GrUniqueKey;
16
egdanield58a0ba2014-06-11 10:30:05 -070017/*
kkinnunen261694c2015-05-05 08:00:10 -070018 * GrStrokeInfo encapsulates all the pertinent infomation regarding the stroke. The SkStrokeRec
19 * which holds information on fill style, width, miter, cap, and join. It also holds information
20 * about the dash like intervals, count, and phase.
egdanield58a0ba2014-06-11 10:30:05 -070021 */
kkinnunend156d362015-05-18 22:23:54 -070022class GrStrokeInfo : public SkStrokeRec {
23public:
bsalomonc55271f2015-11-09 11:55:57 -080024 static const GrStrokeInfo& FillInfo() {
25 static const GrStrokeInfo gFill(kFill_InitStyle);
26 return gFill;
27 }
28
kkinnunend156d362015-05-18 22:23:54 -070029 GrStrokeInfo(SkStrokeRec::InitStyle style)
30 : INHERITED(style)
31 , fDashType(SkPathEffect::kNone_DashType) {
32 }
egdanield58a0ba2014-06-11 10:30:05 -070033
kkinnunend156d362015-05-18 22:23:54 -070034 GrStrokeInfo(const GrStrokeInfo& src, bool includeDash = true)
35 : INHERITED(src) {
kkinnunen261694c2015-05-05 08:00:10 -070036 if (includeDash && src.isDashed()) {
egdanield58a0ba2014-06-11 10:30:05 -070037 fDashType = src.fDashType;
kkinnunen261694c2015-05-05 08:00:10 -070038 fDashPhase = src.fDashPhase;
39 fIntervals.reset(src.getDashCount());
40 memcpy(fIntervals.get(), src.fIntervals.get(), fIntervals.count() * sizeof(SkScalar));
egdanield58a0ba2014-06-11 10:30:05 -070041 } else {
42 fDashType = SkPathEffect::kNone_DashType;
43 }
44 }
45
kkinnunend156d362015-05-18 22:23:54 -070046 GrStrokeInfo(const SkPaint& paint, SkPaint::Style styleOverride)
47 : INHERITED(paint, styleOverride)
48 , fDashType(SkPathEffect::kNone_DashType) {
egdaniele61c4112014-06-12 10:24:21 -070049 this->init(paint);
50 }
51
kkinnunend156d362015-05-18 22:23:54 -070052 explicit GrStrokeInfo(const SkPaint& paint)
53 : INHERITED(paint)
54 , fDashType(SkPathEffect::kNone_DashType) {
egdaniele61c4112014-06-12 10:24:21 -070055 this->init(paint);
egdanield58a0ba2014-06-11 10:30:05 -070056 }
57
kkinnunen18996512015-04-26 23:18:49 -070058 GrStrokeInfo& operator=(const GrStrokeInfo& other) {
kkinnunen261694c2015-05-05 08:00:10 -070059 if (other.isDashed()) {
60 fDashType = other.fDashType;
61 fDashPhase = other.fDashPhase;
62 fIntervals.reset(other.getDashCount());
63 memcpy(fIntervals.get(), other.fIntervals.get(), fIntervals.count() * sizeof(SkScalar));
64 } else {
65 this->removeDash();
66 }
kkinnunend156d362015-05-18 22:23:54 -070067 this->INHERITED::operator=(other);
kkinnunen18996512015-04-26 23:18:49 -070068 return *this;
69 }
70
kkinnunen50b58e62015-05-18 23:02:07 -070071 bool hasEqualEffect(const GrStrokeInfo& other) const {
72 if (this->isDashed() != other.isDashed()) {
73 return false;
74 }
75 if (this->isDashed()) {
76 if (fDashPhase != other.fDashPhase ||
77 fIntervals.count() != other.fIntervals.count() ||
78 memcmp(fIntervals.get(), other.fIntervals.get(),
79 fIntervals.count() * sizeof(SkScalar)) != 0) {
80 return false;
81 }
82 }
83 return this->INHERITED::hasEqualEffect(other);
84 }
85
egdanield58a0ba2014-06-11 10:30:05 -070086 /*
kkinnunen261694c2015-05-05 08:00:10 -070087 * This functions takes in a patheffect and updates the dashing information if the path effect
88 * is a Dash type. Returns true if the path effect is a dashed effect and we are stroking,
89 * otherwise it returns false.
egdanield58a0ba2014-06-11 10:30:05 -070090 */
91 bool setDashInfo(const SkPathEffect* pe) {
kkinnunend156d362015-05-18 22:23:54 -070092 if (pe && !this->isFillStyle()) {
kkinnunen261694c2015-05-05 08:00:10 -070093 SkPathEffect::DashInfo dashInfo;
94 fDashType = pe->asADash(&dashInfo);
egdanield58a0ba2014-06-11 10:30:05 -070095 if (SkPathEffect::kDash_DashType == fDashType) {
kkinnunen261694c2015-05-05 08:00:10 -070096 fIntervals.reset(dashInfo.fCount);
97 dashInfo.fIntervals = fIntervals.get();
98 pe->asADash(&dashInfo);
99 fDashPhase = dashInfo.fPhase;
egdanield58a0ba2014-06-11 10:30:05 -0700100 return true;
101 }
102 }
103 return false;
104 }
105
joshualittfa2008f2015-04-29 11:32:05 -0700106 /*
107 * Like the above, but sets with an explicit SkPathEffect::DashInfo
108 */
109 bool setDashInfo(const SkPathEffect::DashInfo& info) {
kkinnunend156d362015-05-18 22:23:54 -0700110 if (!this->isFillStyle()) {
kkinnunen261694c2015-05-05 08:00:10 -0700111 fDashType = SkPathEffect::kDash_DashType;
112 fDashPhase = info.fPhase;
joshualittfa2008f2015-04-29 11:32:05 -0700113 fIntervals.reset(info.fCount);
kkinnunen261694c2015-05-05 08:00:10 -0700114 for (int i = 0; i < fIntervals.count(); i++) {
joshualittfa2008f2015-04-29 11:32:05 -0700115 fIntervals[i] = info.fIntervals[i];
116 }
joshualittfa2008f2015-04-29 11:32:05 -0700117 return true;
118 }
119 return false;
120 }
121
egdanield58a0ba2014-06-11 10:30:05 -0700122 bool isDashed() const {
kkinnunend156d362015-05-18 22:23:54 -0700123 return (!this->isFillStyle() && SkPathEffect::kDash_DashType == fDashType);
egdanield58a0ba2014-06-11 10:30:05 -0700124 }
125
kkinnunen261694c2015-05-05 08:00:10 -0700126 int32_t getDashCount() const {
127 SkASSERT(this->isDashed());
128 return fIntervals.count();
129 }
130
131 SkScalar getDashPhase() const {
132 SkASSERT(this->isDashed());
133 return fDashPhase;
134 }
135
136 const SkScalar* getDashIntervals() const {
137 SkASSERT(this->isDashed());
138 return fIntervals.get();
egdanield58a0ba2014-06-11 10:30:05 -0700139 }
140
141 void removeDash() {
142 fDashType = SkPathEffect::kNone_DashType;
143 }
egdanield58a0ba2014-06-11 10:30:05 -0700144
kkinnunen18996512015-04-26 23:18:49 -0700145 /** Applies the dash to a path, if the stroke info has dashing.
kkinnunen261694c2015-05-05 08:00:10 -0700146 * @return true if the dashing was applied (dst and dstStrokeInfo will be modified).
kkinnunen18996512015-04-26 23:18:49 -0700147 * false if the stroke info did not have dashing. The dst and dstStrokeInfo
148 * will be unmodified. The stroking in the SkStrokeRec might still
149 * be applicable.
150 */
kkinnunend156d362015-05-18 22:23:54 -0700151 bool applyDashToPath(SkPath* dst, GrStrokeInfo* dstStrokeInfo, const SkPath& src) const;
kkinnunen18996512015-04-26 23:18:49 -0700152
kkinnunen50b58e62015-05-18 23:02:07 -0700153 /**
154 * Computes the length of the data that will be written by asUniqueKeyFragment() function.
155 */
156 int computeUniqueKeyFragmentData32Cnt() const {
157 const int kSkScalarData32Cnt = sizeof(SkScalar) / sizeof(uint32_t);
158 // SkStrokeRec data: 32 bits for style+join+cap and 2 scalars for miter and width.
159 int strokeKeyData32Cnt = 1 + 2 * kSkScalarData32Cnt;
160
161 if (this->isDashed()) {
162 // One scalar for dash phase and one for each dash value.
163 strokeKeyData32Cnt += (1 + this->getDashCount()) * kSkScalarData32Cnt;
164 }
165 return strokeKeyData32Cnt;
166 }
167
168 /**
169 * Writes the object contents as uint32_t data, to be used with GrUniqueKey.
170 * Note: the data written does not encode the length, so care must be taken to ensure
171 * that the full unique key data is encoded properly. For example, GrStrokeInfo
172 * fragment can be placed last in the sequence, at fixed index.
173 */
174 void asUniqueKeyFragment(uint32_t*) const;
175
egdanield58a0ba2014-06-11 10:30:05 -0700176private:
kkinnunen50b58e62015-05-18 23:02:07 -0700177 // Prevent accidental usage, should use GrStrokeInfo::hasEqualEffect.
kkinnunend156d362015-05-18 22:23:54 -0700178 bool hasEqualEffect(const SkStrokeRec& other) const;
egdaniele61c4112014-06-12 10:24:21 -0700179
180 void init(const SkPaint& paint) {
181 const SkPathEffect* pe = paint.getPathEffect();
182 this->setDashInfo(pe);
183 }
184
egdanield58a0ba2014-06-11 10:30:05 -0700185 SkPathEffect::DashType fDashType;
kkinnunen261694c2015-05-05 08:00:10 -0700186 SkScalar fDashPhase;
egdanield58a0ba2014-06-11 10:30:05 -0700187 SkAutoSTArray<2, SkScalar> fIntervals;
kkinnunend156d362015-05-18 22:23:54 -0700188 typedef SkStrokeRec INHERITED;
egdanield58a0ba2014-06-11 10:30:05 -0700189};
190
191#endif