1 /*
2  * Copyright 2016 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "SkJSONRenderer.h"
9 
10 #include "SkBlurMaskFilter.h"
11 #include "SkDashPathEffect.h"
12 #include "SkJSONCanvas.h"
13 #include "SkJSONCPP.h"
14 #include "SkPath.h"
15 #include "SkTextBlob.h"
16 #include "SkTypeface.h"
17 #include "SkValidatingReadBuffer.h"
18 
19 namespace SkJSONRenderer {
20 
21 class Renderer {
22 public:
23     void getPaint(Json::Value& paint, SkPaint* result);
24 
25     void getRect(Json::Value& rect, SkRect* result);
26 
27     void getRRect(Json::Value& rrect, SkRRect* result);
28 
29     void getPath(Json::Value& path, SkPath* result);
30 
31     void getMatrix(Json::Value& matrix, SkMatrix* result);
32 
33     SkRegion::Op getRegionOp(Json::Value& op);
34 
35     void processCommand(Json::Value& command, SkCanvas* target);
36 
37     void processTranslate(Json::Value& command, SkCanvas* target);
38 
39     void processScale(Json::Value& command, SkCanvas* target);
40 
41     void processMatrix(Json::Value& command, SkCanvas* target);
42 
43     void processSave(Json::Value& command, SkCanvas* target);
44 
45     void processRestore(Json::Value& command, SkCanvas* target);
46 
47     void processSaveLayer(Json::Value& command, SkCanvas* target);
48 
49     void processPaint(Json::Value& command, SkCanvas* target);
50 
51     void processRect(Json::Value& command, SkCanvas* target);
52 
53     void processRRect(Json::Value& command, SkCanvas* target);
54 
55     void processOval(Json::Value& command, SkCanvas* target);
56 
57     void processPath(Json::Value& command, SkCanvas* target);
58 
59     void processText(Json::Value& command, SkCanvas* target);
60 
61     void processPosText(Json::Value& command, SkCanvas* target);
62 
63     void processTextOnPath(Json::Value& command, SkCanvas* target);
64 
65     void processTextBlob(Json::Value& command, SkCanvas* target);
66 
67     void processPoints(Json::Value& command, SkCanvas* target);
68 
69     void processImage(Json::Value& command, SkCanvas* target);
70 
71     void processImageRect(Json::Value& command, SkCanvas* target);
72 
73     void processBitmap(Json::Value& command, SkCanvas* target);
74 
75     void processBitmapRect(Json::Value& command, SkCanvas* target);
76 
77     void processClipRect(Json::Value& command, SkCanvas* target);
78 
79     void processClipRRect(Json::Value& command, SkCanvas* target);
80 
81     void processClipPath(Json::Value& command, SkCanvas* target);
82 };
83 
processCommand(Json::Value & command,SkCanvas * target)84 void Renderer::processCommand(Json::Value& command, SkCanvas* target) {
85     const char* name = command[SKJSONCANVAS_COMMAND].asCString();
86     // TODO speed this up with a hash
87     if (!strcmp(name, SKJSONCANVAS_COMMAND_TRANSLATE)) {
88         this->processTranslate(command, target);
89     }
90     else if (!strcmp(name, SKJSONCANVAS_COMMAND_SCALE)) {
91         this->processScale(command, target);
92     }
93     else if (!strcmp(name, SKJSONCANVAS_COMMAND_MATRIX)) {
94         this->processMatrix(command, target);
95     }
96     else if (!strcmp(name, SKJSONCANVAS_COMMAND_SAVE)) {
97         this->processSave(command, target);
98     }
99     else if (!strcmp(name, SKJSONCANVAS_COMMAND_RESTORE)) {
100         this->processRestore(command, target);
101     }
102     else if (!strcmp(name, SKJSONCANVAS_COMMAND_SAVELAYER)) {
103         this->processSaveLayer(command, target);
104     }
105     else if (!strcmp(name, SKJSONCANVAS_COMMAND_PAINT)) {
106         this->processPaint(command, target);
107     }
108     else if (!strcmp(name, SKJSONCANVAS_COMMAND_RECT)) {
109         this->processRect(command, target);
110     }
111     else if (!strcmp(name, SKJSONCANVAS_COMMAND_RRECT)) {
112         this->processRRect(command, target);
113     }
114     else if (!strcmp(name, SKJSONCANVAS_COMMAND_OVAL)) {
115         this->processOval(command, target);
116     }
117     else if (!strcmp(name, SKJSONCANVAS_COMMAND_PATH)) {
118         this->processPath(command, target);
119     }
120     else if (!strcmp(name, SKJSONCANVAS_COMMAND_TEXT)) {
121         this->processText(command, target);
122     }
123     else if (!strcmp(name, SKJSONCANVAS_COMMAND_POSTEXT)) {
124         this->processPosText(command, target);
125     }
126     else if (!strcmp(name, SKJSONCANVAS_COMMAND_TEXTONPATH)) {
127         this->processTextOnPath(command, target);
128     }
129     else if (!strcmp(name, SKJSONCANVAS_COMMAND_TEXTBLOB)) {
130         this->processTextBlob(command, target);
131     }
132     else if (!strcmp(name, SKJSONCANVAS_COMMAND_POINTS)) {
133         this->processPoints(command, target);
134     }
135     else if (!strcmp(name, SKJSONCANVAS_COMMAND_IMAGE)) {
136         this->processImage(command, target);
137     }
138     else if (!strcmp(name, SKJSONCANVAS_COMMAND_IMAGERECT)) {
139         this->processImageRect(command, target);
140     }
141     else if (!strcmp(name, SKJSONCANVAS_COMMAND_BITMAP)) {
142         this->processBitmap(command, target);
143     }
144     else if (!strcmp(name, SKJSONCANVAS_COMMAND_BITMAPRECT)) {
145         this->processBitmapRect(command, target);
146     }
147     else if (!strcmp(name, SKJSONCANVAS_COMMAND_CLIPRECT)) {
148         this->processClipRect(command, target);
149     }
150     else if (!strcmp(name, SKJSONCANVAS_COMMAND_CLIPRRECT)) {
151         this->processClipRRect(command, target);
152     }
153     else if (!strcmp(name, SKJSONCANVAS_COMMAND_CLIPPATH)) {
154         this->processClipPath(command, target);
155     }
156     else {
157         SkDebugf("unsupported JSON command: %s\n", name);
158     }
159 }
160 
apply_paint_color(Json::Value & jsonPaint,SkPaint * target)161 static void apply_paint_color(Json::Value& jsonPaint, SkPaint* target) {
162     if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_COLOR)) {
163         Json::Value color = jsonPaint[SKJSONCANVAS_ATTRIBUTE_COLOR];
164         target->setColor(SkColorSetARGB(color[0].asInt(), color[1].asInt(), color[2].asInt(),
165                          color[3].asInt()));
166     }
167 }
168 
169 // note that the caller is responsible for freeing the pointer
decode_data(Json::Value bytes,void ** target)170 static Json::ArrayIndex decode_data(Json::Value bytes, void** target) {
171     Json::ArrayIndex size = bytes.size();
172     *target = sk_malloc_throw(size);
173     for (Json::ArrayIndex i = 0; i < size; i++) {
174         ((uint8_t*) *target)[i] = bytes[i].asInt();
175     }
176     return size;
177 }
178 
load_flattenable(Json::Value jsonFlattenable)179 static SkFlattenable* load_flattenable(Json::Value jsonFlattenable) {
180     if (!jsonFlattenable.isMember(SKJSONCANVAS_ATTRIBUTE_NAME)) {
181         return nullptr;
182     }
183     const char* name = jsonFlattenable[SKJSONCANVAS_ATTRIBUTE_NAME].asCString();
184     SkFlattenable::Factory factory = SkFlattenable::NameToFactory(name);
185     if (factory == nullptr) {
186         SkDebugf("no factory for loading '%s'\n", name);
187         return nullptr;
188     }
189     void* data;
190     int size = decode_data(jsonFlattenable[SKJSONCANVAS_ATTRIBUTE_BYTES], &data);
191     SkValidatingReadBuffer buffer(data, size);
192     SkFlattenable* result = factory(buffer);
193     free(data);
194     if (!buffer.isValid()) {
195         SkDebugf("invalid buffer loading flattenable\n");
196         return nullptr;
197     }
198     return result;
199 }
200 
colortype_from_name(const char * name)201 static SkColorType colortype_from_name(const char* name) {
202     if (!strcmp(name, SKJSONCANVAS_COLORTYPE_ARGB4444)) {
203         return kARGB_4444_SkColorType;
204     }
205     else if (!strcmp(name, SKJSONCANVAS_COLORTYPE_RGBA8888)) {
206         return kRGBA_8888_SkColorType;
207     }
208     else if (!strcmp(name, SKJSONCANVAS_COLORTYPE_BGRA8888)) {
209         return kBGRA_8888_SkColorType;
210     }
211     else if (!strcmp(name, SKJSONCANVAS_COLORTYPE_565)) {
212         return kRGB_565_SkColorType;
213     }
214     else if (!strcmp(name, SKJSONCANVAS_COLORTYPE_GRAY8)) {
215         return kGray_8_SkColorType;
216     }
217     else if (!strcmp(name, SKJSONCANVAS_COLORTYPE_INDEX8)) {
218         return kIndex_8_SkColorType;
219     }
220     else if (!strcmp(name, SKJSONCANVAS_COLORTYPE_ALPHA8)) {
221         return kAlpha_8_SkColorType;
222     }
223     SkASSERT(false);
224     return kN32_SkColorType;
225 }
226 
convert_colortype(SkBitmap * bitmap,SkColorType colorType)227 static SkBitmap* convert_colortype(SkBitmap* bitmap, SkColorType colorType) {
228     if (bitmap->colorType() == colorType  ) {
229         return bitmap;
230     }
231     SkBitmap* dst = new SkBitmap();
232     if (bitmap->copyTo(dst, colorType)) {
233         delete bitmap;
234         return dst;
235     }
236     SkASSERT(false);
237     delete dst;
238     return bitmap;
239 }
240 
241 // caller is responsible for freeing return value
load_bitmap(const Json::Value & jsonBitmap)242 static SkBitmap* load_bitmap(const Json::Value& jsonBitmap) {
243     if (!jsonBitmap.isMember(SKJSONCANVAS_ATTRIBUTE_BYTES)) {
244         SkDebugf("invalid bitmap\n");
245         return nullptr;
246     }
247     void* data;
248     int size = decode_data(jsonBitmap[SKJSONCANVAS_ATTRIBUTE_BYTES], &data);
249     SkMemoryStream stream(data, size);
250     SkImageDecoder* decoder = SkImageDecoder::Factory(&stream);
251     SkBitmap* bitmap = new SkBitmap();
252     SkImageDecoder::Result result = decoder->decode(&stream, bitmap,
253                                                     SkImageDecoder::kDecodePixels_Mode);
254     free(decoder);
255     if (result != SkImageDecoder::kFailure) {
256         free(data);
257         if (jsonBitmap.isMember(SKJSONCANVAS_ATTRIBUTE_COLOR)) {
258             const char* ctName = jsonBitmap[SKJSONCANVAS_ATTRIBUTE_COLOR].asCString();
259             SkColorType ct = colortype_from_name(ctName);
260             if (ct != kIndex_8_SkColorType) {
261                 bitmap = convert_colortype(bitmap, ct);
262             }
263         }
264         return bitmap;
265     }
266     SkDebugf("image decode failed\n");
267     free(data);
268     return nullptr;
269 }
270 
load_image(const Json::Value & jsonImage)271 static SkImage* load_image(const Json::Value& jsonImage) {
272     SkBitmap* bitmap = load_bitmap(jsonImage);
273     if (bitmap == nullptr) {
274         return nullptr;
275     }
276     SkImage* result = SkImage::NewFromBitmap(*bitmap);
277     delete bitmap;
278     return result;
279 }
280 
apply_paint_shader(Json::Value & jsonPaint,SkPaint * target)281 static void apply_paint_shader(Json::Value& jsonPaint, SkPaint* target) {
282     if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_SHADER)) {
283         Json::Value jsonShader = jsonPaint[SKJSONCANVAS_ATTRIBUTE_SHADER];
284         SkShader* shader = (SkShader*) load_flattenable(jsonShader);
285         if (shader != nullptr) {
286             target->setShader(shader);
287             shader->unref();
288         }
289     }
290 }
291 
apply_paint_patheffect(Json::Value & jsonPaint,SkPaint * target)292 static void apply_paint_patheffect(Json::Value& jsonPaint, SkPaint* target) {
293     if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_PATHEFFECT)) {
294         Json::Value jsonPathEffect = jsonPaint[SKJSONCANVAS_ATTRIBUTE_PATHEFFECT];
295         SkPathEffect* pathEffect = (SkPathEffect*) load_flattenable(jsonPathEffect);
296         if (pathEffect != nullptr) {
297             target->setPathEffect(pathEffect);
298             pathEffect->unref();
299         }
300     }
301 }
302 
apply_paint_maskfilter(Json::Value & jsonPaint,SkPaint * target)303 static void apply_paint_maskfilter(Json::Value& jsonPaint, SkPaint* target) {
304     if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_MASKFILTER)) {
305         Json::Value jsonMaskFilter = jsonPaint[SKJSONCANVAS_ATTRIBUTE_MASKFILTER];
306         SkMaskFilter* maskFilter = (SkMaskFilter*) load_flattenable(jsonMaskFilter);
307         if (maskFilter != nullptr) {
308             target->setMaskFilter(maskFilter);
309             maskFilter->unref();
310         }
311     }
312 }
313 
apply_paint_colorfilter(Json::Value & jsonPaint,SkPaint * target)314 static void apply_paint_colorfilter(Json::Value& jsonPaint, SkPaint* target) {
315     if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_COLORFILTER)) {
316         Json::Value jsonColorFilter = jsonPaint[SKJSONCANVAS_ATTRIBUTE_COLORFILTER];
317         SkColorFilter* colorFilter = (SkColorFilter*) load_flattenable(jsonColorFilter);
318         if (colorFilter != nullptr) {
319             target->setColorFilter(colorFilter);
320             colorFilter->unref();
321         }
322     }
323 }
324 
apply_paint_xfermode(Json::Value & jsonPaint,SkPaint * target)325 static void apply_paint_xfermode(Json::Value& jsonPaint, SkPaint* target) {
326     if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_XFERMODE)) {
327         Json::Value jsonXfermode = jsonPaint[SKJSONCANVAS_ATTRIBUTE_XFERMODE];
328         SkXfermode* xfermode = (SkXfermode*) load_flattenable(jsonXfermode);
329         if (xfermode != nullptr) {
330             target->setXfermode(xfermode);
331             xfermode->unref();
332         }
333     }
334 }
335 
apply_paint_imagefilter(Json::Value & jsonPaint,SkPaint * target)336 static void apply_paint_imagefilter(Json::Value& jsonPaint, SkPaint* target) {
337     if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_IMAGEFILTER)) {
338         Json::Value jsonImageFilter = jsonPaint[SKJSONCANVAS_ATTRIBUTE_IMAGEFILTER];
339         SkImageFilter* imageFilter = (SkImageFilter*) load_flattenable(jsonImageFilter);
340         if (imageFilter != nullptr) {
341             target->setImageFilter(imageFilter);
342             imageFilter->unref();
343         }
344     }
345 }
346 
apply_paint_style(Json::Value & jsonPaint,SkPaint * target)347 static void apply_paint_style(Json::Value& jsonPaint, SkPaint* target) {
348     if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_STYLE)) {
349         const char* style = jsonPaint[SKJSONCANVAS_ATTRIBUTE_STYLE].asCString();
350         if (!strcmp(style, SKJSONCANVAS_STYLE_FILL)) {
351             target->setStyle(SkPaint::kFill_Style);
352         }
353         else if (!strcmp(style, SKJSONCANVAS_STYLE_STROKE)) {
354             target->setStyle(SkPaint::kStroke_Style);
355         }
356         else if (!strcmp(style, SKJSONCANVAS_STYLE_STROKEANDFILL)) {
357             target->setStyle(SkPaint::kStrokeAndFill_Style);
358         }
359     }
360 }
361 
apply_paint_strokewidth(Json::Value & jsonPaint,SkPaint * target)362 static void apply_paint_strokewidth(Json::Value& jsonPaint, SkPaint* target) {
363     if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_STROKEWIDTH)) {
364         float strokeWidth = jsonPaint[SKJSONCANVAS_ATTRIBUTE_STROKEWIDTH].asFloat();
365         target->setStrokeWidth(strokeWidth);
366     }
367 }
368 
apply_paint_strokemiter(Json::Value & jsonPaint,SkPaint * target)369 static void apply_paint_strokemiter(Json::Value& jsonPaint, SkPaint* target) {
370     if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_STROKEMITER)) {
371         float strokeMiter = jsonPaint[SKJSONCANVAS_ATTRIBUTE_STROKEMITER].asFloat();
372         target->setStrokeMiter(strokeMiter);
373     }
374 }
375 
apply_paint_cap(Json::Value & jsonPaint,SkPaint * target)376 static void apply_paint_cap(Json::Value& jsonPaint, SkPaint* target) {
377     if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_CAP)) {
378         const char* cap = jsonPaint[SKJSONCANVAS_ATTRIBUTE_CAP].asCString();
379         if (!strcmp(cap, SKJSONCANVAS_CAP_BUTT)) {
380             target->setStrokeCap(SkPaint::kButt_Cap);
381         }
382         else if (!strcmp(cap, SKJSONCANVAS_CAP_ROUND)) {
383             target->setStrokeCap(SkPaint::kRound_Cap);
384         }
385         else if (!strcmp(cap, SKJSONCANVAS_CAP_SQUARE)) {
386             target->setStrokeCap(SkPaint::kSquare_Cap);
387         }
388     }
389 }
390 
apply_paint_antialias(Json::Value & jsonPaint,SkPaint * target)391 static void apply_paint_antialias(Json::Value& jsonPaint, SkPaint* target) {
392     if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_ANTIALIAS)) {
393         target->setAntiAlias(jsonPaint[SKJSONCANVAS_ATTRIBUTE_ANTIALIAS].asBool());
394     }
395 }
396 
apply_paint_blur(Json::Value & jsonPaint,SkPaint * target)397 static void apply_paint_blur(Json::Value& jsonPaint, SkPaint* target) {
398     if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_BLUR)) {
399         Json::Value blur = jsonPaint[SKJSONCANVAS_ATTRIBUTE_BLUR];
400         SkScalar sigma = blur[SKJSONCANVAS_ATTRIBUTE_SIGMA].asFloat();
401         SkBlurStyle style;
402         const char* jsonStyle = blur[SKJSONCANVAS_ATTRIBUTE_STYLE].asCString();
403         if (!strcmp(jsonStyle, SKJSONCANVAS_BLURSTYLE_NORMAL)) {
404             style = SkBlurStyle::kNormal_SkBlurStyle;
405         }
406         else if (!strcmp(jsonStyle, SKJSONCANVAS_BLURSTYLE_SOLID)) {
407             style = SkBlurStyle::kSolid_SkBlurStyle;
408         }
409         else if (!strcmp(jsonStyle, SKJSONCANVAS_BLURSTYLE_OUTER)) {
410             style = SkBlurStyle::kOuter_SkBlurStyle;
411         }
412         else if (!strcmp(jsonStyle, SKJSONCANVAS_BLURSTYLE_INNER)) {
413             style = SkBlurStyle::kInner_SkBlurStyle;
414         }
415         else {
416             SkASSERT(false);
417             style = SkBlurStyle::kNormal_SkBlurStyle;
418         }
419         SkBlurMaskFilter::BlurFlags flags;
420         const char* jsonQuality = blur[SKJSONCANVAS_ATTRIBUTE_QUALITY].asCString();
421         if (!strcmp(jsonQuality, SKJSONCANVAS_BLURQUALITY_LOW)) {
422             flags = SkBlurMaskFilter::BlurFlags::kNone_BlurFlag;
423         }
424         else if (!strcmp(jsonQuality, SKJSONCANVAS_BLURQUALITY_HIGH)) {
425             flags = SkBlurMaskFilter::BlurFlags::kHighQuality_BlurFlag;
426         }
427         else {
428             SkASSERT(false);
429             flags = SkBlurMaskFilter::BlurFlags::kNone_BlurFlag;
430         }
431         target->setMaskFilter(SkBlurMaskFilter::Create(style, sigma, flags));
432     }
433 }
434 
apply_paint_dashing(Json::Value & jsonPaint,SkPaint * target)435 static void apply_paint_dashing(Json::Value& jsonPaint, SkPaint* target) {
436     if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_DASHING)) {
437         Json::Value dash = jsonPaint[SKJSONCANVAS_ATTRIBUTE_DASHING];
438         Json::Value jsonIntervals = dash[SKJSONCANVAS_ATTRIBUTE_INTERVALS];
439         Json::ArrayIndex count = jsonIntervals.size();
440         SkScalar* intervals = (SkScalar*) sk_malloc_throw(count * sizeof(SkScalar));
441         for (Json::ArrayIndex i = 0; i < count; i++) {
442             intervals[i] = jsonIntervals[i].asFloat();
443         }
444         SkScalar phase = dash[SKJSONCANVAS_ATTRIBUTE_PHASE].asFloat();
445         target->setPathEffect(SkDashPathEffect::Create(intervals, count, phase));
446         free(intervals);
447     }
448 }
449 
apply_paint_textalign(Json::Value & jsonPaint,SkPaint * target)450 static void apply_paint_textalign(Json::Value& jsonPaint, SkPaint* target) {
451     if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_TEXTALIGN)) {
452         SkPaint::Align textAlign;
453         const char* jsonAlign = jsonPaint[SKJSONCANVAS_ATTRIBUTE_TEXTALIGN].asCString();
454         if (!strcmp(jsonAlign, SKJSONCANVAS_ALIGN_LEFT)) {
455             textAlign = SkPaint::kLeft_Align;
456         }
457         else if (!strcmp(jsonAlign, SKJSONCANVAS_ALIGN_CENTER)) {
458             textAlign = SkPaint::kCenter_Align;
459         }
460         else if (!strcmp(jsonAlign, SKJSONCANVAS_ALIGN_RIGHT)) {
461             textAlign = SkPaint::kRight_Align;
462         }
463         else {
464             SkASSERT(false);
465             textAlign = SkPaint::kLeft_Align;
466         }
467         target->setTextAlign(textAlign);
468     }
469 }
470 
apply_paint_textsize(Json::Value & jsonPaint,SkPaint * target)471 static void apply_paint_textsize(Json::Value& jsonPaint, SkPaint* target) {
472     if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_TEXTSIZE)) {
473         float textSize = jsonPaint[SKJSONCANVAS_ATTRIBUTE_TEXTSIZE].asFloat();
474         target->setTextSize(textSize);
475     }
476 }
477 
apply_paint_textscalex(Json::Value & jsonPaint,SkPaint * target)478 static void apply_paint_textscalex(Json::Value& jsonPaint, SkPaint* target) {
479     if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_TEXTSCALEX)) {
480         float textScaleX = jsonPaint[SKJSONCANVAS_ATTRIBUTE_TEXTSCALEX].asFloat();
481         target->setTextScaleX(textScaleX);
482     }
483 }
484 
apply_paint_textskewx(Json::Value & jsonPaint,SkPaint * target)485 static void apply_paint_textskewx(Json::Value& jsonPaint, SkPaint* target) {
486     if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_TEXTSKEWX)) {
487         float textSkewX = jsonPaint[SKJSONCANVAS_ATTRIBUTE_TEXTSKEWX].asFloat();
488         target->setTextSkewX(textSkewX);
489     }
490 }
491 
apply_paint_typeface(Json::Value & jsonPaint,SkPaint * target)492 static void apply_paint_typeface(Json::Value& jsonPaint, SkPaint* target) {
493     if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_TYPEFACE)) {
494         Json::Value jsonTypeface = jsonPaint[SKJSONCANVAS_ATTRIBUTE_TYPEFACE];
495         Json::Value bytes = jsonTypeface[SKJSONCANVAS_ATTRIBUTE_BYTES];
496         void* data;
497         Json::ArrayIndex length = decode_data(bytes, &data);
498         SkMemoryStream buffer(data, length);
499         SkTypeface* typeface = SkTypeface::Deserialize(&buffer);
500         free(data);
501         target->setTypeface(typeface);
502     }
503 }
504 
getPaint(Json::Value & paint,SkPaint * result)505 void Renderer::getPaint(Json::Value& paint, SkPaint* result) {
506     apply_paint_color(paint, result);
507     apply_paint_shader(paint, result);
508     apply_paint_patheffect(paint, result);
509     apply_paint_maskfilter(paint, result);
510     apply_paint_colorfilter(paint, result);
511     apply_paint_xfermode(paint, result);
512     apply_paint_imagefilter(paint, result);
513     apply_paint_style(paint, result);
514     apply_paint_strokewidth(paint, result);
515     apply_paint_strokemiter(paint, result);
516     apply_paint_cap(paint, result);
517     apply_paint_antialias(paint, result);
518     apply_paint_blur(paint, result);
519     apply_paint_dashing(paint, result);
520     apply_paint_textalign(paint, result);
521     apply_paint_textsize(paint, result);
522     apply_paint_textscalex(paint, result);
523     apply_paint_textskewx(paint, result);
524     apply_paint_typeface(paint, result);
525 }
526 
getRect(Json::Value & rect,SkRect * result)527 void Renderer::getRect(Json::Value& rect, SkRect* result) {
528     result->set(rect[0].asFloat(), rect[1].asFloat(), rect[2].asFloat(), rect[3].asFloat());
529 }
530 
getRRect(Json::Value & rrect,SkRRect * result)531 void Renderer::getRRect(Json::Value& rrect, SkRRect* result) {
532     SkVector radii[4] = {
533                             { rrect[1][0].asFloat(), rrect[1][1].asFloat() },
534                             { rrect[2][0].asFloat(), rrect[2][1].asFloat() },
535                             { rrect[3][0].asFloat(), rrect[3][1].asFloat() },
536                             { rrect[4][0].asFloat(), rrect[4][1].asFloat() }
537                         };
538     result->setRectRadii(SkRect::MakeLTRB(rrect[0][0].asFloat(), rrect[0][1].asFloat(),
539                                           rrect[0][2].asFloat(), rrect[0][3].asFloat()),
540                                           radii);
541 }
542 
getMatrix(Json::Value & matrix,SkMatrix * result)543 void Renderer::getMatrix(Json::Value& matrix, SkMatrix* result) {
544     SkScalar values[] = {
545         matrix[0][0].asFloat(), matrix[0][1].asFloat(), matrix[0][2].asFloat(),
546         matrix[1][0].asFloat(), matrix[1][1].asFloat(), matrix[1][2].asFloat(),
547         matrix[2][0].asFloat(), matrix[2][1].asFloat(), matrix[2][2].asFloat()
548     };
549     result->set9(values);
550 }
551 
getPath(Json::Value & path,SkPath * result)552 void Renderer::getPath(Json::Value& path, SkPath* result) {
553     const char* fillType = path[SKJSONCANVAS_ATTRIBUTE_FILLTYPE].asCString();
554     if (!strcmp(fillType, SKJSONCANVAS_FILLTYPE_WINDING)) {
555         result->setFillType(SkPath::kWinding_FillType);
556     }
557     else if (!strcmp(fillType, SKJSONCANVAS_FILLTYPE_EVENODD)) {
558         result->setFillType(SkPath::kEvenOdd_FillType);
559     }
560     else if (!strcmp(fillType, SKJSONCANVAS_FILLTYPE_INVERSEWINDING)) {
561         result->setFillType(SkPath::kInverseWinding_FillType);
562     }
563     else if (!strcmp(fillType, SKJSONCANVAS_FILLTYPE_INVERSEEVENODD)) {
564         result->setFillType(SkPath::kInverseEvenOdd_FillType);
565     }
566     Json::Value verbs = path[SKJSONCANVAS_ATTRIBUTE_VERBS];
567     for (Json::ArrayIndex i = 0; i < verbs.size(); i++) {
568         Json::Value verb = verbs[i];
569         if (verb.isString()) {
570             SkASSERT(!strcmp(verb.asCString(), SKJSONCANVAS_VERB_CLOSE));
571             result->close();
572         }
573         else {
574             if (verb.isMember(SKJSONCANVAS_VERB_MOVE)) {
575                 Json::Value move = verb[SKJSONCANVAS_VERB_MOVE];
576                 result->moveTo(move[0].asFloat(), move[1].asFloat());
577             }
578             else if (verb.isMember(SKJSONCANVAS_VERB_LINE)) {
579                 Json::Value line = verb[SKJSONCANVAS_VERB_LINE];
580                 result->lineTo(line[0].asFloat(), line[1].asFloat());
581             }
582             else if (verb.isMember(SKJSONCANVAS_VERB_QUAD)) {
583                 Json::Value quad = verb[SKJSONCANVAS_VERB_QUAD];
584                 result->quadTo(quad[0][0].asFloat(), quad[0][1].asFloat(),
585                                quad[1][0].asFloat(), quad[1][1].asFloat());
586             }
587             else if (verb.isMember(SKJSONCANVAS_VERB_CUBIC)) {
588                 Json::Value cubic = verb[SKJSONCANVAS_VERB_CUBIC];
589                 result->cubicTo(cubic[0][0].asFloat(), cubic[0][1].asFloat(),
590                                 cubic[1][0].asFloat(), cubic[1][1].asFloat(),
591                                 cubic[2][0].asFloat(), cubic[2][1].asFloat());
592             }
593             else if (verb.isMember(SKJSONCANVAS_VERB_CONIC)) {
594                 Json::Value conic = verb[SKJSONCANVAS_VERB_CONIC];
595                 result->conicTo(conic[0][0].asFloat(), conic[0][1].asFloat(),
596                                 conic[1][0].asFloat(), conic[1][1].asFloat(),
597                                 conic[2].asFloat());
598             }
599             else {
600                 SkASSERT(false);
601             }
602         }
603     }
604 }
605 
getRegionOp(Json::Value & jsonOp)606 SkRegion::Op Renderer::getRegionOp(Json::Value& jsonOp) {
607     const char* op = jsonOp.asCString();
608     if (!strcmp(op, SKJSONCANVAS_REGIONOP_DIFFERENCE)) {
609         return SkRegion::kDifference_Op;
610     }
611     else if (!strcmp(op, SKJSONCANVAS_REGIONOP_INTERSECT)) {
612         return SkRegion::kIntersect_Op;
613     }
614     else if (!strcmp(op, SKJSONCANVAS_REGIONOP_UNION)) {
615         return SkRegion::kUnion_Op;
616     }
617     else if (!strcmp(op, SKJSONCANVAS_REGIONOP_XOR)) {
618         return SkRegion::kXOR_Op;
619     }
620     else if (!strcmp(op, SKJSONCANVAS_REGIONOP_REVERSE_DIFFERENCE)) {
621         return SkRegion::kReverseDifference_Op;
622     }
623     else if (!strcmp(op, SKJSONCANVAS_REGIONOP_REPLACE)) {
624         return SkRegion::kReplace_Op;
625     }
626     SkASSERT(false);
627     return SkRegion::kIntersect_Op;
628 }
629 
processTranslate(Json::Value & command,SkCanvas * target)630 void Renderer::processTranslate(Json::Value& command, SkCanvas* target) {
631     target->translate(command[SKJSONCANVAS_ATTRIBUTE_X].asFloat(),
632                       command[SKJSONCANVAS_ATTRIBUTE_Y].asFloat());
633 }
634 
processScale(Json::Value & command,SkCanvas * target)635 void Renderer::processScale(Json::Value& command, SkCanvas* target) {
636     target->scale(command[SKJSONCANVAS_ATTRIBUTE_X].asFloat(),
637                   command[SKJSONCANVAS_ATTRIBUTE_Y].asFloat());
638 }
639 
processMatrix(Json::Value & command,SkCanvas * target)640 void Renderer::processMatrix(Json::Value& command, SkCanvas* target) {
641     SkMatrix matrix;
642     this->getMatrix(command[SKJSONCANVAS_ATTRIBUTE_MATRIX], &matrix);
643     target->setMatrix(matrix);
644 }
645 
processSave(Json::Value & command,SkCanvas * target)646 void Renderer::processSave(Json::Value& command, SkCanvas* target) {
647     target->save();
648 }
649 
processRestore(Json::Value & command,SkCanvas * target)650 void Renderer::processRestore(Json::Value& command, SkCanvas* target) {
651     target->restore();
652 }
653 
processSaveLayer(Json::Value & command,SkCanvas * target)654 void Renderer::processSaveLayer(Json::Value& command, SkCanvas* target) {
655     SkCanvas::SaveLayerRec rec;
656     SkRect bounds;
657     if (command.isMember(SKJSONCANVAS_ATTRIBUTE_BOUNDS)) {
658         this->getRect(command[SKJSONCANVAS_ATTRIBUTE_BOUNDS], &bounds);
659         rec.fBounds = &bounds;
660     }
661     SkPaint paint;
662     if (command.isMember(SKJSONCANVAS_ATTRIBUTE_PAINT)) {
663         this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
664         rec.fPaint = &paint;
665     }
666     if (command.isMember(SKJSONCANVAS_ATTRIBUTE_BACKDROP)) {
667         rec.fBackdrop = (SkImageFilter*) load_flattenable(command[SKJSONCANVAS_ATTRIBUTE_BACKDROP]);
668     }
669     target->saveLayer(rec);
670     if (rec.fBackdrop != nullptr) {
671         rec.fBackdrop->unref();
672     }
673 }
674 
processPaint(Json::Value & command,SkCanvas * target)675 void Renderer::processPaint(Json::Value& command, SkCanvas* target) {
676     SkPaint paint;
677     this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
678     target->drawPaint(paint);
679 }
680 
processRect(Json::Value & command,SkCanvas * target)681 void Renderer::processRect(Json::Value& command, SkCanvas* target) {
682     SkRect rect;
683     this->getRect(command[SKJSONCANVAS_ATTRIBUTE_COORDS], &rect);
684     SkPaint paint;
685     this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
686     target->drawRect(rect, paint);
687 }
688 
processRRect(Json::Value & command,SkCanvas * target)689 void Renderer::processRRect(Json::Value& command, SkCanvas* target) {
690     SkRRect rrect;
691     this->getRRect(command[SKJSONCANVAS_ATTRIBUTE_COORDS], &rrect);
692     SkPaint paint;
693     this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
694     target->drawRRect(rrect, paint);
695 }
696 
processOval(Json::Value & command,SkCanvas * target)697 void Renderer::processOval(Json::Value& command, SkCanvas* target) {
698     SkRect rect;
699     this->getRect(command[SKJSONCANVAS_ATTRIBUTE_COORDS], &rect);
700     SkPaint paint;
701     this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
702     target->drawOval(rect, paint);
703 }
704 
processPath(Json::Value & command,SkCanvas * target)705 void Renderer::processPath(Json::Value& command, SkCanvas* target) {
706     SkPath path;
707     this->getPath(command[SKJSONCANVAS_ATTRIBUTE_PATH], &path);
708     SkPaint paint;
709     this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
710     target->drawPath(path, paint);
711 }
712 
processText(Json::Value & command,SkCanvas * target)713 void Renderer::processText(Json::Value& command, SkCanvas* target) {
714     const char* text = command[SKJSONCANVAS_ATTRIBUTE_TEXT].asCString();
715     SkPaint paint;
716     this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
717     Json::Value coords = command[SKJSONCANVAS_ATTRIBUTE_COORDS];
718     target->drawText(text, strlen(text), coords[0].asFloat(), coords[1].asFloat(), paint);
719 }
720 
processPosText(Json::Value & command,SkCanvas * target)721 void Renderer::processPosText(Json::Value& command, SkCanvas* target) {
722     const char* text = command[SKJSONCANVAS_ATTRIBUTE_TEXT].asCString();
723     SkPaint paint;
724     this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
725     Json::Value coords = command[SKJSONCANVAS_ATTRIBUTE_COORDS];
726     int count = (int) coords.size();
727     SkPoint* points = (SkPoint*) sk_malloc_throw(count * sizeof(SkPoint));
728     for (int i = 0; i < count; i++) {
729         points[i] = SkPoint::Make(coords[i][0].asFloat(), coords[i][1].asFloat());
730     }
731     target->drawPosText(text, strlen(text), points, paint);
732     free(points);
733 }
734 
processTextOnPath(Json::Value & command,SkCanvas * target)735 void Renderer::processTextOnPath(Json::Value& command, SkCanvas* target) {
736     const char* text = command[SKJSONCANVAS_ATTRIBUTE_TEXT].asCString();
737     SkPath path;
738     this->getPath(command[SKJSONCANVAS_ATTRIBUTE_PATH], &path);
739     SkMatrix* matrixPtr;
740     SkMatrix matrix;
741     if (command.isMember(SKJSONCANVAS_ATTRIBUTE_MATRIX)) {
742         this->getMatrix(command[SKJSONCANVAS_ATTRIBUTE_MATRIX], &matrix);
743         matrixPtr = &matrix;
744     }
745     else {
746         matrixPtr = nullptr;
747     }
748     SkPaint paint;
749     this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
750     target->drawTextOnPath(text, strlen(text), path, matrixPtr, paint);
751 }
752 
processTextBlob(Json::Value & command,SkCanvas * target)753 void Renderer::processTextBlob(Json::Value& command, SkCanvas* target) {
754     SkTextBlobBuilder builder;
755     Json::Value runs = command[SKJSONCANVAS_ATTRIBUTE_RUNS];
756     for (Json::ArrayIndex i = 0 ; i < runs.size(); i++) {
757         Json::Value run = runs[i];
758         SkPaint font;
759         font.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
760         this->getPaint(run[SKJSONCANVAS_ATTRIBUTE_FONT], &font);
761         Json::Value glyphs = run[SKJSONCANVAS_ATTRIBUTE_GLYPHS];
762         int count = glyphs.size();
763         Json::Value coords = run[SKJSONCANVAS_ATTRIBUTE_COORDS];
764         SkScalar x = coords[0].asFloat();
765         SkScalar y = coords[1].asFloat();
766         if (run.isMember(SKJSONCANVAS_ATTRIBUTE_POSITIONS)) {
767             Json::Value positions = run[SKJSONCANVAS_ATTRIBUTE_POSITIONS];
768             if (positions.size() > 0 && positions[0].isNumeric()) {
769                 SkTextBlobBuilder::RunBuffer buffer = builder.allocRunPosH(font, count, y);
770                 for (int j = 0; j < count; j++) {
771                     buffer.glyphs[j] = glyphs[j].asUInt();
772                     buffer.pos[j] = positions[j].asFloat();
773                 }
774             }
775             else {
776                 SkTextBlobBuilder::RunBuffer buffer = builder.allocRunPos(font, count);
777                 for (int j = 0; j < count; j++) {
778                     buffer.glyphs[j] = glyphs[j].asUInt();
779                     buffer.pos[j * 2] = positions[j][0].asFloat();
780                     buffer.pos[j * 2 + 1] = positions[j][1].asFloat();
781                 }
782             }
783         }
784         else {
785             SkTextBlobBuilder::RunBuffer buffer = builder.allocRun(font, count, x, y);
786             for (int j = 0; j < count; j++) {
787                 buffer.glyphs[j] = glyphs[j].asUInt();
788             }
789         }
790     }
791     SkScalar x = command[SKJSONCANVAS_ATTRIBUTE_X].asFloat();
792     SkScalar y = command[SKJSONCANVAS_ATTRIBUTE_Y].asFloat();
793     SkPaint paint;
794     this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
795     target->drawTextBlob(builder.build(), x, y, paint);
796 }
797 
processPoints(Json::Value & command,SkCanvas * target)798 void Renderer::processPoints(Json::Value& command, SkCanvas* target) {
799     SkCanvas::PointMode mode;
800     const char* jsonMode = command[SKJSONCANVAS_ATTRIBUTE_MODE].asCString();
801     if (!strcmp(jsonMode, SKJSONCANVAS_POINTMODE_POINTS)) {
802         mode = SkCanvas::kPoints_PointMode;
803     }
804     else if (!strcmp(jsonMode, SKJSONCANVAS_POINTMODE_LINES)) {
805         mode = SkCanvas::kLines_PointMode;
806     }
807     else if (!strcmp(jsonMode, SKJSONCANVAS_POINTMODE_POLYGON)) {
808         mode = SkCanvas::kPolygon_PointMode;
809     }
810     else {
811         SkASSERT(false);
812         return;
813     }
814     Json::Value jsonPoints = command[SKJSONCANVAS_ATTRIBUTE_POINTS];
815     int count = (int) jsonPoints.size();
816     SkPoint* points = (SkPoint*) sk_malloc_throw(count * sizeof(SkPoint));
817     for (int i = 0; i < count; i++) {
818         points[i] = SkPoint::Make(jsonPoints[i][0].asFloat(), jsonPoints[i][1].asFloat());
819     }
820     SkPaint paint;
821     this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
822     target->drawPoints(mode, count, points, paint);
823     free(points);
824 }
825 
processClipRect(Json::Value & command,SkCanvas * target)826 void Renderer::processClipRect(Json::Value& command, SkCanvas* target) {
827     SkRect rect;
828     this->getRect(command[SKJSONCANVAS_ATTRIBUTE_COORDS], &rect);
829     target->clipRect(rect, this->getRegionOp(command[SKJSONCANVAS_ATTRIBUTE_REGIONOP]),
830                      command[SKJSONCANVAS_ATTRIBUTE_ANTIALIAS].asBool());
831 }
832 
processClipRRect(Json::Value & command,SkCanvas * target)833 void Renderer::processClipRRect(Json::Value& command, SkCanvas* target) {
834     SkRRect rrect;
835     this->getRRect(command[SKJSONCANVAS_ATTRIBUTE_COORDS], &rrect);
836     target->clipRRect(rrect, this->getRegionOp(command[SKJSONCANVAS_ATTRIBUTE_REGIONOP]),
837                       command[SKJSONCANVAS_ATTRIBUTE_ANTIALIAS].asBool());
838 }
839 
processClipPath(Json::Value & command,SkCanvas * target)840 void Renderer::processClipPath(Json::Value& command, SkCanvas* target) {
841     SkPath path;
842     this->getPath(command[SKJSONCANVAS_ATTRIBUTE_PATH], &path);
843     target->clipPath(path, this->getRegionOp(command[SKJSONCANVAS_ATTRIBUTE_REGIONOP]),
844                      command[SKJSONCANVAS_ATTRIBUTE_ANTIALIAS].asBool());
845 }
846 
processImage(Json::Value & command,SkCanvas * target)847 void Renderer::processImage(Json::Value& command, SkCanvas* target) {
848     SkImage* image = load_image(command[SKJSONCANVAS_ATTRIBUTE_IMAGE]);
849     if (image == nullptr) {
850         return;
851     }
852     Json::Value point = command[SKJSONCANVAS_ATTRIBUTE_COORDS];
853     SkPaint* paintPtr;
854     SkPaint paint;
855     if (command.isMember(SKJSONCANVAS_ATTRIBUTE_PAINT)) {
856         this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
857         paintPtr = &paint;
858     }
859     else {
860         paintPtr = nullptr;
861     }
862     target->drawImage(image, point[0].asFloat(), point[1].asFloat(), paintPtr);
863     image->unref();
864 }
865 
processImageRect(Json::Value & command,SkCanvas * target)866 void Renderer::processImageRect(Json::Value& command, SkCanvas* target) {
867     SkImage* image = load_image(command[SKJSONCANVAS_ATTRIBUTE_IMAGE]);
868     if (image == nullptr) {
869         return;
870     }
871     SkRect dst;
872     this->getRect(command[SKJSONCANVAS_ATTRIBUTE_DST], &dst);
873     SkPaint* paintPtr;
874     SkPaint paint;
875     if (command.isMember(SKJSONCANVAS_ATTRIBUTE_PAINT)) {
876         this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
877         paintPtr = &paint;
878     }
879     else {
880         paintPtr = nullptr;
881     }
882     SkCanvas::SrcRectConstraint constraint;
883     if (command.isMember(SKJSONCANVAS_ATTRIBUTE_STRICT) &&
884         command[SKJSONCANVAS_ATTRIBUTE_STRICT].asBool()) {
885         constraint = SkCanvas::kStrict_SrcRectConstraint;
886     }
887     else {
888         constraint = SkCanvas::kFast_SrcRectConstraint;
889     }
890     if (command.isMember(SKJSONCANVAS_ATTRIBUTE_SRC)) {
891         SkRect src;
892         this->getRect(command[SKJSONCANVAS_ATTRIBUTE_SRC], &src);
893         target->drawImageRect(image, src, dst, paintPtr, constraint);
894     }
895     else {
896         target->drawImageRect(image, dst, paintPtr, constraint);
897     }
898     image->unref();
899 }
900 
processBitmap(Json::Value & command,SkCanvas * target)901 void Renderer::processBitmap(Json::Value& command, SkCanvas* target) {
902     SkImage* image = load_image(command[SKJSONCANVAS_ATTRIBUTE_BITMAP]);
903     if (image == nullptr) {
904         return;
905     }
906     Json::Value point = command[SKJSONCANVAS_ATTRIBUTE_COORDS];
907     SkPaint* paintPtr;
908     SkPaint paint;
909     if (command.isMember(SKJSONCANVAS_ATTRIBUTE_PAINT)) {
910         this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
911         paintPtr = &paint;
912     }
913     else {
914         paintPtr = nullptr;
915     }
916     target->drawImage(image, point[0].asFloat(), point[1].asFloat(), paintPtr);
917     image->unref();
918 }
919 
processBitmapRect(Json::Value & command,SkCanvas * target)920 void Renderer::processBitmapRect(Json::Value& command, SkCanvas* target) {
921     SkBitmap* bitmap = load_bitmap(command[SKJSONCANVAS_ATTRIBUTE_BITMAP]);
922     if (bitmap == nullptr) {
923         return;
924     }
925     SkRect dst;
926     this->getRect(command[SKJSONCANVAS_ATTRIBUTE_DST], &dst);
927     SkPaint* paintPtr;
928     SkPaint paint;
929     if (command.isMember(SKJSONCANVAS_ATTRIBUTE_PAINT)) {
930         this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
931         paintPtr = &paint;
932     }
933     else {
934         paintPtr = nullptr;
935     }
936     SkCanvas::SrcRectConstraint constraint;
937     if (command.isMember(SKJSONCANVAS_ATTRIBUTE_STRICT) &&
938         command[SKJSONCANVAS_ATTRIBUTE_STRICT].asBool()) {
939         constraint = SkCanvas::kStrict_SrcRectConstraint;
940     }
941     else {
942         constraint = SkCanvas::kFast_SrcRectConstraint;
943     }
944     if (command.isMember(SKJSONCANVAS_ATTRIBUTE_SRC)) {
945         SkRect src;
946         this->getRect(command[SKJSONCANVAS_ATTRIBUTE_SRC], &src);
947         target->drawBitmapRect(*bitmap, src, dst, paintPtr, constraint);
948     }
949     else {
950         target->drawBitmapRect(*bitmap, dst, paintPtr, constraint);
951     }
952     free(bitmap);
953 }
954 
render(const char * json,SkCanvas * target)955 void render(const char* json, SkCanvas* target) {
956     Renderer renderer;
957     Json::Reader reader;
958     Json::Value root;
959     if (reader.parse(std::string(json), root)) {
960         SkASSERT(root[SKJSONCANVAS_VERSION].asInt() == 1);
961         Json::Value commands = root[SKJSONCANVAS_COMMANDS];
962         for (Json::ArrayIndex i = 0; i < commands.size(); i++) {
963             renderer.processCommand(commands[i], target);
964         }
965     }
966     else {
967         SkDebugf(json);
968         SkFAIL("json parse failure");
969     }
970 }
971 
972 } // namespace
973