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