1 /*
2 * Copyright 2006 The Android Open Source Project
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 "SkDrawExtraPathEffect.h"
9 #include "SkDrawPath.h"
10 #include "Sk1DPathEffect.h"
11 #include "Sk2DPathEffect.h"
12 #include "SkMemberInfo.h"
13 #include "SkPaintPart.h"
14 #include "SkPathEffect.h"
15 #include "SkCornerPathEffect.h"
16
17 #include "SkDashPathEffect.h"
18
19 class SkDrawShapePathEffect : public SkDrawPathEffect {
20 DECLARE_PRIVATE_MEMBER_INFO(DrawShapePathEffect);
21 SkDrawShapePathEffect();
22 virtual ~SkDrawShapePathEffect();
23 bool addChild(SkAnimateMaker& , SkDisplayable* ) override;
24 SkPathEffect* getPathEffect() override;
25 protected:
26 SkADrawable* addPath;
27 SkADrawable* addMatrix;
28 SkDrawPath* path;
29 SkPathEffect* fPathEffect;
30 friend class SkShape1DPathEffect;
31 friend class SkShape2DPathEffect;
32 };
33
34 class SkDrawShape1DPathEffect : public SkDrawShapePathEffect {
35 DECLARE_EXTRAS_MEMBER_INFO(SkDrawShape1DPathEffect);
36 SkDrawShape1DPathEffect(SkDisplayTypes );
37 virtual ~SkDrawShape1DPathEffect();
38 void onEndElement(SkAnimateMaker& ) override;
39 private:
40 SkString phase;
41 SkString spacing;
42 friend class SkShape1DPathEffect;
43 typedef SkDrawShapePathEffect INHERITED;
44 };
45
46 class SkDrawShape2DPathEffect : public SkDrawShapePathEffect {
47 DECLARE_EXTRAS_MEMBER_INFO(SkDrawShape2DPathEffect);
48 SkDrawShape2DPathEffect(SkDisplayTypes );
49 virtual ~SkDrawShape2DPathEffect();
50 void onEndElement(SkAnimateMaker& ) override;
51 private:
52 SkDrawMatrix* matrix;
53 friend class SkShape2DPathEffect;
54 typedef SkDrawShapePathEffect INHERITED;
55 };
56
57 class SkDrawComposePathEffect : public SkDrawPathEffect {
58 DECLARE_EXTRAS_MEMBER_INFO(SkDrawComposePathEffect);
59 SkDrawComposePathEffect(SkDisplayTypes );
60 virtual ~SkDrawComposePathEffect();
61 bool addChild(SkAnimateMaker& , SkDisplayable* ) override;
62 SkPathEffect* getPathEffect() override;
63 bool isPaint() const override;
64 private:
65 SkDrawPathEffect* effect1;
66 SkDrawPathEffect* effect2;
67 };
68
69 class SkDrawCornerPathEffect : public SkDrawPathEffect {
70 DECLARE_EXTRAS_MEMBER_INFO(SkDrawCornerPathEffect);
71 SkDrawCornerPathEffect(SkDisplayTypes );
72 virtual ~SkDrawCornerPathEffect();
73 SkPathEffect* getPathEffect() override;
74 private:
75 SkScalar radius;
76 };
77
78 //////////// SkShape1DPathEffect
79
80 #include "SkAnimateMaker.h"
81 #include "SkAnimatorScript.h"
82 #include "SkDisplayApply.h"
83 #include "SkDrawMatrix.h"
84 #include "SkPaint.h"
85
86 class SkShape1DPathEffect : public Sk1DPathEffect {
87 public:
SkShape1DPathEffect(SkDrawShape1DPathEffect * draw,SkAnimateMaker * maker)88 SkShape1DPathEffect(SkDrawShape1DPathEffect* draw, SkAnimateMaker* maker) :
89 fDraw(draw), fMaker(maker) {
90 }
91
92 // For serialization. This will never be called.
getFactory() const93 Factory getFactory() const override { sk_throw(); return nullptr; }
94
95 protected:
begin(SkScalar contourLength) const96 SkScalar begin(SkScalar contourLength) const override {
97 SkScriptValue value;
98 SkAnimatorScript engine(*fMaker, nullptr, SkType_Float);
99 engine.propertyCallBack(GetContourLength, &contourLength);
100 value.fOperand.fScalar = 0;
101 engine.evaluate(fDraw->phase.c_str(), &value, SkType_Float);
102 return value.fOperand.fScalar;
103 }
104
next(SkPath * dst,SkScalar distance,SkPathMeasure &) const105 SkScalar next(SkPath* dst, SkScalar distance, SkPathMeasure&) const override {
106 fMaker->setExtraPropertyCallBack(fDraw->fType, GetDistance, &distance);
107 SkDrawPath* drawPath = nullptr;
108 if (fDraw->addPath->isPath()) {
109 drawPath = (SkDrawPath*) fDraw->addPath;
110 } else {
111 SkApply* apply = (SkApply*) fDraw->addPath;
112 apply->refresh(*fMaker);
113 apply->activate(*fMaker);
114 apply->interpolate(*fMaker, SkScalarRoundToInt(distance * 1000));
115 drawPath = (SkDrawPath*) apply->getScope();
116 }
117 SkMatrix m;
118 m.reset();
119 if (fDraw->addMatrix) {
120 SkDrawMatrix* matrix;
121 if (fDraw->addMatrix->getType() == SkType_Matrix)
122 matrix = (SkDrawMatrix*) fDraw->addMatrix;
123 else {
124 SkApply* apply = (SkApply*) fDraw->addMatrix;
125 apply->refresh(*fMaker);
126 apply->activate(*fMaker);
127 apply->interpolate(*fMaker, SkScalarRoundToInt(distance * 1000));
128 matrix = (SkDrawMatrix*) apply->getScope();
129 }
130 if (matrix) {
131 m = matrix->getMatrix();
132 }
133 }
134 SkScalar result = 0;
135 SkAnimatorScript::EvaluateFloat(*fMaker, nullptr, fDraw->spacing.c_str(), &result);
136 if (drawPath)
137 dst->addPath(drawPath->getPath(), m);
138 fMaker->clearExtraPropertyCallBack(fDraw->fType);
139 return result;
140 }
141
142 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const143 void toString(SkString* str) const override {
144 str->appendf("SkShape1DPathEffect: (");
145 // TODO: fill in
146 str->appendf(")");
147 }
148 #endif
149
150 private:
GetContourLength(const char * token,size_t len,void * clen,SkScriptValue * value)151 static bool GetContourLength(const char* token, size_t len, void* clen, SkScriptValue* value) {
152 if (SK_LITERAL_STR_EQUAL("contourLength", token, len)) {
153 value->fOperand.fScalar = *(SkScalar*) clen;
154 value->fType = SkType_Float;
155 return true;
156 }
157 return false;
158 }
159
GetDistance(const char * token,size_t len,void * dist,SkScriptValue * value)160 static bool GetDistance(const char* token, size_t len, void* dist, SkScriptValue* value) {
161 if (SK_LITERAL_STR_EQUAL("distance", token, len)) {
162 value->fOperand.fScalar = *(SkScalar*) dist;
163 value->fType = SkType_Float;
164 return true;
165 }
166 return false;
167 }
168
169 SkDrawShape1DPathEffect* fDraw;
170 SkAnimateMaker* fMaker;
171 };
172
173 //////////// SkDrawShapePathEffect
174
175 #if SK_USE_CONDENSED_INFO == 0
176
177 const SkMemberInfo SkDrawShapePathEffect::fInfo[] = {
178 SK_MEMBER(addMatrix, Drawable), // either matrix or apply
179 SK_MEMBER(addPath, Drawable), // either path or apply
180 SK_MEMBER(path, Path),
181 };
182
183 #endif
184
185 DEFINE_GET_MEMBER(SkDrawShapePathEffect);
186
SkDrawShapePathEffect()187 SkDrawShapePathEffect::SkDrawShapePathEffect() :
188 addPath(nullptr), addMatrix(nullptr), path(nullptr), fPathEffect(nullptr) {
189 }
190
~SkDrawShapePathEffect()191 SkDrawShapePathEffect::~SkDrawShapePathEffect() {
192 SkSafeUnref(fPathEffect);
193 }
194
addChild(SkAnimateMaker &,SkDisplayable * child)195 bool SkDrawShapePathEffect::addChild(SkAnimateMaker& , SkDisplayable* child) {
196 path = (SkDrawPath*) child;
197 return true;
198 }
199
getPathEffect()200 SkPathEffect* SkDrawShapePathEffect::getPathEffect() {
201 fPathEffect->ref();
202 return fPathEffect;
203 }
204
205 //////////// SkDrawShape1DPathEffect
206
207 #if SK_USE_CONDENSED_INFO == 0
208
209 const SkMemberInfo SkDrawShape1DPathEffect::fInfo[] = {
210 SK_MEMBER_INHERITED,
211 SK_MEMBER(phase, String),
212 SK_MEMBER(spacing, String),
213 };
214
215 #endif
216
217 DEFINE_GET_MEMBER(SkDrawShape1DPathEffect);
218
SkDrawShape1DPathEffect(SkDisplayTypes type)219 SkDrawShape1DPathEffect::SkDrawShape1DPathEffect(SkDisplayTypes type) : fType(type) {
220 }
221
~SkDrawShape1DPathEffect()222 SkDrawShape1DPathEffect::~SkDrawShape1DPathEffect() {
223 }
224
onEndElement(SkAnimateMaker & maker)225 void SkDrawShape1DPathEffect::onEndElement(SkAnimateMaker& maker) {
226 if (addPath == nullptr || (addPath->isPath() == false && addPath->isApply() == false))
227 maker.setErrorCode(SkDisplayXMLParserError::kUnknownError); // !!! add error
228 else
229 fPathEffect = new SkShape1DPathEffect(this, &maker);
230 }
231
232 ////////// SkShape2DPathEffect
233
234 class SkShape2DPathEffect : public Sk2DPathEffect {
235 public:
SkShape2DPathEffect(SkDrawShape2DPathEffect * draw,SkAnimateMaker * maker,const SkMatrix & matrix)236 SkShape2DPathEffect(SkDrawShape2DPathEffect* draw, SkAnimateMaker* maker,
237 const SkMatrix& matrix) : Sk2DPathEffect(matrix), fDraw(draw), fMaker(maker) {
238 }
239
240 // For serialization. This will never be called.
getFactory() const241 Factory getFactory() const override { sk_throw(); return nullptr; }
242
243 protected:
begin(const SkIRect & uvBounds,SkPath *) const244 void begin(const SkIRect& uvBounds, SkPath*) const override {
245 const_cast<SkShape2DPathEffect*>(this)->setUVBounds(uvBounds);
246 }
247
next(const SkPoint & loc,int u,int v,SkPath * dst) const248 void next(const SkPoint& loc, int u, int v, SkPath* dst) const override {
249 const_cast<SkShape2DPathEffect*>(this)->addPath(loc, u, v, dst);
250 }
251
252 private:
setUVBounds(const SkIRect & uvBounds)253 void setUVBounds(const SkIRect& uvBounds) {
254 fUVBounds.set(SkIntToScalar(uvBounds.fLeft), SkIntToScalar(uvBounds.fTop),
255 SkIntToScalar(uvBounds.fRight), SkIntToScalar(uvBounds.fBottom));
256 }
257
addPath(const SkPoint & loc,int u,int v,SkPath * dst)258 void addPath(const SkPoint& loc, int u, int v, SkPath* dst) {
259 fLoc = loc;
260 fU = u;
261 fV = v;
262 SkDrawPath* drawPath;
263 fMaker->setExtraPropertyCallBack(fDraw->fType, Get2D, this);
264 if (fDraw->addPath->isPath()) {
265 drawPath = (SkDrawPath*) fDraw->addPath;
266 } else {
267 SkApply* apply = (SkApply*) fDraw->addPath;
268 apply->refresh(*fMaker);
269 apply->activate(*fMaker);
270 apply->interpolate(*fMaker, v);
271 drawPath = (SkDrawPath*) apply->getScope();
272 }
273 if (drawPath == nullptr)
274 goto clearCallBack;
275 if (fDraw->matrix) {
276 SkDrawMatrix* matrix;
277 if (fDraw->matrix->getType() == SkType_Matrix)
278 matrix = (SkDrawMatrix*) fDraw->matrix;
279 else {
280 SkApply* apply = (SkApply*) fDraw->matrix;
281 apply->activate(*fMaker);
282 apply->interpolate(*fMaker, v);
283 matrix = (SkDrawMatrix*) apply->getScope();
284 }
285 if (matrix) {
286 dst->addPath(drawPath->getPath(), matrix->getMatrix());
287 goto clearCallBack;
288 }
289 }
290 dst->addPath(drawPath->getPath());
291 clearCallBack:
292 fMaker->clearExtraPropertyCallBack(fDraw->fType);
293 }
294
Get2D(const char * token,size_t len,void * s2D,SkScriptValue * value)295 static bool Get2D(const char* token, size_t len, void* s2D, SkScriptValue* value) {
296 static const char match[] = "locX|locY|left|top|right|bottom|u|v" ;
297 SkShape2DPathEffect* shape2D = (SkShape2DPathEffect*) s2D;
298 int index;
299 if (SkAnimatorScript::MapEnums(match, token, len, &index) == false)
300 return false;
301 SkASSERT((sizeof(SkPoint) + sizeof(SkRect)) / sizeof(SkScalar) == 6);
302 if (index < 6) {
303 value->fType = SkType_Float;
304 value->fOperand.fScalar = (&shape2D->fLoc.fX)[index];
305 } else {
306 value->fType = SkType_Int;
307 value->fOperand.fS32 = (&shape2D->fU)[index - 6];
308 }
309 return true;
310 }
311
312 SkPoint fLoc;
313 SkRect fUVBounds;
314 int32_t fU;
315 int32_t fV;
316 SkDrawShape2DPathEffect* fDraw;
317 SkAnimateMaker* fMaker;
318
319 // illegal
320 SkShape2DPathEffect(const SkShape2DPathEffect&);
321 SkShape2DPathEffect& operator=(const SkShape2DPathEffect&);
322 };
323
324 ////////// SkDrawShape2DPathEffect
325
326 #if SK_USE_CONDENSED_INFO == 0
327
328 const SkMemberInfo SkDrawShape2DPathEffect::fInfo[] = {
329 SK_MEMBER_INHERITED,
330 SK_MEMBER(matrix, Matrix)
331 };
332
333 #endif
334
335 DEFINE_GET_MEMBER(SkDrawShape2DPathEffect);
336
SkDrawShape2DPathEffect(SkDisplayTypes type)337 SkDrawShape2DPathEffect::SkDrawShape2DPathEffect(SkDisplayTypes type) : fType(type) {
338 }
339
~SkDrawShape2DPathEffect()340 SkDrawShape2DPathEffect::~SkDrawShape2DPathEffect() {
341 }
342
onEndElement(SkAnimateMaker & maker)343 void SkDrawShape2DPathEffect::onEndElement(SkAnimateMaker& maker) {
344 if (addPath == nullptr || (addPath->isPath() == false && addPath->isApply() == false) ||
345 matrix == nullptr)
346 maker.setErrorCode(SkDisplayXMLParserError::kUnknownError); // !!! add error
347 else
348 fPathEffect = new SkShape2DPathEffect(this, &maker, matrix->getMatrix());
349 }
350
351 ////////// SkDrawComposePathEffect
352
353 #if SK_USE_CONDENSED_INFO == 0
354
355 const SkMemberInfo SkDrawComposePathEffect::fInfo[] = {
356 SK_MEMBER(effect1, PathEffect),
357 SK_MEMBER(effect2, PathEffect)
358 };
359
360 #endif
361
362 DEFINE_GET_MEMBER(SkDrawComposePathEffect);
363
SkDrawComposePathEffect(SkDisplayTypes type)364 SkDrawComposePathEffect::SkDrawComposePathEffect(SkDisplayTypes type) : fType(type),
365 effect1(nullptr), effect2(nullptr) {
366 }
367
~SkDrawComposePathEffect()368 SkDrawComposePathEffect::~SkDrawComposePathEffect() {
369 delete effect1;
370 delete effect2;
371 }
372
addChild(SkAnimateMaker &,SkDisplayable * child)373 bool SkDrawComposePathEffect::addChild(SkAnimateMaker& , SkDisplayable* child) {
374 if (effect1 == nullptr)
375 effect1 = (SkDrawPathEffect*) child;
376 else
377 effect2 = (SkDrawPathEffect*) child;
378 return true;
379 }
380
getPathEffect()381 SkPathEffect* SkDrawComposePathEffect::getPathEffect() {
382 SkPathEffect* e1 = effect1->getPathEffect();
383 SkPathEffect* e2 = effect2->getPathEffect();
384 SkPathEffect* composite = SkComposePathEffect::Create(e1, e2);
385 e1->unref();
386 e2->unref();
387 return composite;
388 }
389
isPaint() const390 bool SkDrawComposePathEffect::isPaint() const {
391 return true;
392 }
393
394 //////////// SkDrawCornerPathEffect
395
396 #if SK_USE_CONDENSED_INFO == 0
397
398 const SkMemberInfo SkDrawCornerPathEffect::fInfo[] = {
399 SK_MEMBER(radius, Float)
400 };
401
402 #endif
403
404 DEFINE_GET_MEMBER(SkDrawCornerPathEffect);
405
SkDrawCornerPathEffect(SkDisplayTypes type)406 SkDrawCornerPathEffect::SkDrawCornerPathEffect(SkDisplayTypes type):
407 fType(type), radius(0) {
408 }
409
~SkDrawCornerPathEffect()410 SkDrawCornerPathEffect::~SkDrawCornerPathEffect() {
411 }
412
getPathEffect()413 SkPathEffect* SkDrawCornerPathEffect::getPathEffect() {
414 return SkCornerPathEffect::Create(radius);
415 }
416
417 /////////
418
419 #include "SkExtras.h"
420
421 const char kDrawShape1DPathEffectName[] = "pathEffect:shape1D";
422 const char kDrawShape2DPathEffectName[] = "pathEffect:shape2D";
423 const char kDrawComposePathEffectName[] = "pathEffect:compose";
424 const char kDrawCornerPathEffectName[] = "pathEffect:corner";
425
426 class SkExtraPathEffects : public SkExtras {
427 public:
SkExtraPathEffects()428 SkExtraPathEffects() :
429 skDrawShape1DPathEffectType(SkType_Unknown),
430 skDrawShape2DPathEffectType(SkType_Unknown),
431 skDrawComposePathEffectType(SkType_Unknown),
432 skDrawCornerPathEffectType(SkType_Unknown) {
433 }
434
createInstance(SkDisplayTypes type)435 virtual SkDisplayable* createInstance(SkDisplayTypes type) {
436 SkDisplayable* result = nullptr;
437 if (skDrawShape1DPathEffectType == type)
438 result = new SkDrawShape1DPathEffect(type);
439 else if (skDrawShape2DPathEffectType == type)
440 result = new SkDrawShape2DPathEffect(type);
441 else if (skDrawComposePathEffectType == type)
442 result = new SkDrawComposePathEffect(type);
443 else if (skDrawCornerPathEffectType == type)
444 result = new SkDrawCornerPathEffect(type);
445 return result;
446 }
447
definesType(SkDisplayTypes type)448 virtual bool definesType(SkDisplayTypes type) {
449 return type == skDrawShape1DPathEffectType ||
450 type == skDrawShape2DPathEffectType ||
451 type == skDrawComposePathEffectType ||
452 type == skDrawCornerPathEffectType;
453 }
454
455 #if SK_USE_CONDENSED_INFO == 0
getMembers(SkDisplayTypes type,int * infoCountPtr)456 virtual const SkMemberInfo* getMembers(SkDisplayTypes type, int* infoCountPtr) {
457 const SkMemberInfo* info = nullptr;
458 int infoCount = 0;
459 if (skDrawShape1DPathEffectType == type) {
460 info = SkDrawShape1DPathEffect::fInfo;
461 infoCount = SkDrawShape1DPathEffect::fInfoCount;
462 } else if (skDrawShape2DPathEffectType == type) {
463 info = SkDrawShape2DPathEffect::fInfo;
464 infoCount = SkDrawShape2DPathEffect::fInfoCount;
465 } else if (skDrawComposePathEffectType == type) {
466 info = SkDrawComposePathEffect::fInfo;
467 infoCount = SkDrawShape1DPathEffect::fInfoCount;
468 } else if (skDrawCornerPathEffectType == type) {
469 info = SkDrawCornerPathEffect::fInfo;
470 infoCount = SkDrawCornerPathEffect::fInfoCount;
471 }
472 if (infoCountPtr)
473 *infoCountPtr = infoCount;
474 return info;
475 }
476 #endif
477
478 #ifdef SK_DEBUG
getName(SkDisplayTypes type)479 virtual const char* getName(SkDisplayTypes type) {
480 if (skDrawShape1DPathEffectType == type)
481 return kDrawShape1DPathEffectName;
482 else if (skDrawShape2DPathEffectType == type)
483 return kDrawShape2DPathEffectName;
484 else if (skDrawComposePathEffectType == type)
485 return kDrawComposePathEffectName;
486 else if (skDrawCornerPathEffectType == type)
487 return kDrawCornerPathEffectName;
488 return nullptr;
489 }
490 #endif
491
getType(const char name[],size_t len)492 virtual SkDisplayTypes getType(const char name[], size_t len ) {
493 SkDisplayTypes* type = nullptr;
494 if (SK_LITERAL_STR_EQUAL(kDrawShape1DPathEffectName, name, len))
495 type = &skDrawShape1DPathEffectType;
496 else if (SK_LITERAL_STR_EQUAL(kDrawShape2DPathEffectName, name, len))
497 type = &skDrawShape2DPathEffectType;
498 else if (SK_LITERAL_STR_EQUAL(kDrawComposePathEffectName, name, len))
499 type = &skDrawComposePathEffectType;
500 else if (SK_LITERAL_STR_EQUAL(kDrawCornerPathEffectName, name, len))
501 type = &skDrawCornerPathEffectType;
502 if (type) {
503 if (*type == SkType_Unknown)
504 *type = SkDisplayType::RegisterNewType();
505 return *type;
506 }
507 return SkType_Unknown;
508 }
509
510 private:
511 SkDisplayTypes skDrawShape1DPathEffectType;
512 SkDisplayTypes skDrawShape2DPathEffectType;
513 SkDisplayTypes skDrawComposePathEffectType;
514 SkDisplayTypes skDrawCornerPathEffectType;
515 };
516
InitializeSkExtraPathEffects(SkAnimator * animator)517 void InitializeSkExtraPathEffects(SkAnimator* animator) {
518 animator->addExtras(new SkExtraPathEffects());
519 }
520
521 ////////////////
522
523
SkExtras()524 SkExtras::SkExtras() : fExtraCallBack(nullptr), fExtraStorage(nullptr) {
525 }
526