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