Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(46)

Side by Side Diff: experimental/svg/model/SkSVGRenderContext.cpp

Issue 2234153002: [SVGDom] Add more presentation attributes. (Closed) Base URL: https://chromium.googlesource.com/skia.git@master
Patch Set: review Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « experimental/svg/model/SkSVGRenderContext.h ('k') | experimental/svg/model/SkSVGShape.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2016 Google Inc. 2 * Copyright 2016 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkCanvas.h" 8 #include "SkCanvas.h"
9 #include "SkSVGAttribute.h"
9 #include "SkSVGRenderContext.h" 10 #include "SkSVGRenderContext.h"
10 #include "SkSVGTypes.h" 11 #include "SkSVGTypes.h"
11 12
12 namespace { 13 namespace {
13 14
14 SkScalar length_size_for_type(const SkSize& viewport, SkSVGLengthContext::Length Type t) { 15 SkScalar length_size_for_type(const SkSize& viewport, SkSVGLengthContext::Length Type t) {
15 switch (t) { 16 switch (t) {
16 case SkSVGLengthContext::LengthType::kHorizontal: 17 case SkSVGLengthContext::LengthType::kHorizontal:
17 return viewport.width(); 18 return viewport.width();
18 case SkSVGLengthContext::LengthType::kVertical: 19 case SkSVGLengthContext::LengthType::kVertical:
19 return viewport.height(); 20 return viewport.height();
20 case SkSVGLengthContext::LengthType::kOther: 21 case SkSVGLengthContext::LengthType::kOther:
21 return SkScalarSqrt(viewport.width() * viewport.height()); 22 return SkScalarSqrt(viewport.width() * viewport.height());
22 } 23 }
23 24
24 SkASSERT(false); // Not reached. 25 SkASSERT(false); // Not reached.
25 return 0; 26 return 0;
26 } 27 }
27 28
28 } // anonymous ns 29 } // anonymous ns
29 30
30 SkScalar SkSVGLengthContext::resolve(const SkSVGLength& l, LengthType t) const { 31 SkScalar SkSVGLengthContext::resolve(const SkSVGLength& l, LengthType t) const {
31 switch (l.unit()) { 32 switch (l.unit()) {
32 case SkSVGLength::Unit::kNumber: 33 case SkSVGLength::Unit::kNumber:
34 // Fall through.
35 case SkSVGLength::Unit::kPX:
33 return l.value(); 36 return l.value();
34 break;
35 case SkSVGLength::Unit::kPercentage: 37 case SkSVGLength::Unit::kPercentage:
36 return l.value() * length_size_for_type(fViewport, t) / 100; 38 return l.value() * length_size_for_type(fViewport, t) / 100;
37 break;
38 default: 39 default:
39 SkDebugf("unsupported unit type: <%d>\n", l.unit()); 40 SkDebugf("unsupported unit type: <%d>\n", l.unit());
40 break; 41 return 0;
41 } 42 }
42
43 return 0;
44 } 43 }
45 44
46 SkRect SkSVGLengthContext::resolveRect(const SkSVGLength& x, const SkSVGLength& y, 45 SkRect SkSVGLengthContext::resolveRect(const SkSVGLength& x, const SkSVGLength& y,
47 const SkSVGLength& w, const SkSVGLength& h) const { 46 const SkSVGLength& w, const SkSVGLength& h) const {
48 return SkRect::MakeXYWH( 47 return SkRect::MakeXYWH(
49 this->resolve(x, SkSVGLengthContext::LengthType::kHorizontal), 48 this->resolve(x, SkSVGLengthContext::LengthType::kHorizontal),
50 this->resolve(y, SkSVGLengthContext::LengthType::kVertical), 49 this->resolve(y, SkSVGLengthContext::LengthType::kVertical),
51 this->resolve(w, SkSVGLengthContext::LengthType::kHorizontal), 50 this->resolve(w, SkSVGLengthContext::LengthType::kHorizontal),
52 this->resolve(h, SkSVGLengthContext::LengthType::kVertical)); 51 this->resolve(h, SkSVGLengthContext::LengthType::kVertical));
53 } 52 }
54 53
55 SkSVGPresentationContext::SkSVGPresentationContext() {} 54 namespace {
56 55
57 SkSVGPresentationContext::SkSVGPresentationContext(const SkSVGPresentationContex t& o) { 56 SkPaint::Cap toSkCap(const SkSVGLineCap& cap) {
58 this->initFrom(o); 57 switch (cap.type()) {
59 } 58 case SkSVGLineCap::Type::kButt:
60 59 return SkPaint::kButt_Cap;
61 SkSVGPresentationContext& SkSVGPresentationContext::operator=(const SkSVGPresent ationContext& o) { 60 case SkSVGLineCap::Type::kRound:
62 this->initFrom(o); 61 return SkPaint::kRound_Cap;
63 return *this; 62 case SkSVGLineCap::Type::kSquare:
64 } 63 return SkPaint::kSquare_Cap;
65 64 default:
66 void SkSVGPresentationContext::initFrom(const SkSVGPresentationContext& other) { 65 SkASSERT(false);
67 if (other.fFill.isValid()) { 66 return SkPaint::kButt_Cap;
68 fFill.set(*other.fFill.get());
69 } else {
70 fFill.reset();
71 }
72
73 if (other.fStroke.isValid()) {
74 fStroke.set(*other.fStroke.get());
75 } else {
76 fStroke.reset();
77 } 67 }
78 } 68 }
79 69
80 SkPaint& SkSVGPresentationContext::ensureFill() { 70 SkPaint::Join toSkJoin(const SkSVGLineJoin& join) {
81 if (!fFill.isValid()) { 71 switch (join.type()) {
82 fFill.init(); 72 case SkSVGLineJoin::Type::kMiter:
83 fFill.get()->setStyle(SkPaint::kFill_Style); 73 return SkPaint::kMiter_Join;
84 fFill.get()->setAntiAlias(true); 74 case SkSVGLineJoin::Type::kRound:
75 return SkPaint::kRound_Join;
76 case SkSVGLineJoin::Type::kBevel:
77 return SkPaint::kBevel_Join;
78 default:
79 SkASSERT(false);
80 return SkPaint::kMiter_Join;
85 } 81 }
86 return *fFill.get();
87 } 82 }
88 83
89 SkPaint& SkSVGPresentationContext::ensureStroke() { 84 void applySvgPaint(const SkSVGPaint& svgPaint, SkPaint* p) {
90 if (!fStroke.isValid()) { 85 switch (svgPaint.type()) {
91 fStroke.init(); 86 case SkSVGPaint::Type::kColor:
92 fStroke.get()->setStyle(SkPaint::kStroke_Style); 87 p->setColor(SkColorSetA(svgPaint.color(), p->getAlpha()));
93 fStroke.get()->setAntiAlias(true); 88 break;
89 case SkSVGPaint::Type::kCurrentColor:
90 SkDebugf("unimplemented 'currentColor' paint type");
91 // Fall through.
92 case SkSVGPaint::Type::kNone:
93 // Fall through.
94 case SkSVGPaint::Type::kInherit:
95 break;
94 } 96 }
95 return *fStroke.get();
96 } 97 }
97 98
98 void SkSVGPresentationContext::setFillColor(SkColor color) { 99 // Commit the selected attribute to the paint cache.
99 this->ensureFill().setColor(color); 100 template <SkSVGAttribute>
101 void commitToPaint(const SkSVGPresentationAttributes&,
102 const SkSVGLengthContext&,
103 SkSVGPresentationContext*);
104
105 template <>
106 void commitToPaint<SkSVGAttribute::kFill>(const SkSVGPresentationAttributes& att rs,
107 const SkSVGLengthContext&,
108 SkSVGPresentationContext* pctx) {
109 applySvgPaint(*attrs.fFill.get(), &pctx->fFillPaint);
100 } 110 }
101 111
102 void SkSVGPresentationContext::setStrokeColor(SkColor color) { 112 template <>
103 this->ensureStroke().setColor(color); 113 void commitToPaint<SkSVGAttribute::kStroke>(const SkSVGPresentationAttributes& a ttrs,
114 const SkSVGLengthContext&,
115 SkSVGPresentationContext* pctx) {
116 applySvgPaint(*attrs.fStroke.get(), &pctx->fStrokePaint);
117 }
118
119 template <>
120 void commitToPaint<SkSVGAttribute::kFillOpacity>(const SkSVGPresentationAttribut es& attrs,
121 const SkSVGLengthContext&,
122 SkSVGPresentationContext* pctx) {
123 pctx->fFillPaint.setAlpha(static_cast<uint8_t>(*attrs.fFillOpacity.get() * 2 55));
124 }
125
126 template <>
127 void commitToPaint<SkSVGAttribute::kStrokeLineCap>(const SkSVGPresentationAttrib utes& attrs,
128 const SkSVGLengthContext&,
129 SkSVGPresentationContext* pct x) {
130 const auto& cap = *attrs.fStrokeLineCap.get();
131 if (cap.type() != SkSVGLineCap::Type::kInherit) {
132 pctx->fStrokePaint.setStrokeCap(toSkCap(cap));
133 }
134 }
135
136 template <>
137 void commitToPaint<SkSVGAttribute::kStrokeLineJoin>(const SkSVGPresentationAttri butes& attrs,
138 const SkSVGLengthContext&,
139 SkSVGPresentationContext* pc tx) {
140 const auto& join = *attrs.fStrokeLineJoin.get();
141 if (join.type() != SkSVGLineJoin::Type::kInherit) {
142 pctx->fStrokePaint.setStrokeJoin(toSkJoin(join));
143 }
144 }
145
146 template <>
147 void commitToPaint<SkSVGAttribute::kStrokeOpacity>(const SkSVGPresentationAttrib utes& attrs,
148 const SkSVGLengthContext&,
149 SkSVGPresentationContext* pct x) {
150 pctx->fStrokePaint.setAlpha(static_cast<uint8_t>(*attrs.fStrokeOpacity.get() * 255));
151 }
152
153 template <>
154 void commitToPaint<SkSVGAttribute::kStrokeWidth>(const SkSVGPresentationAttribut es& attrs,
155 const SkSVGLengthContext& lctx,
156 SkSVGPresentationContext* pctx) {
157 auto strokeWidth = lctx.resolve(*attrs.fStrokeWidth.get(),
158 SkSVGLengthContext::LengthType::kOther);
159 pctx->fStrokePaint.setStrokeWidth(strokeWidth);
160 }
161
162 } // anonymous ns
163
164 SkSVGPresentationContext::SkSVGPresentationContext()
165 : fInherited(SkSVGPresentationAttributes::MakeInitial()) {
166
167 fFillPaint.setStyle(SkPaint::kFill_Style);
168 fStrokePaint.setStyle(SkPaint::kStroke_Style);
169
170 // TODO: drive AA off presentation attrs also (shape-rendering?)
171 fFillPaint.setAntiAlias(true);
172 fStrokePaint.setAntiAlias(true);
173
174 // Commit initial values to the paint cache.
175 SkSVGLengthContext dummy(SkSize::Make(0, 0));
176 commitToPaint<SkSVGAttribute::kFill>(fInherited, dummy, this);
177 commitToPaint<SkSVGAttribute::kFillOpacity>(fInherited, dummy, this);
178 commitToPaint<SkSVGAttribute::kStroke>(fInherited, dummy, this);
179 commitToPaint<SkSVGAttribute::kStrokeLineCap>(fInherited, dummy, this);
180 commitToPaint<SkSVGAttribute::kStrokeLineJoin>(fInherited, dummy, this);
181 commitToPaint<SkSVGAttribute::kStrokeOpacity>(fInherited, dummy, this);
182 commitToPaint<SkSVGAttribute::kStrokeWidth>(fInherited, dummy, this);
104 } 183 }
105 184
106 SkSVGRenderContext::SkSVGRenderContext(SkCanvas* canvas, 185 SkSVGRenderContext::SkSVGRenderContext(SkCanvas* canvas,
107 const SkSVGLengthContext& lctx, 186 const SkSVGLengthContext& lctx,
108 const SkSVGPresentationContext& pctx) 187 const SkSVGPresentationContext& pctx)
109 : fLengthContext(lctx) 188 : fLengthContext(lctx)
110 , fPresentationContext(pctx) 189 , fPresentationContext(pctx)
111 , fCanvas(canvas) 190 , fCanvas(canvas)
112 , fCanvasSaveCount(canvas->getSaveCount()) {} 191 , fCanvasSaveCount(canvas->getSaveCount()) {}
113 192
114 SkSVGRenderContext::SkSVGRenderContext(const SkSVGRenderContext& other) 193 SkSVGRenderContext::SkSVGRenderContext(const SkSVGRenderContext& other)
115 : SkSVGRenderContext(other.canvas(), 194 : SkSVGRenderContext(other.fCanvas,
116 other.lengthContext(), 195 *other.fLengthContext,
117 other.presentationContext()) {} 196 *other.fPresentationContext) {}
118 197
119 SkSVGRenderContext::~SkSVGRenderContext() { 198 SkSVGRenderContext::~SkSVGRenderContext() {
120 fCanvas->restoreToCount(fCanvasSaveCount); 199 fCanvas->restoreToCount(fCanvasSaveCount);
121 } 200 }
201
202 void SkSVGRenderContext::applyPresentationAttributes(const SkSVGPresentationAttr ibutes& attrs) {
203
204 #define ApplyLazyInheritedAttribute(ATTR) \
205 do { \
206 /* All attributes should be defined on the inherited context. */ \
207 SkASSERT(fPresentationContext->fInherited.f ## ATTR.isValid()); \
208 const auto* value = attrs.f ## ATTR.getMaybeNull(); \
209 if (value && *value != *fPresentationContext->fInherited.f ## ATTR.get() ) { \
210 /* Update the local attribute value */ \
211 fPresentationContext.writable()->fInherited.f ## ATTR.set(*value); \
212 /* Update the cached paints */ \
213 commitToPaint<SkSVGAttribute::k ## ATTR>(attrs, *fLengthContext, \
214 fPresentationContext.writab le()); \
215 } \
216 } while (false)
217
218 ApplyLazyInheritedAttribute(Fill);
219 ApplyLazyInheritedAttribute(FillOpacity);
220 ApplyLazyInheritedAttribute(Stroke);
221 ApplyLazyInheritedAttribute(StrokeLineCap);
222 ApplyLazyInheritedAttribute(StrokeLineJoin);
223 ApplyLazyInheritedAttribute(StrokeOpacity);
224 ApplyLazyInheritedAttribute(StrokeWidth);
225
226 #undef ApplyLazyInheritedAttribute
227 }
228
229 const SkPaint* SkSVGRenderContext::fillPaint() const {
230 const SkSVGPaint::Type paintType = fPresentationContext->fInherited.fFill.ge t()->type();
231 return paintType != SkSVGPaint::Type::kNone ? &fPresentationContext->fFillPa int : nullptr;
232 }
233
234 const SkPaint* SkSVGRenderContext::strokePaint() const {
235 const SkSVGPaint::Type paintType = fPresentationContext->fInherited.fStroke. get()->type();
236 return paintType != SkSVGPaint::Type::kNone ? &fPresentationContext->fStroke Paint : nullptr;
237 }
OLDNEW
« no previous file with comments | « experimental/svg/model/SkSVGRenderContext.h ('k') | experimental/svg/model/SkSVGShape.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698