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