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
19namespace SkJSONRenderer {
20
21class Renderer {
22public:
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
84void 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
161static 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
170static 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
179static 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
201static 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
227static 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
242static 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
271static 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
281static 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
292static 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
303static 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
314static 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
325static 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
336static 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
347static 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
362static 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
369static 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
376static 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
391static 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
397static 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
435static 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
450static 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
471static 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
478static 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
485static 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
492static 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
505void 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
527void Renderer::getRect(Json::Value& rect, SkRect* result) {
528    result->set(rect[0].asFloat(), rect[1].asFloat(), rect[2].asFloat(), rect[3].asFloat());
529}
530
531void 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
543void 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
552void 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
606SkRegion::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
630void Renderer::processTranslate(Json::Value& command, SkCanvas* target) {
631    target->translate(command[SKJSONCANVAS_ATTRIBUTE_X].asFloat(),
632                      command[SKJSONCANVAS_ATTRIBUTE_Y].asFloat());
633}
634
635void Renderer::processScale(Json::Value& command, SkCanvas* target) {
636    target->scale(command[SKJSONCANVAS_ATTRIBUTE_X].asFloat(),
637                  command[SKJSONCANVAS_ATTRIBUTE_Y].asFloat());
638}
639
640void Renderer::processMatrix(Json::Value& command, SkCanvas* target) {
641    SkMatrix matrix;
642    this->getMatrix(command[SKJSONCANVAS_ATTRIBUTE_MATRIX], &matrix);
643    target->setMatrix(matrix);
644}
645
646void Renderer::processSave(Json::Value& command, SkCanvas* target) {
647    target->save();
648}
649
650void Renderer::processRestore(Json::Value& command, SkCanvas* target) {
651    target->restore();
652}
653
654void 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
675void Renderer::processPaint(Json::Value& command, SkCanvas* target) {
676    SkPaint paint;
677    this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
678    target->drawPaint(paint);
679}
680
681void 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
689void 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
697void 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
705void 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
713void 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
721void 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
735void 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
753void 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
798void 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
826void 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
833void 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
840void 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
847void 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
866void 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
901void 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
920void 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
955void 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