SkDrawCommand.cpp revision 517dbe8bdc2a4aa3e90b30abae34a02959ba15a7
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
80SkClearCommand::SkClearCommand(SkColor color) {
81    fColor = color;
82    fDrawType = DRAW_CLEAR;
83    fInfo.push(SkObjectParser::CustomTextToString("No Parameters"));
84}
85
86void SkClearCommand::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
176SkClipPathCommand::SkClipPathCommand(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 SkClipPathCommand::execute(SkCanvas* canvas) {
188    canvas->clipPath(fPath, fOp, fDoAA);
189}
190
191bool SkClipPathCommand::render(SkCanvas* canvas) const {
192    render_path(canvas, fPath);
193    return true;
194}
195
196SkClipRegionCommand::SkClipRegionCommand(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 SkClipRegionCommand::execute(SkCanvas* canvas) {
206    canvas->clipRegion(fRegion, fOp);
207}
208
209SkClipRectCommand::SkClipRectCommand(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 SkClipRectCommand::execute(SkCanvas* canvas) {
221    canvas->clipRect(fRect, fOp, fDoAA);
222}
223
224SkClipRRectCommand::SkClipRRectCommand(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 SkClipRRectCommand::execute(SkCanvas* canvas) {
236    canvas->clipRRect(fRRect, fOp, fDoAA);
237}
238
239bool SkClipRRectCommand::render(SkCanvas* canvas) const {
240    render_rrect(canvas, fRRect);
241    return true;
242}
243
244SkConcatCommand::SkConcatCommand(const SkMatrix& matrix) {
245    fMatrix = matrix;
246    fDrawType = CONCAT;
247
248    fInfo.push(SkObjectParser::MatrixToString(matrix));
249}
250
251void SkConcatCommand::execute(SkCanvas* canvas) {
252    canvas->concat(fMatrix);
253}
254
255SkDrawBitmapCommand::SkDrawBitmapCommand(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 SkDrawBitmapCommand::execute(SkCanvas* canvas) {
277    canvas->drawBitmap(fBitmap, fLeft, fTop, fPaintPtr);
278}
279
280bool SkDrawBitmapCommand::render(SkCanvas* canvas) const {
281    render_bitmap(canvas, fBitmap);
282    return true;
283}
284
285SkDrawBitmapMatrixCommand::SkDrawBitmapMatrixCommand(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 SkDrawBitmapMatrixCommand::execute(SkCanvas* canvas) {
306    canvas->drawBitmapMatrix(fBitmap, fMatrix, fPaintPtr);
307}
308
309bool SkDrawBitmapMatrixCommand::render(SkCanvas* canvas) const {
310    render_bitmap(canvas, fBitmap);
311    return true;
312}
313
314SkDrawBitmapNineCommand::SkDrawBitmapNineCommand(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 SkDrawBitmapNineCommand::execute(SkCanvas* canvas) {
336    canvas->drawBitmapNine(fBitmap, fCenter, fDst, fPaintPtr);
337}
338
339bool SkDrawBitmapNineCommand::render(SkCanvas* canvas) const {
340    render_bitmap(canvas, fBitmap);
341    return true;
342}
343
344SkDrawBitmapRectCommand::SkDrawBitmapRectCommand(const SkBitmap& bitmap, const SkRect* src,
345                                                 const SkRect& dst, const SkPaint* paint,
346                                                 SkCanvas::DrawBitmapRectFlags flags) {
347    fBitmap = bitmap;
348    if (NULL != src) {
349        fSrc = *src;
350    } else {
351        fSrc.setEmpty();
352    }
353    fDst = dst;
354
355    if (NULL != paint) {
356        fPaint = *paint;
357        fPaintPtr = &fPaint;
358    } else {
359        fPaintPtr = NULL;
360    }
361    fFlags = flags;
362
363    fDrawType = DRAW_BITMAP_RECT_TO_RECT;
364
365    fInfo.push(SkObjectParser::BitmapToString(bitmap));
366    if (NULL != src) {
367        fInfo.push(SkObjectParser::RectToString(*src, "Src: "));
368    }
369    fInfo.push(SkObjectParser::RectToString(dst, "Dst: "));
370    if (NULL != paint) {
371        fInfo.push(SkObjectParser::PaintToString(*paint));
372    }
373    fInfo.push(SkObjectParser::IntToString(fFlags, "Flags: "));
374}
375
376void SkDrawBitmapRectCommand::execute(SkCanvas* canvas) {
377    canvas->drawBitmapRectToRect(fBitmap, this->srcRect(), fDst, fPaintPtr, fFlags);
378}
379
380bool SkDrawBitmapRectCommand::render(SkCanvas* canvas) const {
381    render_bitmap(canvas, fBitmap, this->srcRect());
382    return true;
383}
384
385SkDrawDataCommand::SkDrawDataCommand(const void* data, size_t length) {
386    fData = new char[length];
387    memcpy(fData, data, length);
388    fLength = length;
389    fDrawType = DRAW_DATA;
390
391    // TODO: add display of actual data?
392    SkString* str = new SkString;
393    str->appendf("length: %d", (int) length);
394    fInfo.push(str);
395}
396
397void SkDrawDataCommand::execute(SkCanvas* canvas) {
398    canvas->drawData(fData, fLength);
399}
400
401SkBeginCommentGroupCommand::SkBeginCommentGroupCommand(const char* description)
402    : INHERITED(BEGIN_COMMENT_GROUP)
403    , fDescription(description) {
404    SkString* temp = new SkString;
405    temp->appendf("Description: %s", description);
406    fInfo.push(temp);
407}
408
409SkCommentCommand::SkCommentCommand(const char* kywd, const char* value)
410    : INHERITED(COMMENT)
411    , fKywd(kywd)
412    , fValue(value) {
413    SkString* temp = new SkString;
414    temp->appendf("%s: %s", kywd, value);
415    fInfo.push(temp);
416}
417
418SkEndCommentGroupCommand::SkEndCommentGroupCommand() : INHERITED(END_COMMENT_GROUP) {
419}
420
421SkDrawOvalCommand::SkDrawOvalCommand(const SkRect& oval, const SkPaint& paint) {
422    fOval = oval;
423    fPaint = paint;
424    fDrawType = DRAW_OVAL;
425
426    fInfo.push(SkObjectParser::RectToString(oval));
427    fInfo.push(SkObjectParser::PaintToString(paint));
428}
429
430void SkDrawOvalCommand::execute(SkCanvas* canvas) {
431    canvas->drawOval(fOval, fPaint);
432}
433
434bool SkDrawOvalCommand::render(SkCanvas* canvas) const {
435    canvas->clear(0xFFFFFFFF);
436    canvas->save();
437
438    xlate_and_scale_to_bounds(canvas, fOval);
439
440    SkPaint p;
441    p.setColor(SK_ColorBLACK);
442    p.setStyle(SkPaint::kStroke_Style);
443
444    canvas->drawOval(fOval, p);
445    canvas->restore();
446
447    return true;
448}
449
450SkDrawPaintCommand::SkDrawPaintCommand(const SkPaint& paint) {
451    fPaint = paint;
452    fDrawType = DRAW_PAINT;
453
454    fInfo.push(SkObjectParser::PaintToString(paint));
455}
456
457void SkDrawPaintCommand::execute(SkCanvas* canvas) {
458    canvas->drawPaint(fPaint);
459}
460
461bool SkDrawPaintCommand::render(SkCanvas* canvas) const {
462    canvas->clear(0xFFFFFFFF);
463    canvas->drawPaint(fPaint);
464    return true;
465}
466
467SkDrawPathCommand::SkDrawPathCommand(const SkPath& path, const SkPaint& paint) {
468    fPath = path;
469    fPaint = paint;
470    fDrawType = DRAW_PATH;
471
472    fInfo.push(SkObjectParser::PathToString(path));
473    fInfo.push(SkObjectParser::PaintToString(paint));
474}
475
476void SkDrawPathCommand::execute(SkCanvas* canvas) {
477    canvas->drawPath(fPath, fPaint);
478}
479
480bool SkDrawPathCommand::render(SkCanvas* canvas) const {
481    render_path(canvas, fPath);
482    return true;
483}
484
485SkDrawPictureCommand::SkDrawPictureCommand(SkPicture& picture) :
486    fPicture(picture) {
487    fDrawType = DRAW_PICTURE;
488    SkString* temp = new SkString;
489    temp->appendf("SkPicture: W: %d H: %d", picture.width(), picture.height());
490    fInfo.push(temp);
491}
492
493void SkDrawPictureCommand::execute(SkCanvas* canvas) {
494    canvas->drawPicture(fPicture);
495}
496
497bool SkDrawPictureCommand::render(SkCanvas* canvas) const {
498    canvas->clear(0xFFFFFFFF);
499    canvas->save();
500
501    SkRect bounds = SkRect::MakeWH(SkIntToScalar(fPicture.width()),
502                                   SkIntToScalar(fPicture.height()));
503    xlate_and_scale_to_bounds(canvas, bounds);
504
505    canvas->drawPicture(const_cast<SkPicture&>(fPicture));
506
507    canvas->restore();
508
509    return true;
510}
511
512SkDrawPointsCommand::SkDrawPointsCommand(SkCanvas::PointMode mode, size_t count,
513                                         const SkPoint pts[], const SkPaint& paint) {
514    fMode = mode;
515    fCount = count;
516    fPts = new SkPoint[count];
517    memcpy(fPts, pts, count * sizeof(SkPoint));
518    fPaint = paint;
519    fDrawType = DRAW_POINTS;
520
521    fInfo.push(SkObjectParser::PointsToString(pts, count));
522    fInfo.push(SkObjectParser::ScalarToString(SkIntToScalar((unsigned int)count),
523                                              "Points: "));
524    fInfo.push(SkObjectParser::PointModeToString(mode));
525    fInfo.push(SkObjectParser::PaintToString(paint));
526}
527
528void SkDrawPointsCommand::execute(SkCanvas* canvas) {
529    canvas->drawPoints(fMode, fCount, fPts, fPaint);
530}
531
532bool SkDrawPointsCommand::render(SkCanvas* canvas) const {
533    canvas->clear(0xFFFFFFFF);
534    canvas->save();
535
536    SkRect bounds;
537
538    bounds.setEmpty();
539    for (unsigned int i = 0; i < fCount; ++i) {
540        bounds.growToInclude(fPts[i].fX, fPts[i].fY);
541    }
542
543    xlate_and_scale_to_bounds(canvas, bounds);
544
545    SkPaint p;
546    p.setColor(SK_ColorBLACK);
547    p.setStyle(SkPaint::kStroke_Style);
548
549    canvas->drawPoints(fMode, fCount, fPts, p);
550    canvas->restore();
551
552    return true;
553}
554
555SkDrawPosTextCommand::SkDrawPosTextCommand(const void* text, size_t byteLength,
556                                           const SkPoint pos[], const SkPaint& paint) {
557    size_t numPts = paint.countText(text, byteLength);
558
559    fText = new char[byteLength];
560    memcpy(fText, text, byteLength);
561    fByteLength = byteLength;
562
563    fPos = new SkPoint[numPts];
564    memcpy(fPos, pos, numPts * sizeof(SkPoint));
565
566    fPaint = paint;
567    fDrawType = DRAW_POS_TEXT;
568
569    fInfo.push(SkObjectParser::TextToString(text, byteLength, paint.getTextEncoding()));
570    // TODO(chudy): Test that this works.
571    fInfo.push(SkObjectParser::PointsToString(pos, 1));
572    fInfo.push(SkObjectParser::PaintToString(paint));
573}
574
575void SkDrawPosTextCommand::execute(SkCanvas* canvas) {
576    canvas->drawPosText(fText, fByteLength, fPos, fPaint);
577}
578
579
580SkDrawPosTextHCommand::SkDrawPosTextHCommand(const void* text, size_t byteLength,
581                                             const SkScalar xpos[], SkScalar constY,
582                                             const SkPaint& paint) {
583    size_t numPts = paint.countText(text, byteLength);
584
585    fText = new char[byteLength];
586    memcpy(fText, text, byteLength);
587    fByteLength = byteLength;
588
589    fXpos = new SkScalar[numPts];
590    memcpy(fXpos, xpos, numPts * sizeof(SkScalar));
591
592    fConstY = constY;
593    fPaint = paint;
594    fDrawType = DRAW_POS_TEXT_H;
595
596    fInfo.push(SkObjectParser::TextToString(text, byteLength, paint.getTextEncoding()));
597    fInfo.push(SkObjectParser::ScalarToString(xpos[0], "XPOS: "));
598    fInfo.push(SkObjectParser::ScalarToString(constY, "SkScalar constY: "));
599    fInfo.push(SkObjectParser::PaintToString(paint));
600}
601
602void SkDrawPosTextHCommand::execute(SkCanvas* canvas) {
603    canvas->drawPosTextH(fText, fByteLength, fXpos, fConstY, fPaint);
604}
605
606SkDrawRectCommand::SkDrawRectCommand(const SkRect& rect, const SkPaint& paint) {
607    fRect = rect;
608    fPaint = paint;
609    fDrawType = DRAW_RECT;
610
611    fInfo.push(SkObjectParser::RectToString(rect));
612    fInfo.push(SkObjectParser::PaintToString(paint));
613}
614
615void SkDrawRectCommand::execute(SkCanvas* canvas) {
616    canvas->drawRect(fRect, fPaint);
617}
618
619SkDrawRRectCommand::SkDrawRRectCommand(const SkRRect& rrect, const SkPaint& paint) {
620    fRRect = rrect;
621    fPaint = paint;
622    fDrawType = DRAW_RRECT;
623
624    fInfo.push(SkObjectParser::RRectToString(rrect));
625    fInfo.push(SkObjectParser::PaintToString(paint));
626}
627
628void SkDrawRRectCommand::execute(SkCanvas* canvas) {
629    canvas->drawRRect(fRRect, fPaint);
630}
631
632bool SkDrawRRectCommand::render(SkCanvas* canvas) const {
633    render_rrect(canvas, fRRect);
634    return true;
635}
636
637SkDrawSpriteCommand::SkDrawSpriteCommand(const SkBitmap& bitmap, int left, int top,
638                                         const SkPaint* paint) {
639    fBitmap = bitmap;
640    fLeft = left;
641    fTop = top;
642    if (NULL != paint) {
643        fPaint = *paint;
644        fPaintPtr = &fPaint;
645    } else {
646        fPaintPtr = NULL;
647    }
648    fDrawType = DRAW_SPRITE;
649
650    fInfo.push(SkObjectParser::BitmapToString(bitmap));
651    fInfo.push(SkObjectParser::IntToString(left, "Left: "));
652    fInfo.push(SkObjectParser::IntToString(top, "Top: "));
653    if (NULL != paint) {
654        fInfo.push(SkObjectParser::PaintToString(*paint));
655    }
656}
657
658void SkDrawSpriteCommand::execute(SkCanvas* canvas) {
659    canvas->drawSprite(fBitmap, fLeft, fTop, fPaintPtr);
660}
661
662bool SkDrawSpriteCommand::render(SkCanvas* canvas) const {
663    render_bitmap(canvas, fBitmap);
664    return true;
665}
666
667SkDrawTextCommand::SkDrawTextCommand(const void* text, size_t byteLength, SkScalar x, SkScalar y,
668                                     const SkPaint& paint) {
669    fText = new char[byteLength];
670    memcpy(fText, text, byteLength);
671    fByteLength = byteLength;
672    fX = x;
673    fY = y;
674    fPaint = paint;
675    fDrawType = DRAW_TEXT;
676
677    fInfo.push(SkObjectParser::TextToString(text, byteLength, paint.getTextEncoding()));
678    fInfo.push(SkObjectParser::ScalarToString(x, "SkScalar x: "));
679    fInfo.push(SkObjectParser::ScalarToString(y, "SkScalar y: "));
680    fInfo.push(SkObjectParser::PaintToString(paint));
681}
682
683void SkDrawTextCommand::execute(SkCanvas* canvas) {
684    canvas->drawText(fText, fByteLength, fX, fY, fPaint);
685}
686
687SkDrawTextOnPathCommand::SkDrawTextOnPathCommand(const void* text, size_t byteLength,
688                                                 const SkPath& path, const SkMatrix* matrix,
689                                                 const SkPaint& paint) {
690    fText = new char[byteLength];
691    memcpy(fText, text, byteLength);
692    fByteLength = byteLength;
693    fPath = path;
694    if (NULL != matrix) {
695        fMatrix = *matrix;
696    } else {
697        fMatrix.setIdentity();
698    }
699    fPaint = paint;
700    fDrawType = DRAW_TEXT_ON_PATH;
701
702    fInfo.push(SkObjectParser::TextToString(text, byteLength, paint.getTextEncoding()));
703    fInfo.push(SkObjectParser::PathToString(path));
704    if (NULL != matrix) {
705        fInfo.push(SkObjectParser::MatrixToString(*matrix));
706    }
707    fInfo.push(SkObjectParser::PaintToString(paint));
708}
709
710void SkDrawTextOnPathCommand::execute(SkCanvas* canvas) {
711    canvas->drawTextOnPath(fText, fByteLength, fPath,
712                           fMatrix.isIdentity() ? NULL : &fMatrix,
713                           fPaint);
714}
715
716SkDrawVerticesCommand::SkDrawVerticesCommand(SkCanvas::VertexMode vmode, int vertexCount,
717                                             const SkPoint vertices[], const SkPoint texs[],
718                                             const SkColor colors[], SkXfermode* xfermode,
719                                             const uint16_t indices[], int indexCount,
720                                             const SkPaint& paint) {
721    fVmode = vmode;
722
723    fVertexCount = vertexCount;
724
725    fVertices = new SkPoint[vertexCount];
726    memcpy(fVertices, vertices, vertexCount * sizeof(SkPoint));
727
728    if (NULL != texs) {
729        fTexs = new SkPoint[vertexCount];
730        memcpy(fTexs, texs, vertexCount * sizeof(SkPoint));
731    } else {
732        fTexs = NULL;
733    }
734
735    if (NULL != colors) {
736        fColors = new SkColor[vertexCount];
737        memcpy(fColors, colors, vertexCount * sizeof(SkColor));
738    } else {
739        fColors = NULL;
740    }
741
742    fXfermode = xfermode;
743    if (NULL != fXfermode) {
744        fXfermode->ref();
745    }
746
747    if (indexCount > 0) {
748        fIndices = new uint16_t[indexCount];
749        memcpy(fIndices, indices, indexCount * sizeof(uint16_t));
750    } else {
751        fIndices = NULL;
752    }
753
754    fIndexCount = indexCount;
755    fPaint = paint;
756    fDrawType = DRAW_VERTICES;
757
758    // TODO(chudy)
759    fInfo.push(SkObjectParser::CustomTextToString("To be implemented."));
760    fInfo.push(SkObjectParser::PaintToString(paint));
761}
762
763SkDrawVerticesCommand::~SkDrawVerticesCommand() {
764    delete [] fVertices;
765    delete [] fTexs;
766    delete [] fColors;
767    SkSafeUnref(fXfermode);
768    delete [] fIndices;
769}
770
771void SkDrawVerticesCommand::execute(SkCanvas* canvas) {
772    canvas->drawVertices(fVmode, fVertexCount, fVertices,
773                         fTexs, fColors, fXfermode, fIndices,
774                         fIndexCount, fPaint);
775}
776
777SkRestoreCommand::SkRestoreCommand() {
778    fDrawType = RESTORE;
779    fInfo.push(SkObjectParser::CustomTextToString("No Parameters"));
780}
781
782void SkRestoreCommand::execute(SkCanvas* canvas) {
783    canvas->restore();
784}
785
786void SkRestoreCommand::trackSaveState(int* state) {
787    (*state)--;
788}
789
790SkRotateCommand::SkRotateCommand(SkScalar degrees) {
791    fDegrees = degrees;
792    fDrawType = ROTATE;
793
794    fInfo.push(SkObjectParser::ScalarToString(degrees, "SkScalar degrees: "));
795}
796
797void SkRotateCommand::execute(SkCanvas* canvas) {
798    canvas->rotate(fDegrees);
799}
800
801SkSaveCommand::SkSaveCommand(SkCanvas::SaveFlags flags) {
802    fFlags = flags;
803    fDrawType = SAVE;
804    fInfo.push(SkObjectParser::SaveFlagsToString(flags));
805}
806
807void SkSaveCommand::execute(SkCanvas* canvas) {
808    canvas->save(fFlags);
809}
810
811void SkSaveCommand::trackSaveState(int* state) {
812    (*state)++;
813}
814
815SkSaveLayerCommand::SkSaveLayerCommand(const SkRect* bounds, const SkPaint* paint,
816                                       SkCanvas::SaveFlags flags) {
817    if (NULL != bounds) {
818        fBounds = *bounds;
819    } else {
820        fBounds.setEmpty();
821    }
822
823    if (NULL != paint) {
824        fPaint = *paint;
825        fPaintPtr = &fPaint;
826    } else {
827        fPaintPtr = NULL;
828    }
829    fFlags = flags;
830    fDrawType = SAVE_LAYER;
831
832    if (NULL != bounds) {
833        fInfo.push(SkObjectParser::RectToString(*bounds, "Bounds: "));
834    }
835    if (NULL != paint) {
836        fInfo.push(SkObjectParser::PaintToString(*paint));
837    }
838    fInfo.push(SkObjectParser::SaveFlagsToString(flags));
839}
840
841void SkSaveLayerCommand::execute(SkCanvas* canvas) {
842    canvas->saveLayer(fBounds.isEmpty() ? NULL : &fBounds,
843                      fPaintPtr,
844                      fFlags);
845}
846
847void SkSaveLayerCommand::trackSaveState(int* state) {
848    (*state)++;
849}
850
851SkScaleCommand::SkScaleCommand(SkScalar sx, SkScalar sy) {
852    fSx = sx;
853    fSy = sy;
854    fDrawType = SCALE;
855
856    fInfo.push(SkObjectParser::ScalarToString(sx, "SkScalar sx: "));
857    fInfo.push(SkObjectParser::ScalarToString(sy, "SkScalar sy: "));
858}
859
860void SkScaleCommand::execute(SkCanvas* canvas) {
861    canvas->scale(fSx, fSy);
862}
863
864SkSetMatrixCommand::SkSetMatrixCommand(const SkMatrix& matrix) {
865    fMatrix = matrix;
866    fDrawType = SET_MATRIX;
867
868    fInfo.push(SkObjectParser::MatrixToString(matrix));
869}
870
871void SkSetMatrixCommand::execute(SkCanvas* canvas) {
872    canvas->setMatrix(fMatrix);
873}
874
875SkSkewCommand::SkSkewCommand(SkScalar sx, SkScalar sy) {
876    fSx = sx;
877    fSy = sy;
878    fDrawType = SKEW;
879
880    fInfo.push(SkObjectParser::ScalarToString(sx, "SkScalar sx: "));
881    fInfo.push(SkObjectParser::ScalarToString(sy, "SkScalar sy: "));
882}
883
884void SkSkewCommand::execute(SkCanvas* canvas) {
885    canvas->skew(fSx, fSy);
886}
887
888SkTranslateCommand::SkTranslateCommand(SkScalar dx, SkScalar dy) {
889    fDx = dx;
890    fDy = dy;
891    fDrawType = TRANSLATE;
892
893    fInfo.push(SkObjectParser::ScalarToString(dx, "SkScalar dx: "));
894    fInfo.push(SkObjectParser::ScalarToString(dy, "SkScalar dy: "));
895}
896
897void SkTranslateCommand::execute(SkCanvas* canvas) {
898    canvas->translate(fDx, fDy);
899}
900