SkDrawCommand.cpp revision 86681b37bd20204e47a492119b345c01d00bc939
1
2/*
3 * Copyright 2012 Google Inc.
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 "SkDrawCommand.h"
11#include "SkObjectParser.h"
12
13// TODO(chudy): Refactor into non subclass model.
14
15SkDrawCommand::SkDrawCommand(DrawType type)
16    : fDrawType(type)
17    , fVisible(true) {
18}
19
20SkDrawCommand::SkDrawCommand() {
21    fVisible = true;
22}
23
24SkDrawCommand::~SkDrawCommand() {
25    fInfo.deleteAll();
26}
27
28const char* SkDrawCommand::GetCommandString(DrawType type) {
29    switch (type) {
30        case UNUSED: SkDEBUGFAIL("DrawType UNUSED\n"); break;
31        case DRAW_CLEAR: return "Clear";
32        case CLIP_PATH: return "Clip Path";
33        case CLIP_REGION: return "Clip Region";
34        case CLIP_RECT: return "Clip Rect";
35        case CLIP_RRECT: return "Clip RRect";
36        case CONCAT: return "Concat";
37        case DRAW_BITMAP: return "Draw Bitmap";
38        case DRAW_BITMAP_MATRIX: return "Draw Bitmap Matrix";
39        case DRAW_BITMAP_NINE: return "Draw Bitmap Nine";
40        case DRAW_BITMAP_RECT_TO_RECT: return "Draw Bitmap Rect";
41        case DRAW_DATA: return "Draw Data";
42        case DRAW_OVAL: return "Draw Oval";
43        case DRAW_PAINT: return "Draw Paint";
44        case DRAW_PATH: return "Draw Path";
45        case DRAW_PICTURE: return "Draw Picture";
46        case DRAW_POINTS: return "Draw Points";
47        case DRAW_POS_TEXT: return "Draw Pos Text";
48        case DRAW_POS_TEXT_H: return "Draw Pos Text H";
49        case DRAW_RECT: return "Draw Rect";
50        case DRAW_RRECT: return "Draw RRect";
51        case DRAW_SPRITE: return "Draw Sprite";
52        case DRAW_TEXT: return "Draw Text";
53        case DRAW_TEXT_ON_PATH: return "Draw Text On Path";
54        case DRAW_VERTICES: return "Draw Vertices";
55        case RESTORE: return "Restore";
56        case ROTATE: return "Rotate";
57        case SAVE: return "Save";
58        case SAVE_LAYER: return "Save Layer";
59        case SCALE: return "Scale";
60        case SET_MATRIX: return "Set Matrix";
61        case SKEW: return "Skew";
62        case TRANSLATE: return "Translate";
63        case NOOP: return "NoOp";
64        case BEGIN_COMMENT_GROUP: return "BeginCommentGroup";
65        case COMMENT: return "Comment";
66        case END_COMMENT_GROUP: return "EndCommentGroup";
67        default:
68            SkDebugf("DrawType error 0x%08x\n", type);
69            SkASSERT(0);
70            break;
71    }
72    SkDEBUGFAIL("DrawType UNUSED\n");
73    return NULL;
74}
75
76SkString SkDrawCommand::toString() {
77    return SkString(GetCommandString(fDrawType));
78}
79
80Clear::Clear(SkColor color) {
81    fColor = color;
82    fDrawType = DRAW_CLEAR;
83    fInfo.push(SkObjectParser::CustomTextToString("No Parameters"));
84}
85
86void Clear::execute(SkCanvas* canvas) {
87    canvas->clear(fColor);
88}
89
90namespace {
91
92void xlate_and_scale_to_bounds(SkCanvas* canvas, const SkRect& bounds) {
93    const SkISize& size = canvas->getDeviceSize();
94
95    static const SkScalar kInsetFrac = 0.9f; // Leave a border around object
96
97    canvas->translate(size.fWidth/2.0f, size.fHeight/2.0f);
98    if (bounds.width() > bounds.height()) {
99        canvas->scale(SkDoubleToScalar((kInsetFrac*size.fWidth)/bounds.width()),
100                      SkDoubleToScalar((kInsetFrac*size.fHeight)/bounds.width()));
101    } else {
102        canvas->scale(SkDoubleToScalar((kInsetFrac*size.fWidth)/bounds.height()),
103                      SkDoubleToScalar((kInsetFrac*size.fHeight)/bounds.height()));
104    }
105    canvas->translate(-bounds.centerX(), -bounds.centerY());
106}
107
108
109void render_path(SkCanvas* canvas, const SkPath& path) {
110    canvas->clear(0xFFFFFFFF);
111    canvas->save();
112
113    const SkRect& bounds = path.getBounds();
114
115    xlate_and_scale_to_bounds(canvas, bounds);
116
117    SkPaint p;
118    p.setColor(SK_ColorBLACK);
119    p.setStyle(SkPaint::kStroke_Style);
120
121    canvas->drawPath(path, p);
122    canvas->restore();
123}
124
125void render_bitmap(SkCanvas* canvas, const SkBitmap& input, const SkRect* srcRect = NULL) {
126    const SkISize& size = canvas->getDeviceSize();
127
128    SkScalar xScale = SkIntToScalar(size.fWidth-2) / input.width();
129    SkScalar yScale = SkIntToScalar(size.fHeight-2) / input.height();
130
131    if (input.width() > input.height()) {
132        yScale *= input.height() / (float) input.width();
133    } else {
134        xScale *= input.width() / (float) input.height();
135    }
136
137    SkRect dst = SkRect::MakeXYWH(SK_Scalar1, SK_Scalar1,
138                                  xScale * input.width(),
139                                  yScale * input.height());
140
141    canvas->clear(0xFFFFFFFF);
142    canvas->drawBitmapRect(input, NULL, dst);
143
144    if (NULL != srcRect) {
145        SkRect r = SkRect::MakeLTRB(srcRect->fLeft * xScale + SK_Scalar1,
146                                    srcRect->fTop * yScale + SK_Scalar1,
147                                    srcRect->fRight * xScale + SK_Scalar1,
148                                    srcRect->fBottom * yScale + SK_Scalar1);
149        SkPaint p;
150        p.setColor(SK_ColorRED);
151        p.setStyle(SkPaint::kStroke_Style);
152
153        canvas->drawRect(r, p);
154    }
155}
156
157void render_rrect(SkCanvas* canvas, const SkRRect& rrect) {
158    canvas->clear(0xFFFFFFFF);
159    canvas->save();
160
161    const SkRect& bounds = rrect.getBounds();
162
163    xlate_and_scale_to_bounds(canvas, bounds);
164
165    SkPaint p;
166    p.setColor(SK_ColorBLACK);
167    p.setStyle(SkPaint::kStroke_Style);
168
169    canvas->drawRRect(rrect, p);
170    canvas->restore();
171}
172
173};
174
175
176ClipPath::ClipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
177    fPath = path;
178    fOp = op;
179    fDoAA = doAA;
180    fDrawType = CLIP_PATH;
181
182    fInfo.push(SkObjectParser::PathToString(path));
183    fInfo.push(SkObjectParser::RegionOpToString(op));
184    fInfo.push(SkObjectParser::BoolToString(doAA));
185}
186
187void ClipPath::execute(SkCanvas* canvas) {
188    canvas->clipPath(fPath, fOp, fDoAA);
189}
190
191bool ClipPath::render(SkCanvas* canvas) const {
192    render_path(canvas, fPath);
193    return true;
194}
195
196ClipRegion::ClipRegion(const SkRegion& region, SkRegion::Op op) {
197    fRegion = region;
198    fOp = op;
199    fDrawType = CLIP_REGION;
200
201    fInfo.push(SkObjectParser::RegionToString(region));
202    fInfo.push(SkObjectParser::RegionOpToString(op));
203}
204
205void ClipRegion::execute(SkCanvas* canvas) {
206    canvas->clipRegion(fRegion, fOp);
207}
208
209ClipRect::ClipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
210    fRect = rect;
211    fOp = op;
212    fDoAA = doAA;
213    fDrawType = CLIP_RECT;
214
215    fInfo.push(SkObjectParser::RectToString(rect));
216    fInfo.push(SkObjectParser::RegionOpToString(op));
217    fInfo.push(SkObjectParser::BoolToString(doAA));
218}
219
220void ClipRect::execute(SkCanvas* canvas) {
221    canvas->clipRect(fRect, fOp, fDoAA);
222}
223
224ClipRRect::ClipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
225    fRRect = rrect;
226    fOp = op;
227    fDoAA = doAA;
228    fDrawType = CLIP_RRECT;
229
230    fInfo.push(SkObjectParser::RRectToString(rrect));
231    fInfo.push(SkObjectParser::RegionOpToString(op));
232    fInfo.push(SkObjectParser::BoolToString(doAA));
233}
234
235void ClipRRect::execute(SkCanvas* canvas) {
236    canvas->clipRRect(fRRect, fOp, fDoAA);
237}
238
239bool ClipRRect::render(SkCanvas* canvas) const {
240    render_rrect(canvas, fRRect);
241    return true;
242}
243
244Concat::Concat(const SkMatrix& matrix) {
245    fMatrix = matrix;
246    fDrawType = CONCAT;
247
248    fInfo.push(SkObjectParser::MatrixToString(matrix));
249}
250
251void Concat::execute(SkCanvas* canvas) {
252    canvas->concat(fMatrix);
253}
254
255DrawBitmap::DrawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
256                       const SkPaint* paint) {
257    fBitmap = bitmap;
258    fLeft = left;
259    fTop = top;
260    if (NULL != paint) {
261        fPaint = *paint;
262        fPaintPtr = &fPaint;
263    } else {
264        fPaintPtr = NULL;
265    }
266    fDrawType = DRAW_BITMAP;
267
268    fInfo.push(SkObjectParser::BitmapToString(bitmap));
269    fInfo.push(SkObjectParser::ScalarToString(left, "SkScalar left: "));
270    fInfo.push(SkObjectParser::ScalarToString(top, "SkScalar top: "));
271    if (NULL != paint) {
272        fInfo.push(SkObjectParser::PaintToString(*paint));
273    }
274}
275
276void DrawBitmap::execute(SkCanvas* canvas) {
277    canvas->drawBitmap(fBitmap, fLeft, fTop, fPaintPtr);
278}
279
280bool DrawBitmap::render(SkCanvas* canvas) const {
281    render_bitmap(canvas, fBitmap);
282    return true;
283}
284
285DrawBitmapMatrix::DrawBitmapMatrix(const SkBitmap& bitmap,
286                                   const SkMatrix& matrix,
287                                   const SkPaint* paint) {
288    fBitmap = bitmap;
289    fMatrix = matrix;
290    if (NULL != paint) {
291        fPaint = *paint;
292        fPaintPtr = &fPaint;
293    } else {
294        fPaintPtr = NULL;
295    }
296    fDrawType = DRAW_BITMAP_MATRIX;
297
298    fInfo.push(SkObjectParser::BitmapToString(bitmap));
299    fInfo.push(SkObjectParser::MatrixToString(matrix));
300    if (NULL != paint) {
301        fInfo.push(SkObjectParser::PaintToString(*paint));
302    }
303}
304
305void DrawBitmapMatrix::execute(SkCanvas* canvas) {
306    canvas->drawBitmapMatrix(fBitmap, fMatrix, fPaintPtr);
307}
308
309bool DrawBitmapMatrix::render(SkCanvas* canvas) const {
310    render_bitmap(canvas, fBitmap);
311    return true;
312}
313
314DrawBitmapNine::DrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
315                               const SkRect& dst, const SkPaint* paint) {
316    fBitmap = bitmap;
317    fCenter = center;
318    fDst = dst;
319    if (NULL != paint) {
320        fPaint = *paint;
321        fPaintPtr = &fPaint;
322    } else {
323        fPaintPtr = NULL;
324    }
325    fDrawType = DRAW_BITMAP_NINE;
326
327    fInfo.push(SkObjectParser::BitmapToString(bitmap));
328    fInfo.push(SkObjectParser::IRectToString(center));
329    fInfo.push(SkObjectParser::RectToString(dst, "Dst: "));
330    if (NULL != paint) {
331        fInfo.push(SkObjectParser::PaintToString(*paint));
332    }
333}
334
335void DrawBitmapNine::execute(SkCanvas* canvas) {
336    canvas->drawBitmapNine(fBitmap, fCenter, fDst, fPaintPtr);
337}
338
339bool DrawBitmapNine::render(SkCanvas* canvas) const {
340    render_bitmap(canvas, fBitmap);
341    return true;
342}
343
344DrawBitmapRect::DrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
345                               const SkRect& dst, const SkPaint* paint) {
346    fBitmap = bitmap;
347    if (NULL != src) {
348        fSrc = *src;
349    } else {
350        fSrc.setEmpty();
351    }
352    fDst = dst;
353
354    if (NULL != paint) {
355        fPaint = *paint;
356        fPaintPtr = &fPaint;
357    } else {
358        fPaintPtr = NULL;
359    }
360    fDrawType = DRAW_BITMAP_RECT_TO_RECT;
361
362    fInfo.push(SkObjectParser::BitmapToString(bitmap));
363    if (NULL != src) {
364        fInfo.push(SkObjectParser::RectToString(*src, "Src: "));
365    }
366    fInfo.push(SkObjectParser::RectToString(dst, "Dst: "));
367    if (NULL != paint) {
368        fInfo.push(SkObjectParser::PaintToString(*paint));
369    }
370}
371
372void DrawBitmapRect::execute(SkCanvas* canvas) {
373    canvas->drawBitmapRectToRect(fBitmap, this->srcRect(), fDst, fPaintPtr);
374}
375
376bool DrawBitmapRect::render(SkCanvas* canvas) const {
377    render_bitmap(canvas, fBitmap, this->srcRect());
378    return true;
379}
380
381DrawData::DrawData(const void* data, size_t length) {
382    fData = new char[length];
383    memcpy(fData, data, length);
384    fLength = length;
385    fDrawType = DRAW_DATA;
386
387    // TODO: add display of actual data?
388    SkString* str = new SkString;
389    str->appendf("length: %d", (int) length);
390    fInfo.push(str);
391}
392
393void DrawData::execute(SkCanvas* canvas) {
394    canvas->drawData(fData, fLength);
395}
396
397BeginCommentGroup::BeginCommentGroup(const char* description)
398    : INHERITED(BEGIN_COMMENT_GROUP)
399    , fDescription(description) {
400    SkString* temp = new SkString;
401    temp->appendf("Description: %s", description);
402    fInfo.push(temp);
403}
404
405Comment::Comment(const char* kywd, const char* value)
406    : INHERITED(COMMENT)
407    , fKywd(kywd)
408    , fValue(value) {
409    SkString* temp = new SkString;
410    temp->appendf("%s: %s", kywd, value);
411    fInfo.push(temp);
412}
413
414EndCommentGroup::EndCommentGroup() : INHERITED(END_COMMENT_GROUP) {
415}
416
417DrawOval::DrawOval(const SkRect& oval, const SkPaint& paint) {
418    fOval = oval;
419    fPaint = paint;
420    fDrawType = DRAW_OVAL;
421
422    fInfo.push(SkObjectParser::RectToString(oval));
423    fInfo.push(SkObjectParser::PaintToString(paint));
424}
425
426void DrawOval::execute(SkCanvas* canvas) {
427    canvas->drawOval(fOval, fPaint);
428}
429
430bool DrawOval::render(SkCanvas* canvas) const {
431    canvas->clear(0xFFFFFFFF);
432    canvas->save();
433
434    xlate_and_scale_to_bounds(canvas, fOval);
435
436    SkPaint p;
437    p.setColor(SK_ColorBLACK);
438    p.setStyle(SkPaint::kStroke_Style);
439
440    canvas->drawOval(fOval, p);
441    canvas->restore();
442
443    return true;
444}
445
446DrawPaint::DrawPaint(const SkPaint& paint) {
447    fPaint = paint;
448    fDrawType = DRAW_PAINT;
449
450    fInfo.push(SkObjectParser::PaintToString(paint));
451}
452
453void DrawPaint::execute(SkCanvas* canvas) {
454    canvas->drawPaint(fPaint);
455}
456
457bool DrawPaint::render(SkCanvas* canvas) const {
458    canvas->clear(0xFFFFFFFF);
459    canvas->drawPaint(fPaint);
460    return true;
461}
462
463DrawPath::DrawPath(const SkPath& path, const SkPaint& paint) {
464    fPath = path;
465    fPaint = paint;
466    fDrawType = DRAW_PATH;
467
468    fInfo.push(SkObjectParser::PathToString(path));
469    fInfo.push(SkObjectParser::PaintToString(paint));
470}
471
472void DrawPath::execute(SkCanvas* canvas) {
473    canvas->drawPath(fPath, fPaint);
474}
475
476bool DrawPath::render(SkCanvas* canvas) const {
477    render_path(canvas, fPath);
478    return true;
479}
480
481DrawPicture::DrawPicture(SkPicture& picture) :
482    fPicture(picture) {
483    fDrawType = DRAW_PICTURE;
484    fInfo.push(SkObjectParser::CustomTextToString("To be implemented."));
485}
486
487void DrawPicture::execute(SkCanvas* canvas) {
488    canvas->drawPicture(fPicture);
489}
490
491DrawPoints::DrawPoints(SkCanvas::PointMode mode, size_t count,
492                       const SkPoint pts[], const SkPaint& paint) {
493    fMode = mode;
494    fCount = count;
495    fPts = new SkPoint[count];
496    memcpy(fPts, pts, count * sizeof(SkPoint));
497    fPaint = paint;
498    fDrawType = DRAW_POINTS;
499
500    fInfo.push(SkObjectParser::PointsToString(pts, count));
501    fInfo.push(SkObjectParser::ScalarToString(SkIntToScalar((unsigned int)count),
502                                              "Points: "));
503    fInfo.push(SkObjectParser::PointModeToString(mode));
504    fInfo.push(SkObjectParser::PaintToString(paint));
505}
506
507void DrawPoints::execute(SkCanvas* canvas) {
508    canvas->drawPoints(fMode, fCount, fPts, fPaint);
509}
510
511bool DrawPoints::render(SkCanvas* canvas) const {
512    canvas->clear(0xFFFFFFFF);
513    canvas->save();
514
515    SkRect bounds;
516
517    bounds.setEmpty();
518    for (unsigned int i = 0; i < fCount; ++i) {
519        bounds.growToInclude(fPts[i].fX, fPts[i].fY);
520    }
521
522    xlate_and_scale_to_bounds(canvas, bounds);
523
524    SkPaint p;
525    p.setColor(SK_ColorBLACK);
526    p.setStyle(SkPaint::kStroke_Style);
527
528    canvas->drawPoints(fMode, fCount, fPts, p);
529    canvas->restore();
530
531    return true;
532}
533
534DrawPosText::DrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
535                         const SkPaint& paint) {
536    size_t numPts = paint.countText(text, byteLength);
537
538    fText = new char[byteLength];
539    memcpy(fText, text, byteLength);
540    fByteLength = byteLength;
541
542    fPos = new SkPoint[numPts];
543    memcpy(fPos, pos, numPts * sizeof(SkPoint));
544
545    fPaint = paint;
546    fDrawType = DRAW_POS_TEXT;
547
548    fInfo.push(SkObjectParser::TextToString(text, byteLength, paint.getTextEncoding()));
549    // TODO(chudy): Test that this works.
550    fInfo.push(SkObjectParser::PointsToString(pos, 1));
551    fInfo.push(SkObjectParser::PaintToString(paint));
552}
553
554void DrawPosText::execute(SkCanvas* canvas) {
555    canvas->drawPosText(fText, fByteLength, fPos, fPaint);
556}
557
558
559DrawPosTextH::DrawPosTextH(const void* text, size_t byteLength,
560                           const SkScalar xpos[], SkScalar constY,
561                           const SkPaint& paint) {
562    size_t numPts = paint.countText(text, byteLength);
563
564    fText = new char[byteLength];
565    memcpy(fText, text, byteLength);
566    fByteLength = byteLength;
567
568    fXpos = new SkScalar[numPts];
569    memcpy(fXpos, xpos, numPts * sizeof(SkScalar));
570
571    fConstY = constY;
572    fPaint = paint;
573    fDrawType = DRAW_POS_TEXT_H;
574
575    fInfo.push(SkObjectParser::TextToString(text, byteLength, paint.getTextEncoding()));
576    fInfo.push(SkObjectParser::ScalarToString(xpos[0], "XPOS: "));
577    fInfo.push(SkObjectParser::ScalarToString(constY, "SkScalar constY: "));
578    fInfo.push(SkObjectParser::PaintToString(paint));
579}
580
581void DrawPosTextH::execute(SkCanvas* canvas) {
582    canvas->drawPosTextH(fText, fByteLength, fXpos, fConstY, fPaint);
583}
584
585DrawRectC::DrawRectC(const SkRect& rect, const SkPaint& paint) {
586    fRect = rect;
587    fPaint = paint;
588    fDrawType = DRAW_RECT;
589
590    fInfo.push(SkObjectParser::RectToString(rect));
591    fInfo.push(SkObjectParser::PaintToString(paint));
592}
593
594void DrawRectC::execute(SkCanvas* canvas) {
595    canvas->drawRect(fRect, fPaint);
596}
597
598DrawRRect::DrawRRect(const SkRRect& rrect, const SkPaint& paint) {
599    fRRect = rrect;
600    fPaint = paint;
601    fDrawType = DRAW_RRECT;
602
603    fInfo.push(SkObjectParser::RRectToString(rrect));
604    fInfo.push(SkObjectParser::PaintToString(paint));
605}
606
607void DrawRRect::execute(SkCanvas* canvas) {
608    canvas->drawRRect(fRRect, fPaint);
609}
610
611bool DrawRRect::render(SkCanvas* canvas) const {
612    render_rrect(canvas, fRRect);
613    return true;
614}
615
616DrawSprite::DrawSprite(const SkBitmap& bitmap, int left, int top,
617                       const SkPaint* paint) {
618    fBitmap = bitmap;
619    fLeft = left;
620    fTop = top;
621    if (NULL != paint) {
622        fPaint = *paint;
623        fPaintPtr = &fPaint;
624    } else {
625        fPaintPtr = NULL;
626    }
627    fDrawType = DRAW_SPRITE;
628
629    fInfo.push(SkObjectParser::BitmapToString(bitmap));
630    fInfo.push(SkObjectParser::IntToString(left, "Left: "));
631    fInfo.push(SkObjectParser::IntToString(top, "Top: "));
632    if (NULL != paint) {
633        fInfo.push(SkObjectParser::PaintToString(*paint));
634    }
635}
636
637void DrawSprite::execute(SkCanvas* canvas) {
638    canvas->drawSprite(fBitmap, fLeft, fTop, fPaintPtr);
639}
640
641bool DrawSprite::render(SkCanvas* canvas) const {
642    render_bitmap(canvas, fBitmap);
643    return true;
644}
645
646DrawTextC::DrawTextC(const void* text, size_t byteLength, SkScalar x, SkScalar y,
647                     const SkPaint& paint) {
648    fText = new char[byteLength];
649    memcpy(fText, text, byteLength);
650    fByteLength = byteLength;
651    fX = x;
652    fY = y;
653    fPaint = paint;
654    fDrawType = DRAW_TEXT;
655
656    fInfo.push(SkObjectParser::TextToString(text, byteLength, paint.getTextEncoding()));
657    fInfo.push(SkObjectParser::ScalarToString(x, "SkScalar x: "));
658    fInfo.push(SkObjectParser::ScalarToString(y, "SkScalar y: "));
659    fInfo.push(SkObjectParser::PaintToString(paint));
660}
661
662void DrawTextC::execute(SkCanvas* canvas) {
663    canvas->drawText(fText, fByteLength, fX, fY, fPaint);
664}
665
666DrawTextOnPath::DrawTextOnPath(const void* text, size_t byteLength,
667                               const SkPath& path, const SkMatrix* matrix,
668                               const SkPaint& paint) {
669    fText = new char[byteLength];
670    memcpy(fText, text, byteLength);
671    fByteLength = byteLength;
672    fPath = path;
673    if (NULL != matrix) {
674        fMatrix = *matrix;
675    } else {
676        fMatrix.setIdentity();
677    }
678    fPaint = paint;
679    fDrawType = DRAW_TEXT_ON_PATH;
680
681    fInfo.push(SkObjectParser::TextToString(text, byteLength, paint.getTextEncoding()));
682    fInfo.push(SkObjectParser::PathToString(path));
683    if (NULL != matrix) {
684        fInfo.push(SkObjectParser::MatrixToString(*matrix));
685    }
686    fInfo.push(SkObjectParser::PaintToString(paint));
687}
688
689void DrawTextOnPath::execute(SkCanvas* canvas) {
690    canvas->drawTextOnPath(fText, fByteLength, fPath,
691                           fMatrix.isIdentity() ? NULL : &fMatrix,
692                           fPaint);
693}
694
695DrawVertices::DrawVertices(SkCanvas::VertexMode vmode, int vertexCount,
696                           const SkPoint vertices[], const SkPoint texs[],
697                           const SkColor colors[], SkXfermode* xfermode,
698                           const uint16_t indices[], int indexCount,
699                           const SkPaint& paint) {
700    fVmode = vmode;
701
702    fVertexCount = vertexCount;
703
704    fVertices = new SkPoint[vertexCount];
705    memcpy(fVertices, vertices, vertexCount * sizeof(SkPoint));
706
707    if (NULL != texs) {
708        fTexs = new SkPoint[vertexCount];
709        memcpy(fTexs, texs, vertexCount * sizeof(SkPoint));
710    } else {
711        fTexs = NULL;
712    }
713
714    if (NULL != colors) {
715        fColors = new SkColor[vertexCount];
716        memcpy(fColors, colors, vertexCount * sizeof(SkColor));
717    } else {
718        fColors = NULL;
719    }
720
721    fXfermode = xfermode;
722    if (NULL != fXfermode) {
723        fXfermode->ref();
724    }
725
726    if (indexCount > 0) {
727        fIndices = new uint16_t[indexCount];
728        memcpy(fIndices, indices, indexCount * sizeof(uint16_t));
729    } else {
730        fIndices = NULL;
731    }
732
733    fIndexCount = indexCount;
734    fPaint = paint;
735    fDrawType = DRAW_VERTICES;
736
737    // TODO(chudy)
738    fInfo.push(SkObjectParser::CustomTextToString("To be implemented."));
739    fInfo.push(SkObjectParser::PaintToString(paint));
740}
741
742DrawVertices::~DrawVertices() {
743    delete [] fVertices;
744    delete [] fTexs;
745    delete [] fColors;
746    SkSafeUnref(fXfermode);
747    delete [] fIndices;
748}
749
750void DrawVertices::execute(SkCanvas* canvas) {
751    canvas->drawVertices(fVmode, fVertexCount, fVertices,
752                         fTexs, fColors, fXfermode, fIndices,
753                         fIndexCount, fPaint);
754}
755
756Restore::Restore() {
757    fDrawType = RESTORE;
758    fInfo.push(SkObjectParser::CustomTextToString("No Parameters"));
759}
760
761void Restore::execute(SkCanvas* canvas) {
762    canvas->restore();
763}
764
765void Restore::trackSaveState(int* state) {
766    (*state)--;
767}
768
769Rotate::Rotate(SkScalar degrees) {
770    fDegrees = degrees;
771    fDrawType = ROTATE;
772
773    fInfo.push(SkObjectParser::ScalarToString(degrees, "SkScalar degrees: "));
774}
775
776void Rotate::execute(SkCanvas* canvas) {
777    canvas->rotate(fDegrees);
778}
779
780Save::Save(SkCanvas::SaveFlags flags) {
781    fFlags = flags;
782    fDrawType = SAVE;
783    fInfo.push(SkObjectParser::SaveFlagsToString(flags));
784}
785
786void Save::execute(SkCanvas* canvas) {
787    canvas->save(fFlags);
788}
789
790void Save::trackSaveState(int* state) {
791    (*state)++;
792}
793
794SaveLayer::SaveLayer(const SkRect* bounds, const SkPaint* paint,
795                     SkCanvas::SaveFlags flags) {
796    if (NULL != bounds) {
797        fBounds = *bounds;
798    } else {
799        fBounds.setEmpty();
800    }
801
802    if (NULL != paint) {
803        fPaint = *paint;
804        fPaintPtr = &fPaint;
805    } else {
806        fPaintPtr = NULL;
807    }
808    fFlags = flags;
809    fDrawType = SAVE_LAYER;
810
811    if (NULL != bounds) {
812        fInfo.push(SkObjectParser::RectToString(*bounds, "Bounds: "));
813    }
814    if (NULL != paint) {
815        fInfo.push(SkObjectParser::PaintToString(*paint));
816    }
817    fInfo.push(SkObjectParser::SaveFlagsToString(flags));
818}
819
820void SaveLayer::execute(SkCanvas* canvas) {
821    canvas->saveLayer(fBounds.isEmpty() ? NULL : &fBounds,
822                      fPaintPtr,
823                      fFlags);
824}
825
826void SaveLayer::trackSaveState(int* state) {
827    (*state)++;
828}
829
830Scale::Scale(SkScalar sx, SkScalar sy) {
831    fSx = sx;
832    fSy = sy;
833    fDrawType = SCALE;
834
835    fInfo.push(SkObjectParser::ScalarToString(sx, "SkScalar sx: "));
836    fInfo.push(SkObjectParser::ScalarToString(sy, "SkScalar sy: "));
837}
838
839void Scale::execute(SkCanvas* canvas) {
840    canvas->scale(fSx, fSy);
841}
842
843SetMatrix::SetMatrix(const SkMatrix& matrix) {
844    fMatrix = matrix;
845    fDrawType = SET_MATRIX;
846
847    fInfo.push(SkObjectParser::MatrixToString(matrix));
848}
849
850void SetMatrix::execute(SkCanvas* canvas) {
851    canvas->setMatrix(fMatrix);
852}
853
854Skew::Skew(SkScalar sx, SkScalar sy) {
855    fSx = sx;
856    fSy = sy;
857    fDrawType = SKEW;
858
859    fInfo.push(SkObjectParser::ScalarToString(sx, "SkScalar sx: "));
860    fInfo.push(SkObjectParser::ScalarToString(sy, "SkScalar sy: "));
861}
862
863void Skew::execute(SkCanvas* canvas) {
864    canvas->skew(fSx, fSy);
865}
866
867Translate::Translate(SkScalar dx, SkScalar dy) {
868    fDx = dx;
869    fDy = dy;
870    fDrawType = TRANSLATE;
871
872    fInfo.push(SkObjectParser::ScalarToString(dx, "SkScalar dx: "));
873    fInfo.push(SkObjectParser::ScalarToString(dy, "SkScalar dy: "));
874}
875
876void Translate::execute(SkCanvas* canvas) {
877    canvas->translate(fDx, fDy);
878}
879