1
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
9
10#include "SkDisplayType.h"
11#include "SkAnimateMaker.h"
12#include "SkAnimateSet.h"
13#include "SkDisplayAdd.h"
14#include "SkDisplayApply.h"
15#include "SkDisplayBounds.h"
16#include "SkDisplayEvent.h"
17#include "SkDisplayInclude.h"
18#ifdef SK_DEBUG
19#include "SkDisplayList.h"
20#endif
21#include "SkDisplayMath.h"
22#include "SkDisplayMovie.h"
23#include "SkDisplayNumber.h"
24#include "SkDisplayPost.h"
25#include "SkDisplayRandom.h"
26#include "SkDisplayTypes.h"
27#include "SkDraw3D.h"
28#include "SkDrawBitmap.h"
29#include "SkDrawClip.h"
30#include "SkDrawDash.h"
31#include "SkDrawDiscrete.h"
32#include "SkDrawEmboss.h"
33#include "SkDrawFull.h"
34#include "SkDrawGradient.h"
35#include "SkDrawLine.h"
36#include "SkDrawMatrix.h"
37#include "SkDrawOval.h"
38#include "SkDrawPaint.h"
39#include "SkDrawPath.h"
40#include "SkDrawPoint.h"
41#include "SkDrawSaveLayer.h"
42#include "SkDrawText.h"
43#include "SkDrawTextBox.h"
44#include "SkDrawTo.h"
45#include "SkDrawTransparentShader.h"
46#include "SkDump.h"
47#include "SkExtras.h"
48#include "SkHitClear.h"
49#include "SkHitTest.h"
50#include "SkMatrixParts.h"
51#include "SkPathParts.h"
52#include "SkPostParts.h"
53#include "SkSnapshot.h"
54#include "SkTextOnPath.h"
55#include "SkTextToPath.h"
56#include "SkTSearch.h"
57
58#define CASE_NEW(_class) \
59    case SkType_##_class: result = new Sk##_class(); break
60#define CASE_DRAW_NEW(_class) \
61    case SkType_##_class: result = new SkDraw##_class(); break
62#define CASE_DISPLAY_NEW(_class) \
63    case SkType_##_class: result = new SkDisplay##_class(); break
64#ifdef SK_DEBUG
65    #define CASE_DEBUG_RETURN_NIL(_class) \
66        case SkType_##_class: return NULL
67#else
68    #define CASE_DEBUG_RETURN_NIL(_class)
69#endif
70
71
72SkDisplayTypes SkDisplayType::gNewTypes = kNumberOfTypes;
73
74SkDisplayable* SkDisplayType::CreateInstance(SkAnimateMaker* maker, SkDisplayTypes type) {
75    SkDisplayable* result = NULL;
76    switch (type) {
77        // unknown
78        CASE_DISPLAY_NEW(Math);
79        CASE_DISPLAY_NEW(Number);
80        CASE_NEW(Add);
81        CASE_NEW(AddCircle);
82        // addgeom
83        CASE_DEBUG_RETURN_NIL(AddMode);
84        CASE_NEW(AddOval);
85        CASE_NEW(AddPath);
86        CASE_NEW(AddRect);
87        CASE_NEW(AddRoundRect);
88        CASE_DEBUG_RETURN_NIL(Align);
89        CASE_NEW(Animate);
90        // animatebase
91        CASE_NEW(Apply);
92        CASE_DEBUG_RETURN_NIL(ApplyMode);
93        CASE_DEBUG_RETURN_NIL(ApplyTransition);
94        CASE_DISPLAY_NEW(Array);
95        // argb
96        // base64
97        // basebitmap
98        // baseclassinfo
99        CASE_DRAW_NEW(Bitmap);
100        // bitmapencoding
101        // bitmapformat
102        CASE_DRAW_NEW(BitmapShader);
103        CASE_DRAW_NEW(Blur);
104        CASE_DISPLAY_NEW(Boolean);
105        // boundable
106        CASE_DISPLAY_NEW(Bounds);
107        CASE_DEBUG_RETURN_NIL(Cap);
108        CASE_NEW(Clear);
109        CASE_DRAW_NEW(Clip);
110        CASE_NEW(Close);
111        CASE_DRAW_NEW(Color);
112        CASE_NEW(CubicTo);
113        CASE_NEW(Dash);
114        CASE_NEW(DataInput);
115        CASE_NEW(Discrete);
116        // displayable
117        // drawable
118        CASE_NEW(DrawTo);
119        CASE_NEW(Dump);
120        // dynamicstring
121        CASE_DRAW_NEW(Emboss);
122        CASE_DISPLAY_NEW(Event);
123        CASE_DEBUG_RETURN_NIL(EventCode);
124        CASE_DEBUG_RETURN_NIL(EventKind);
125        CASE_DEBUG_RETURN_NIL(EventMode);
126        // filltype
127        // filtertype
128        CASE_DISPLAY_NEW(Float);
129        CASE_NEW(FromPath);
130        CASE_DEBUG_RETURN_NIL(FromPathMode);
131        CASE_NEW(Full);
132        // gradient
133        CASE_NEW(Group);
134        CASE_NEW(HitClear);
135        CASE_NEW(HitTest);
136        CASE_NEW(ImageBaseBitmap);
137        CASE_NEW(Include);
138        CASE_NEW(Input);
139        CASE_DISPLAY_NEW(Int);
140        CASE_DEBUG_RETURN_NIL(Join);
141        CASE_NEW(Line);
142        CASE_NEW(LineTo);
143        CASE_NEW(DrawLinearGradient);
144        CASE_DRAW_NEW(MaskFilter);
145        CASE_DEBUG_RETURN_NIL(MaskFilterBlurStyle);
146        // maskfilterlight
147        CASE_DRAW_NEW(Matrix);
148        // memberfunction
149        // memberproperty
150        CASE_NEW(Move);
151        CASE_NEW(MoveTo);
152        CASE_DISPLAY_NEW(Movie);
153        // msec
154        CASE_NEW(Oval);
155        CASE_DRAW_NEW(Paint);
156        CASE_DRAW_NEW(Path);
157        // pathdirection
158        CASE_DRAW_NEW(PathEffect);
159        // point
160        CASE_NEW(DrawPoint);
161        CASE_NEW(PolyToPoly);
162        CASE_NEW(Polygon);
163        CASE_NEW(Polyline);
164        CASE_NEW(Post);
165        CASE_NEW(QuadTo);
166        CASE_NEW(RCubicTo);
167        CASE_NEW(RLineTo);
168        CASE_NEW(RMoveTo);
169        CASE_NEW(RQuadTo);
170        CASE_NEW(DrawRadialGradient);
171        CASE_DISPLAY_NEW(Random);
172        CASE_DRAW_NEW(Rect);
173        CASE_NEW(RectToRect);
174        CASE_NEW(Remove);
175        CASE_NEW(Replace);
176        CASE_NEW(Rotate);
177        CASE_NEW(RoundRect);
178        CASE_NEW(Save);
179        CASE_NEW(SaveLayer);
180        CASE_NEW(Scale);
181        // screenplay
182        CASE_NEW(Set);
183        CASE_DRAW_NEW(Shader);
184        CASE_NEW(Skew);
185        CASE_NEW(3D_Camera);
186        CASE_NEW(3D_Patch);
187        // 3dpoint
188        CASE_NEW(Snapshot);
189        CASE_DISPLAY_NEW(String);
190        // style
191        CASE_NEW(Text);
192        CASE_DRAW_NEW(TextBox);
193        // textboxalign
194        // textboxmode
195        CASE_NEW(TextOnPath);
196        CASE_NEW(TextToPath);
197        CASE_DEBUG_RETURN_NIL(TileMode);
198        CASE_NEW(Translate);
199        CASE_DRAW_NEW(TransparentShader);
200        CASE_DRAW_NEW(Typeface);
201        CASE_DEBUG_RETURN_NIL(Xfermode);
202        default:
203            SkExtras** end = maker->fExtras.end();
204            for (SkExtras** extraPtr = maker->fExtras.begin(); extraPtr < end; extraPtr++) {
205                if ((result = (*extraPtr)->createInstance(type)) != NULL)
206                    return result;
207            }
208            SkASSERT(0);
209    }
210    return result;
211}
212
213#undef CASE_NEW
214#undef CASE_DRAW_NEW
215#undef CASE_DISPLAY_NEW
216
217#if SK_USE_CONDENSED_INFO == 0
218
219#define CASE_GET_INFO(_class) case SkType_##_class: \
220    info = Sk##_class::fInfo; infoCount = Sk##_class::fInfoCount; break
221#define CASE_GET_DRAW_INFO(_class) case SkType_##_class: \
222    info = SkDraw##_class::fInfo; infoCount = SkDraw##_class::fInfoCount; break
223#define CASE_GET_DISPLAY_INFO(_class) case SkType_##_class: \
224    info = SkDisplay##_class::fInfo; infoCount = SkDisplay##_class::fInfoCount; \
225    break
226
227const SkMemberInfo* SkDisplayType::GetMembers(SkAnimateMaker* maker,
228        SkDisplayTypes type, int* infoCountPtr) {
229    const SkMemberInfo* info = NULL;
230    int infoCount = 0;
231    switch (type) {
232        // unknown
233        CASE_GET_DISPLAY_INFO(Math);
234        CASE_GET_DISPLAY_INFO(Number);
235        CASE_GET_INFO(Add);
236        CASE_GET_INFO(AddCircle);
237        CASE_GET_INFO(AddGeom);
238        // addmode
239        CASE_GET_INFO(AddOval);
240        CASE_GET_INFO(AddPath);
241        CASE_GET_INFO(AddRect);
242        CASE_GET_INFO(AddRoundRect);
243        // align
244        CASE_GET_INFO(Animate);
245        CASE_GET_INFO(AnimateBase);
246        CASE_GET_INFO(Apply);
247        // applymode
248        // applytransition
249        CASE_GET_DISPLAY_INFO(Array);
250        // argb
251        // base64
252        CASE_GET_INFO(BaseBitmap);
253        // baseclassinfo
254        CASE_GET_DRAW_INFO(Bitmap);
255        // bitmapencoding
256        // bitmapformat
257        CASE_GET_DRAW_INFO(BitmapShader);
258        CASE_GET_DRAW_INFO(Blur);
259        CASE_GET_DISPLAY_INFO(Boolean);
260        // boundable
261        CASE_GET_DISPLAY_INFO(Bounds);
262        // cap
263        // clear
264        CASE_GET_DRAW_INFO(Clip);
265        // close
266        CASE_GET_DRAW_INFO(Color);
267        CASE_GET_INFO(CubicTo);
268        CASE_GET_INFO(Dash);
269        CASE_GET_INFO(DataInput);
270        CASE_GET_INFO(Discrete);
271        // displayable
272        // drawable
273        CASE_GET_INFO(DrawTo);
274        CASE_GET_INFO(Dump);
275        // dynamicstring
276        CASE_GET_DRAW_INFO(Emboss);
277        CASE_GET_DISPLAY_INFO(Event);
278        // eventcode
279        // eventkind
280        // eventmode
281        // filltype
282        // filtertype
283        CASE_GET_DISPLAY_INFO(Float);
284        CASE_GET_INFO(FromPath);
285        // frompathmode
286        // full
287        CASE_GET_INFO(DrawGradient);
288        CASE_GET_INFO(Group);
289        CASE_GET_INFO(HitClear);
290        CASE_GET_INFO(HitTest);
291        CASE_GET_INFO(ImageBaseBitmap);
292        CASE_GET_INFO(Include);
293        CASE_GET_INFO(Input);
294        CASE_GET_DISPLAY_INFO(Int);
295        // join
296        CASE_GET_INFO(Line);
297        CASE_GET_INFO(LineTo);
298        CASE_GET_INFO(DrawLinearGradient);
299        // maskfilter
300        // maskfilterblurstyle
301        // maskfilterlight
302        CASE_GET_DRAW_INFO(Matrix);
303        // memberfunction
304        // memberproperty
305        CASE_GET_INFO(Move);
306        CASE_GET_INFO(MoveTo);
307        CASE_GET_DISPLAY_INFO(Movie);
308        // msec
309        CASE_GET_INFO(Oval);
310        CASE_GET_DRAW_INFO(Path);
311        CASE_GET_DRAW_INFO(Paint);
312        // pathdirection
313        // patheffect
314        case SkType_Point: info = Sk_Point::fInfo; infoCount = Sk_Point::fInfoCount; break; // no virtual flavor
315        CASE_GET_INFO(DrawPoint); // virtual flavor
316        CASE_GET_INFO(PolyToPoly);
317        CASE_GET_INFO(Polygon);
318        CASE_GET_INFO(Polyline);
319        CASE_GET_INFO(Post);
320        CASE_GET_INFO(QuadTo);
321        CASE_GET_INFO(RCubicTo);
322        CASE_GET_INFO(RLineTo);
323        CASE_GET_INFO(RMoveTo);
324        CASE_GET_INFO(RQuadTo);
325        CASE_GET_INFO(DrawRadialGradient);
326        CASE_GET_DISPLAY_INFO(Random);
327        CASE_GET_DRAW_INFO(Rect);
328        CASE_GET_INFO(RectToRect);
329        CASE_GET_INFO(Remove);
330        CASE_GET_INFO(Replace);
331        CASE_GET_INFO(Rotate);
332        CASE_GET_INFO(RoundRect);
333        CASE_GET_INFO(Save);
334        CASE_GET_INFO(SaveLayer);
335        CASE_GET_INFO(Scale);
336        // screenplay
337        CASE_GET_INFO(Set);
338        CASE_GET_DRAW_INFO(Shader);
339        CASE_GET_INFO(Skew);
340        CASE_GET_INFO(3D_Camera);
341        CASE_GET_INFO(3D_Patch);
342        CASE_GET_INFO(3D_Point);
343        CASE_GET_INFO(Snapshot);
344        CASE_GET_DISPLAY_INFO(String);
345        // style
346        CASE_GET_INFO(Text);
347        CASE_GET_DRAW_INFO(TextBox);
348        // textboxalign
349        // textboxmode
350        CASE_GET_INFO(TextOnPath);
351        CASE_GET_INFO(TextToPath);
352        // tilemode
353        CASE_GET_INFO(Translate);
354        // transparentshader
355        CASE_GET_DRAW_INFO(Typeface);
356        // xfermode
357        // knumberoftypes
358        default:
359            if (maker) {
360                SkExtras** end = maker->fExtras.end();
361                for (SkExtras** extraPtr = maker->fExtras.begin(); extraPtr < end; extraPtr++) {
362                    if ((info = (*extraPtr)->getMembers(type, infoCountPtr)) != NULL)
363                        return info;
364                }
365            }
366            return NULL;
367    }
368    if (infoCountPtr)
369        *infoCountPtr = infoCount;
370    return info;
371}
372
373const SkMemberInfo* SkDisplayType::GetMember(SkAnimateMaker* maker,
374        SkDisplayTypes type, const char** matchPtr ) {
375    int infoCount = 0;  // Initialize to remove a warning.
376    const SkMemberInfo* info = GetMembers(maker, type, &infoCount);
377    info = SkMemberInfo::Find(info, infoCount, matchPtr);
378//  SkASSERT(info);
379    return info;
380}
381
382#undef CASE_GET_INFO
383#undef CASE_GET_DRAW_INFO
384#undef CASE_GET_DISPLAY_INFO
385
386#endif // SK_USE_CONDENSED_INFO == 0
387
388#if defined SK_DEBUG || defined SK_BUILD_CONDENSED
389    #define DRAW_NAME(_name, _type) {_name, _type, true, false }
390    #define DISPLAY_NAME(_name, _type) {_name, _type, false, true }
391    #define INIT_BOOL_FIELDS    , false, false
392#else
393    #define DRAW_NAME(_name, _type) {_name, _type }
394    #define DISPLAY_NAME(_name, _type) {_name, _type }
395    #define INIT_BOOL_FIELDS
396#endif
397
398const TypeNames gTypeNames[] = {
399    // unknown
400    { "Math", SkType_Math                       INIT_BOOL_FIELDS },
401    { "Number", SkType_Number                   INIT_BOOL_FIELDS },
402    { "add", SkType_Add                         INIT_BOOL_FIELDS },
403    { "addCircle", SkType_AddCircle             INIT_BOOL_FIELDS },
404    // addgeom
405    // addmode
406    { "addOval", SkType_AddOval                 INIT_BOOL_FIELDS },
407    { "addPath", SkType_AddPath                 INIT_BOOL_FIELDS },
408    { "addRect", SkType_AddRect                 INIT_BOOL_FIELDS },
409    { "addRoundRect", SkType_AddRoundRect       INIT_BOOL_FIELDS },
410    // align
411    { "animate", SkType_Animate                 INIT_BOOL_FIELDS },
412    // animateBase
413    { "apply", SkType_Apply                     INIT_BOOL_FIELDS },
414    // applymode
415    // applytransition
416    { "array", SkType_Array                     INIT_BOOL_FIELDS },
417    // argb
418    // base64
419    // basebitmap
420    // baseclassinfo
421    DRAW_NAME("bitmap", SkType_Bitmap),
422    // bitmapencoding
423    // bitmapformat
424    DRAW_NAME("bitmapShader", SkType_BitmapShader),
425    DRAW_NAME("blur", SkType_Blur),
426    { "boolean", SkType_Boolean                 INIT_BOOL_FIELDS },
427    // boundable
428    DISPLAY_NAME("bounds", SkType_Bounds),
429    // cap
430    { "clear", SkType_Clear                     INIT_BOOL_FIELDS },
431    DRAW_NAME("clip", SkType_Clip),
432    { "close", SkType_Close                     INIT_BOOL_FIELDS },
433    DRAW_NAME("color", SkType_Color),
434    { "cubicTo", SkType_CubicTo                 INIT_BOOL_FIELDS },
435    { "dash", SkType_Dash                       INIT_BOOL_FIELDS },
436    { "data", SkType_DataInput                  INIT_BOOL_FIELDS },
437    { "discrete", SkType_Discrete               INIT_BOOL_FIELDS },
438    // displayable
439    // drawable
440    { "drawTo", SkType_DrawTo                   INIT_BOOL_FIELDS },
441    { "dump", SkType_Dump                       INIT_BOOL_FIELDS },
442    // dynamicstring
443    DRAW_NAME("emboss", SkType_Emboss),
444    DISPLAY_NAME("event", SkType_Event),
445    // eventcode
446    // eventkind
447    // eventmode
448    // filltype
449    // filtertype
450    { "float", SkType_Float                     INIT_BOOL_FIELDS },
451    { "fromPath", SkType_FromPath               INIT_BOOL_FIELDS },
452    // frompathmode
453    { "full", SkType_Full                       INIT_BOOL_FIELDS },
454    // gradient
455    { "group", SkType_Group                     INIT_BOOL_FIELDS },
456    { "hitClear", SkType_HitClear               INIT_BOOL_FIELDS },
457    { "hitTest", SkType_HitTest                 INIT_BOOL_FIELDS },
458    { "image", SkType_ImageBaseBitmap           INIT_BOOL_FIELDS },
459    { "include", SkType_Include                 INIT_BOOL_FIELDS },
460    { "input", SkType_Input                     INIT_BOOL_FIELDS },
461    { "int", SkType_Int                         INIT_BOOL_FIELDS },
462    // join
463    { "line", SkType_Line                       INIT_BOOL_FIELDS },
464    { "lineTo", SkType_LineTo                   INIT_BOOL_FIELDS },
465    { "linearGradient", SkType_DrawLinearGradient   INIT_BOOL_FIELDS },
466    { "maskFilter", SkType_MaskFilter           INIT_BOOL_FIELDS },
467    // maskfilterblurstyle
468    // maskfilterlight
469    DRAW_NAME("matrix", SkType_Matrix),
470    // memberfunction
471    // memberproperty
472    { "move", SkType_Move                       INIT_BOOL_FIELDS },
473    { "moveTo", SkType_MoveTo                   INIT_BOOL_FIELDS },
474    { "movie", SkType_Movie                     INIT_BOOL_FIELDS },
475    // msec
476    { "oval", SkType_Oval                       INIT_BOOL_FIELDS },
477    DRAW_NAME("paint", SkType_Paint),
478    DRAW_NAME("path", SkType_Path),
479    // pathdirection
480    { "pathEffect", SkType_PathEffect           INIT_BOOL_FIELDS },
481    // point
482    DRAW_NAME("point", SkType_DrawPoint),
483    { "polyToPoly", SkType_PolyToPoly           INIT_BOOL_FIELDS },
484    { "polygon", SkType_Polygon                 INIT_BOOL_FIELDS },
485    { "polyline", SkType_Polyline               INIT_BOOL_FIELDS },
486    { "post", SkType_Post                       INIT_BOOL_FIELDS },
487    { "quadTo", SkType_QuadTo                   INIT_BOOL_FIELDS },
488    { "rCubicTo", SkType_RCubicTo               INIT_BOOL_FIELDS },
489    { "rLineTo", SkType_RLineTo                 INIT_BOOL_FIELDS },
490    { "rMoveTo", SkType_RMoveTo                 INIT_BOOL_FIELDS },
491    { "rQuadTo", SkType_RQuadTo                 INIT_BOOL_FIELDS },
492    { "radialGradient", SkType_DrawRadialGradient   INIT_BOOL_FIELDS },
493    DISPLAY_NAME("random", SkType_Random),
494    { "rect", SkType_Rect                       INIT_BOOL_FIELDS },
495    { "rectToRect", SkType_RectToRect           INIT_BOOL_FIELDS },
496    { "remove", SkType_Remove                   INIT_BOOL_FIELDS },
497    { "replace", SkType_Replace                 INIT_BOOL_FIELDS },
498    { "rotate", SkType_Rotate                   INIT_BOOL_FIELDS },
499    { "roundRect", SkType_RoundRect             INIT_BOOL_FIELDS },
500    { "save", SkType_Save                       INIT_BOOL_FIELDS },
501    { "saveLayer", SkType_SaveLayer             INIT_BOOL_FIELDS },
502    { "scale", SkType_Scale                     INIT_BOOL_FIELDS },
503    // screenplay
504    { "set", SkType_Set                         INIT_BOOL_FIELDS },
505    { "shader", SkType_Shader                   INIT_BOOL_FIELDS },
506    { "skew", SkType_Skew                       INIT_BOOL_FIELDS },
507    { "skia3d:camera", SkType_3D_Camera         INIT_BOOL_FIELDS },
508    { "skia3d:patch", SkType_3D_Patch           INIT_BOOL_FIELDS },
509    // point
510    { "snapshot", SkType_Snapshot               INIT_BOOL_FIELDS },
511    { "string", SkType_String                   INIT_BOOL_FIELDS },
512    // style
513    { "text", SkType_Text                       INIT_BOOL_FIELDS },
514    { "textBox", SkType_TextBox                 INIT_BOOL_FIELDS },
515    // textboxalign
516    // textboxmode
517    { "textOnPath", SkType_TextOnPath           INIT_BOOL_FIELDS },
518    { "textToPath", SkType_TextToPath           INIT_BOOL_FIELDS },
519    // tilemode
520    { "translate", SkType_Translate             INIT_BOOL_FIELDS },
521    DRAW_NAME("transparentShader", SkType_TransparentShader),
522    { "typeface", SkType_Typeface               INIT_BOOL_FIELDS }
523    // xfermode
524    // knumberoftypes
525};
526
527const int kTypeNamesSize = SK_ARRAY_COUNT(gTypeNames);
528
529SkDisplayTypes SkDisplayType::Find(SkAnimateMaker* maker, const SkMemberInfo* match) {
530    for (int index = 0; index < kTypeNamesSize; index++) {
531        SkDisplayTypes type = gTypeNames[index].fType;
532        const SkMemberInfo* info = SkDisplayType::GetMembers(maker, type, NULL);
533        if (info == match)
534            return type;
535    }
536    return (SkDisplayTypes) -1;
537}
538
539// !!! optimize this by replacing function with a byte-sized lookup table
540SkDisplayTypes SkDisplayType::GetParent(SkAnimateMaker* maker, SkDisplayTypes base) {
541    if (base == SkType_Group || base == SkType_Save || base == SkType_SaveLayer)        //!!! cheat a little until we have a lookup table
542        return SkType_Displayable;
543    if (base == SkType_Set)
544        return SkType_Animate;  // another cheat until we have a lookup table
545    const SkMemberInfo* info = GetMembers(maker, base, NULL); // get info for this type
546    SkASSERT(info);
547    if (info->fType != SkType_BaseClassInfo)
548        return SkType_Unknown; // if no base, done
549    // !!! could change SK_MEMBER_INHERITED macro to take type, stuff in offset, so that
550    // this (and table builder) could know type without the following steps:
551    const SkMemberInfo* inherited = info->getInherited();
552    SkDisplayTypes result = (SkDisplayTypes) (SkType_Unknown + 1);
553    for (; result <= SkType_Xfermode; result = (SkDisplayTypes) (result + 1)) {
554        const SkMemberInfo* match = GetMembers(maker, result, NULL);
555        if (match == inherited)
556            break;
557    }
558    SkASSERT(result <= SkType_Xfermode);
559    return result;
560}
561
562SkDisplayTypes SkDisplayType::GetType(SkAnimateMaker* maker, const char match[], size_t len ) {
563    int index = SkStrSearch(&gTypeNames[0].fName, kTypeNamesSize, match,
564        len, sizeof(gTypeNames[0]));
565    if (index >= 0 && index < kTypeNamesSize)
566        return gTypeNames[index].fType;
567    SkExtras** end = maker->fExtras.end();
568    for (SkExtras** extraPtr = maker->fExtras.begin(); extraPtr < end; extraPtr++) {
569        SkDisplayTypes result = (*extraPtr)->getType(match, len);
570        if (result != SkType_Unknown)
571            return result;
572    }
573    return (SkDisplayTypes) -1;
574}
575
576bool SkDisplayType::IsEnum(SkAnimateMaker* , SkDisplayTypes type) {
577    switch (type) {
578        case SkType_AddMode:
579        case SkType_Align:
580        case SkType_ApplyMode:
581        case SkType_ApplyTransition:
582        case SkType_BitmapEncoding:
583        case SkType_BitmapFormat:
584        case SkType_Boolean:
585        case SkType_Cap:
586        case SkType_EventCode:
587        case SkType_EventKind:
588        case SkType_EventMode:
589        case SkType_FillType:
590        case SkType_FilterType:
591        case SkType_FontStyle:
592        case SkType_FromPathMode:
593        case SkType_Join:
594        case SkType_MaskFilterBlurStyle:
595        case SkType_PathDirection:
596        case SkType_Style:
597        case SkType_TextBoxAlign:
598        case SkType_TextBoxMode:
599        case SkType_TileMode:
600        case SkType_Xfermode:
601            return true;
602        default:    // to avoid warnings
603            break;
604    }
605    return false;
606}
607
608bool SkDisplayType::IsDisplayable(SkAnimateMaker* , SkDisplayTypes type) {
609    switch (type) {
610        case SkType_Add:
611        case SkType_AddCircle:
612        case SkType_AddOval:
613        case SkType_AddPath:
614        case SkType_AddRect:
615        case SkType_AddRoundRect:
616        case SkType_Animate:
617        case SkType_AnimateBase:
618        case SkType_Apply:
619        case SkType_BaseBitmap:
620        case SkType_Bitmap:
621        case SkType_BitmapShader:
622        case SkType_Blur:
623        case SkType_Clear:
624        case SkType_Clip:
625        case SkType_Close:
626        case SkType_Color:
627        case SkType_CubicTo:
628        case SkType_Dash:
629        case SkType_DataInput:
630        case SkType_Discrete:
631        case SkType_Displayable:
632        case SkType_Drawable:
633        case SkType_DrawTo:
634        case SkType_Emboss:
635        case SkType_Event:
636        case SkType_FromPath:
637        case SkType_Full:
638        case SkType_Group:
639        case SkType_ImageBaseBitmap:
640        case SkType_Input:
641        case SkType_Line:
642        case SkType_LineTo:
643        case SkType_DrawLinearGradient:
644        case SkType_Matrix:
645        case SkType_Move:
646        case SkType_MoveTo:
647        case SkType_Movie:
648        case SkType_Oval:
649        case SkType_Paint:
650        case SkType_Path:
651        case SkType_PolyToPoly:
652        case SkType_Polygon:
653        case SkType_Polyline:
654        case SkType_Post:
655        case SkType_QuadTo:
656        case SkType_RCubicTo:
657        case SkType_RLineTo:
658        case SkType_RMoveTo:
659        case SkType_RQuadTo:
660        case SkType_DrawRadialGradient:
661        case SkType_Random:
662        case SkType_Rect:
663        case SkType_RectToRect:
664        case SkType_Remove:
665        case SkType_Replace:
666        case SkType_Rotate:
667        case SkType_RoundRect:
668        case SkType_Save:
669        case SkType_SaveLayer:
670        case SkType_Scale:
671        case SkType_Set:
672        case SkType_Shader:
673        case SkType_Skew:
674        case SkType_3D_Camera:
675        case SkType_3D_Patch:
676        case SkType_Snapshot:
677        case SkType_Text:
678        case SkType_TextBox:
679        case SkType_TextOnPath:
680        case SkType_TextToPath:
681        case SkType_Translate:
682        case SkType_TransparentShader:
683            return true;
684        default:    // to avoid warnings
685            break;
686    }
687    return false;
688}
689
690bool SkDisplayType::IsStruct(SkAnimateMaker* , SkDisplayTypes type) {
691    switch (type) {
692        case SkType_Point:
693        case SkType_3D_Point:
694            return true;
695        default:    // to avoid warnings
696            break;
697    }
698    return false;
699}
700
701
702SkDisplayTypes SkDisplayType::RegisterNewType() {
703    gNewTypes = (SkDisplayTypes) (gNewTypes + 1);
704    return gNewTypes;
705}
706
707
708
709#ifdef SK_DEBUG
710const char* SkDisplayType::GetName(SkAnimateMaker* maker, SkDisplayTypes type) {
711    for (int index = 0; index < kTypeNamesSize - 1; index++) {
712        if (gTypeNames[index].fType == type)
713            return gTypeNames[index].fName;
714    }
715    SkExtras** end = maker->fExtras.end();
716    for (SkExtras** extraPtr = maker->fExtras.begin(); extraPtr < end; extraPtr++) {
717        const char* result = (*extraPtr)->getName(type);
718        if (result != NULL)
719            return result;
720    }
721    return NULL;
722}
723#endif
724
725#ifdef SK_SUPPORT_UNITTEST
726void SkDisplayType::UnitTest() {
727    SkAnimator animator;
728    SkAnimateMaker* maker = animator.fMaker;
729    int index;
730    for (index = 0; index < kTypeNamesSize - 1; index++) {
731        SkASSERT(strcmp(gTypeNames[index].fName, gTypeNames[index + 1].fName) < 0);
732        SkASSERT(gTypeNames[index].fType < gTypeNames[index + 1].fType);
733    }
734    for (index = 0; index < kTypeNamesSize; index++) {
735        SkDisplayable* test = CreateInstance(maker, gTypeNames[index].fType);
736        if (test == NULL)
737            continue;
738#if defined _WIN32 && _MSC_VER >= 1300  && defined _INC_CRTDBG // only on windows, only if using "crtdbg.h"
739    // we know that crtdbg puts 0xfdfdfdfd at the end of the block
740    // look for unitialized memory, signature 0xcdcdcdcd prior to that
741        int* start = (int*) test;
742        while (*start != 0xfdfdfdfd) {
743            SkASSERT(*start != 0xcdcdcdcd);
744            start++;
745        }
746#endif
747        delete test;
748    }
749    for (index = 0; index < kTypeNamesSize; index++) {
750        int infoCount;
751        const SkMemberInfo* info = GetMembers(maker, gTypeNames[index].fType, &infoCount);
752        if (info == NULL)
753            continue;
754#if SK_USE_CONDENSED_INFO == 0
755        for (int inner = 0; inner < infoCount - 1; inner++) {
756            if (info[inner].fType == SkType_BaseClassInfo)
757                continue;
758            SkASSERT(strcmp(info[inner].fName, info[inner + 1].fName) < 0);
759        }
760#endif
761    }
762#if defined SK_DEBUG || defined SK_BUILD_CONDENSED
763    BuildCondensedInfo(maker);
764#endif
765}
766#endif
767