1978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas/*
2978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas * Copyright 2016 Google Inc.
3978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas *
4978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas * Use of this source code is governed by a BSD-style license that can be
5978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas * found in the LICENSE file.
6978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas */
7978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas
8978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas#include "SkJSONRenderer.h"
978fc22af41a5118963a8f7253758111b05b9700eethannicholas
1078fc22af41a5118963a8f7253758111b05b9700eethannicholas#include "SkBlurMaskFilter.h"
1178fc22af41a5118963a8f7253758111b05b9700eethannicholas#include "SkDashPathEffect.h"
12978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas#include "SkJSONCanvas.h"
13978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas#include "SkJSONCPP.h"
14978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas#include "SkPath.h"
15f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas#include "SkTextBlob.h"
16f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas#include "SkTypeface.h"
1730c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas#include "SkValidatingReadBuffer.h"
18978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas
19978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholasnamespace SkJSONRenderer {
20978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas
21978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholasclass Renderer {
22978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholaspublic:
237471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    void getPaint(Json::Value& paint, SkPaint* result);
24978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas
257471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    void getRect(Json::Value& rect, SkRect* result);
26978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas
277471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    void getRRect(Json::Value& rrect, SkRRect* result);
28978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas
297471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    void getPath(Json::Value& path, SkPath* result);
3078fc22af41a5118963a8f7253758111b05b9700eethannicholas
317471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    void getMatrix(Json::Value& matrix, SkMatrix* result);
327471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas
337471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    SkRegion::Op getRegionOp(Json::Value& op);
3478fc22af41a5118963a8f7253758111b05b9700eethannicholas
35978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    void processCommand(Json::Value& command, SkCanvas* target);
36978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas
377471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    void processTranslate(Json::Value& command, SkCanvas* target);
387471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas
397471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    void processScale(Json::Value& command, SkCanvas* target);
407471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas
41978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    void processMatrix(Json::Value& command, SkCanvas* target);
42978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas
43978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    void processSave(Json::Value& command, SkCanvas* target);
44978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas
45978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    void processRestore(Json::Value& command, SkCanvas* target);
46978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas
4730c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    void processSaveLayer(Json::Value& command, SkCanvas* target);
4830c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas
49978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    void processPaint(Json::Value& command, SkCanvas* target);
50978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas
51978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    void processRect(Json::Value& command, SkCanvas* target);
52978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas
53978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    void processRRect(Json::Value& command, SkCanvas* target);
54978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas
55978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    void processOval(Json::Value& command, SkCanvas* target);
56978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas
57978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    void processPath(Json::Value& command, SkCanvas* target);
58978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas
59978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    void processText(Json::Value& command, SkCanvas* target);
60978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas
6178fc22af41a5118963a8f7253758111b05b9700eethannicholas    void processPosText(Json::Value& command, SkCanvas* target);
6278fc22af41a5118963a8f7253758111b05b9700eethannicholas
637471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    void processTextOnPath(Json::Value& command, SkCanvas* target);
647471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas
65f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas    void processTextBlob(Json::Value& command, SkCanvas* target);
66f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas
67978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    void processPoints(Json::Value& command, SkCanvas* target);
68978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas
6930c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    void processImage(Json::Value& command, SkCanvas* target);
7030c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas
7130c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    void processImageRect(Json::Value& command, SkCanvas* target);
7230c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas
7330c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    void processBitmap(Json::Value& command, SkCanvas* target);
7430c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas
7530c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    void processBitmapRect(Json::Value& command, SkCanvas* target);
7630c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas
77978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    void processClipRect(Json::Value& command, SkCanvas* target);
7878fc22af41a5118963a8f7253758111b05b9700eethannicholas
7978fc22af41a5118963a8f7253758111b05b9700eethannicholas    void processClipRRect(Json::Value& command, SkCanvas* target);
8078fc22af41a5118963a8f7253758111b05b9700eethannicholas
8178fc22af41a5118963a8f7253758111b05b9700eethannicholas    void processClipPath(Json::Value& command, SkCanvas* target);
82978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas};
83978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas
84978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholasvoid Renderer::processCommand(Json::Value& command, SkCanvas* target) {
85978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    const char* name = command[SKJSONCANVAS_COMMAND].asCString();
86978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    // TODO speed this up with a hash
877471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    if (!strcmp(name, SKJSONCANVAS_COMMAND_TRANSLATE)) {
887471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas        this->processTranslate(command, target);
897471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    }
907471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    else if (!strcmp(name, SKJSONCANVAS_COMMAND_SCALE)) {
917471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas        this->processScale(command, target);
927471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    }
937471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    else if (!strcmp(name, SKJSONCANVAS_COMMAND_MATRIX)) {
94978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas        this->processMatrix(command, target);
95978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    }
96978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    else if (!strcmp(name, SKJSONCANVAS_COMMAND_SAVE)) {
97978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas        this->processSave(command, target);
98978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    }
99978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    else if (!strcmp(name, SKJSONCANVAS_COMMAND_RESTORE)) {
100978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas        this->processRestore(command, target);
101978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    }
10230c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    else if (!strcmp(name, SKJSONCANVAS_COMMAND_SAVELAYER)) {
10330c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        this->processSaveLayer(command, target);
10430c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
105978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    else if (!strcmp(name, SKJSONCANVAS_COMMAND_PAINT)) {
106978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas        this->processPaint(command, target);
107978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    }
108978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    else if (!strcmp(name, SKJSONCANVAS_COMMAND_RECT)) {
109978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas        this->processRect(command, target);
110978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    }
111978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    else if (!strcmp(name, SKJSONCANVAS_COMMAND_RRECT)) {
112978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas        this->processRRect(command, target);
113978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    }
114978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    else if (!strcmp(name, SKJSONCANVAS_COMMAND_OVAL)) {
115978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas        this->processOval(command, target);
116978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    }
117978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    else if (!strcmp(name, SKJSONCANVAS_COMMAND_PATH)) {
118978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas        this->processPath(command, target);
119978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    }
120978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    else if (!strcmp(name, SKJSONCANVAS_COMMAND_TEXT)) {
121978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas        this->processText(command, target);
122978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    }
12378fc22af41a5118963a8f7253758111b05b9700eethannicholas    else if (!strcmp(name, SKJSONCANVAS_COMMAND_POSTEXT)) {
12478fc22af41a5118963a8f7253758111b05b9700eethannicholas        this->processPosText(command, target);
12578fc22af41a5118963a8f7253758111b05b9700eethannicholas    }
1267471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    else if (!strcmp(name, SKJSONCANVAS_COMMAND_TEXTONPATH)) {
1277471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas        this->processTextOnPath(command, target);
1287471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    }
129f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas    else if (!strcmp(name, SKJSONCANVAS_COMMAND_TEXTBLOB)) {
130f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas        this->processTextBlob(command, target);
131f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas    }
132978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    else if (!strcmp(name, SKJSONCANVAS_COMMAND_POINTS)) {
133978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas        this->processPoints(command, target);
134978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    }
13530c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    else if (!strcmp(name, SKJSONCANVAS_COMMAND_IMAGE)) {
13630c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        this->processImage(command, target);
13730c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
13830c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    else if (!strcmp(name, SKJSONCANVAS_COMMAND_IMAGERECT)) {
13930c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        this->processImageRect(command, target);
14030c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
14130c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    else if (!strcmp(name, SKJSONCANVAS_COMMAND_BITMAP)) {
14230c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        this->processBitmap(command, target);
14330c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
14430c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    else if (!strcmp(name, SKJSONCANVAS_COMMAND_BITMAPRECT)) {
14530c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        this->processBitmapRect(command, target);
14630c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
147978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    else if (!strcmp(name, SKJSONCANVAS_COMMAND_CLIPRECT)) {
148978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas        this->processClipRect(command, target);
149978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    }
15078fc22af41a5118963a8f7253758111b05b9700eethannicholas    else if (!strcmp(name, SKJSONCANVAS_COMMAND_CLIPRRECT)) {
15178fc22af41a5118963a8f7253758111b05b9700eethannicholas        this->processClipRRect(command, target);
15278fc22af41a5118963a8f7253758111b05b9700eethannicholas    }
15378fc22af41a5118963a8f7253758111b05b9700eethannicholas    else if (!strcmp(name, SKJSONCANVAS_COMMAND_CLIPPATH)) {
15478fc22af41a5118963a8f7253758111b05b9700eethannicholas        this->processClipPath(command, target);
15578fc22af41a5118963a8f7253758111b05b9700eethannicholas    }
156978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    else {
157978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas        SkDebugf("unsupported JSON command: %s\n", name);
158978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    }
159978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas}
160978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas
16130c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholasstatic void apply_paint_color(Json::Value& jsonPaint, SkPaint* target) {
162978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_COLOR)) {
163978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas        Json::Value color = jsonPaint[SKJSONCANVAS_ATTRIBUTE_COLOR];
16430c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        target->setColor(SkColorSetARGB(color[0].asInt(), color[1].asInt(), color[2].asInt(),
165978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas                         color[3].asInt()));
166978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    }
16730c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas}
16830c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas
16930c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas// note that the caller is responsible for freeing the pointer
17030c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholasstatic Json::ArrayIndex decode_data(Json::Value bytes, void** target) {
17130c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    Json::ArrayIndex size = bytes.size();
17230c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    *target = sk_malloc_throw(size);
17330c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    for (Json::ArrayIndex i = 0; i < size; i++) {
17430c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        ((uint8_t*) *target)[i] = bytes[i].asInt();
17530c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
17630c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    return size;
17730c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas}
17830c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas
17930c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholasstatic SkFlattenable* load_flattenable(Json::Value jsonFlattenable) {
18030c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    if (!jsonFlattenable.isMember(SKJSONCANVAS_ATTRIBUTE_NAME)) {
18130c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        return nullptr;
18230c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
18330c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    const char* name = jsonFlattenable[SKJSONCANVAS_ATTRIBUTE_NAME].asCString();
18430c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    SkFlattenable::Factory factory = SkFlattenable::NameToFactory(name);
18530c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    if (factory == nullptr) {
1860bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas        SkDebugf("no factory for loading '%s'\n", name);
18730c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        return nullptr;
18830c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
18930c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    void* data;
19030c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    int size = decode_data(jsonFlattenable[SKJSONCANVAS_ATTRIBUTE_BYTES], &data);
19130c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    SkValidatingReadBuffer buffer(data, size);
19230c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    SkFlattenable* result = factory(buffer);
19330c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    free(data);
19430c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    if (!buffer.isValid()) {
1950bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas        SkDebugf("invalid buffer loading flattenable\n");
19630c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        return nullptr;
19730c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
19830c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    return result;
19930c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas}
20030c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas
2010bd103497a21c2cb30fd5382cedb706cbf4941faethannicholasstatic SkColorType colortype_from_name(const char* name) {
2020bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas    if (!strcmp(name, SKJSONCANVAS_COLORTYPE_ARGB4444)) {
2030bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas        return kARGB_4444_SkColorType;
2040bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas    }
2050bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas    else if (!strcmp(name, SKJSONCANVAS_COLORTYPE_RGBA8888)) {
2060bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas        return kRGBA_8888_SkColorType;
2070bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas    }
2080bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas    else if (!strcmp(name, SKJSONCANVAS_COLORTYPE_BGRA8888)) {
2090bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas        return kBGRA_8888_SkColorType;
2100bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas    }
2110bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas    else if (!strcmp(name, SKJSONCANVAS_COLORTYPE_565)) {
2120bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas        return kRGB_565_SkColorType;
2130bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas    }
2140bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas    else if (!strcmp(name, SKJSONCANVAS_COLORTYPE_GRAY8)) {
2150bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas        return kGray_8_SkColorType;
2160bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas    }
2170bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas    else if (!strcmp(name, SKJSONCANVAS_COLORTYPE_INDEX8)) {
2180bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas        return kIndex_8_SkColorType;
2190bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas    }
2200bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas    else if (!strcmp(name, SKJSONCANVAS_COLORTYPE_ALPHA8)) {
2210bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas        return kAlpha_8_SkColorType;
2220bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas    }
2230bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas    SkASSERT(false);
2240bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas    return kN32_SkColorType;
2250bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas}
2260bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas
2270bd103497a21c2cb30fd5382cedb706cbf4941faethannicholasstatic SkBitmap* convert_colortype(SkBitmap* bitmap, SkColorType colorType) {
2280bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas    if (bitmap->colorType() == colorType  ) {
2290bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas        return bitmap;
2300bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas    }
2310bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas    SkBitmap* dst = new SkBitmap();
2320bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas    if (bitmap->copyTo(dst, colorType)) {
2330bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas        delete bitmap;
2340bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas        return dst;
2350bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas    }
2360bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas    SkASSERT(false);
2370bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas    delete dst;
2380bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas    return bitmap;
2390bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas}
2400bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas
24130c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas// caller is responsible for freeing return value
2420bd103497a21c2cb30fd5382cedb706cbf4941faethannicholasstatic SkBitmap* load_bitmap(const Json::Value& jsonBitmap) {
24330c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    if (!jsonBitmap.isMember(SKJSONCANVAS_ATTRIBUTE_BYTES)) {
2440bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas        SkDebugf("invalid bitmap\n");
24530c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        return nullptr;
24630c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
24730c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    void* data;
24830c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    int size = decode_data(jsonBitmap[SKJSONCANVAS_ATTRIBUTE_BYTES], &data);
24930c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    SkMemoryStream stream(data, size);
25030c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    SkImageDecoder* decoder = SkImageDecoder::Factory(&stream);
25130c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    SkBitmap* bitmap = new SkBitmap();
25230c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    SkImageDecoder::Result result = decoder->decode(&stream, bitmap,
25330c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas                                                    SkImageDecoder::kDecodePixels_Mode);
25430c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    free(decoder);
25530c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    if (result != SkImageDecoder::kFailure) {
25630c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        free(data);
2570bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas        if (jsonBitmap.isMember(SKJSONCANVAS_ATTRIBUTE_COLOR)) {
2580bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas            const char* ctName = jsonBitmap[SKJSONCANVAS_ATTRIBUTE_COLOR].asCString();
2590bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas            SkColorType ct = colortype_from_name(ctName);
2600bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas            if (ct != kIndex_8_SkColorType) {
2610bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas                bitmap = convert_colortype(bitmap, ct);
2620bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas            }
2630bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas        }
26430c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        return bitmap;
26530c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
2660bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas    SkDebugf("image decode failed\n");
26730c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    free(data);
26830c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    return nullptr;
26930c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas}
27030c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas
2710bd103497a21c2cb30fd5382cedb706cbf4941faethannicholasstatic SkImage* load_image(const Json::Value& jsonImage) {
27230c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    SkBitmap* bitmap = load_bitmap(jsonImage);
27330c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    if (bitmap == nullptr) {
27430c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        return nullptr;
27530c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
27630c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    SkImage* result = SkImage::NewFromBitmap(*bitmap);
2770bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas    delete bitmap;
27830c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    return result;
27930c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas}
28030c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas
28130c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholasstatic void apply_paint_shader(Json::Value& jsonPaint, SkPaint* target) {
28230c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_SHADER)) {
28330c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        Json::Value jsonShader = jsonPaint[SKJSONCANVAS_ATTRIBUTE_SHADER];
28430c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        SkShader* shader = (SkShader*) load_flattenable(jsonShader);
28530c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        if (shader != nullptr) {
28630c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas            target->setShader(shader);
28730c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas            shader->unref();
28830c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        }
28930c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
29030c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas}
29130c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas
29230c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholasstatic void apply_paint_patheffect(Json::Value& jsonPaint, SkPaint* target) {
29330c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_PATHEFFECT)) {
29430c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        Json::Value jsonPathEffect = jsonPaint[SKJSONCANVAS_ATTRIBUTE_PATHEFFECT];
29530c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        SkPathEffect* pathEffect = (SkPathEffect*) load_flattenable(jsonPathEffect);
29630c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        if (pathEffect != nullptr) {
29730c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas            target->setPathEffect(pathEffect);
29830c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas            pathEffect->unref();
29930c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        }
30030c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
30130c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas}
30230c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas
30330c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholasstatic void apply_paint_maskfilter(Json::Value& jsonPaint, SkPaint* target) {
30430c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_MASKFILTER)) {
30530c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        Json::Value jsonMaskFilter = jsonPaint[SKJSONCANVAS_ATTRIBUTE_MASKFILTER];
30630c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        SkMaskFilter* maskFilter = (SkMaskFilter*) load_flattenable(jsonMaskFilter);
30730c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        if (maskFilter != nullptr) {
30830c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas            target->setMaskFilter(maskFilter);
30930c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas            maskFilter->unref();
31030c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        }
31130c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
31230c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas}
31330c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas
314f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholasstatic void apply_paint_colorfilter(Json::Value& jsonPaint, SkPaint* target) {
315f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas    if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_COLORFILTER)) {
316f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas        Json::Value jsonColorFilter = jsonPaint[SKJSONCANVAS_ATTRIBUTE_COLORFILTER];
317f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas        SkColorFilter* colorFilter = (SkColorFilter*) load_flattenable(jsonColorFilter);
318f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas        if (colorFilter != nullptr) {
319f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas            target->setColorFilter(colorFilter);
320f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas            colorFilter->unref();
321f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas        }
322f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas    }
323f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas}
324f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas
32530c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholasstatic void apply_paint_xfermode(Json::Value& jsonPaint, SkPaint* target) {
32630c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_XFERMODE)) {
32730c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        Json::Value jsonXfermode = jsonPaint[SKJSONCANVAS_ATTRIBUTE_XFERMODE];
32830c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        SkXfermode* xfermode = (SkXfermode*) load_flattenable(jsonXfermode);
32930c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        if (xfermode != nullptr) {
33030c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas            target->setXfermode(xfermode);
33130c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas            xfermode->unref();
33230c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        }
33330c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
33430c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas}
33530c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas
3360bd103497a21c2cb30fd5382cedb706cbf4941faethannicholasstatic void apply_paint_imagefilter(Json::Value& jsonPaint, SkPaint* target) {
3370bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas    if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_IMAGEFILTER)) {
3380bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas        Json::Value jsonImageFilter = jsonPaint[SKJSONCANVAS_ATTRIBUTE_IMAGEFILTER];
3390bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas        SkImageFilter* imageFilter = (SkImageFilter*) load_flattenable(jsonImageFilter);
3400bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas        if (imageFilter != nullptr) {
3410bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas            target->setImageFilter(imageFilter);
3420bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas            imageFilter->unref();
3430bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas        }
3440bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas    }
3450bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas}
3460bd103497a21c2cb30fd5382cedb706cbf4941faethannicholas
34730c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholasstatic void apply_paint_style(Json::Value& jsonPaint, SkPaint* target) {
348978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_STYLE)) {
349978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas        const char* style = jsonPaint[SKJSONCANVAS_ATTRIBUTE_STYLE].asCString();
350978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas        if (!strcmp(style, SKJSONCANVAS_STYLE_FILL)) {
35130c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas            target->setStyle(SkPaint::kFill_Style);
352978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas        }
353978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas        else if (!strcmp(style, SKJSONCANVAS_STYLE_STROKE)) {
35430c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas            target->setStyle(SkPaint::kStroke_Style);
355978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas        }
356978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas        else if (!strcmp(style, SKJSONCANVAS_STYLE_STROKEANDFILL)) {
35730c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas            target->setStyle(SkPaint::kStrokeAndFill_Style);
358978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas        }
359978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    }
36030c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas}
36130c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas
36230c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholasstatic void apply_paint_strokewidth(Json::Value& jsonPaint, SkPaint* target) {
363978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_STROKEWIDTH)) {
364978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas        float strokeWidth = jsonPaint[SKJSONCANVAS_ATTRIBUTE_STROKEWIDTH].asFloat();
36530c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        target->setStrokeWidth(strokeWidth);
36630c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
36730c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas}
36830c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas
36930c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholasstatic void apply_paint_strokemiter(Json::Value& jsonPaint, SkPaint* target) {
37030c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_STROKEMITER)) {
37130c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        float strokeMiter = jsonPaint[SKJSONCANVAS_ATTRIBUTE_STROKEMITER].asFloat();
37230c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        target->setStrokeMiter(strokeMiter);
37330c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
37430c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas}
37530c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas
37630c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholasstatic void apply_paint_cap(Json::Value& jsonPaint, SkPaint* target) {
37730c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_CAP)) {
37830c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        const char* cap = jsonPaint[SKJSONCANVAS_ATTRIBUTE_CAP].asCString();
37930c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        if (!strcmp(cap, SKJSONCANVAS_CAP_BUTT)) {
38030c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas            target->setStrokeCap(SkPaint::kButt_Cap);
38130c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        }
38230c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        else if (!strcmp(cap, SKJSONCANVAS_CAP_ROUND)) {
38330c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas            target->setStrokeCap(SkPaint::kRound_Cap);
38430c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        }
38530c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        else if (!strcmp(cap, SKJSONCANVAS_CAP_SQUARE)) {
38630c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas            target->setStrokeCap(SkPaint::kSquare_Cap);
38730c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        }
388978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    }
38930c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas}
39030c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas
39130c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholasstatic void apply_paint_antialias(Json::Value& jsonPaint, SkPaint* target) {
392978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_ANTIALIAS)) {
39330c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        target->setAntiAlias(jsonPaint[SKJSONCANVAS_ATTRIBUTE_ANTIALIAS].asBool());
394978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    }
39530c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas}
39630c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas
39730c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholasstatic void apply_paint_blur(Json::Value& jsonPaint, SkPaint* target) {
39878fc22af41a5118963a8f7253758111b05b9700eethannicholas    if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_BLUR)) {
39978fc22af41a5118963a8f7253758111b05b9700eethannicholas        Json::Value blur = jsonPaint[SKJSONCANVAS_ATTRIBUTE_BLUR];
40078fc22af41a5118963a8f7253758111b05b9700eethannicholas        SkScalar sigma = blur[SKJSONCANVAS_ATTRIBUTE_SIGMA].asFloat();
40178fc22af41a5118963a8f7253758111b05b9700eethannicholas        SkBlurStyle style;
40278fc22af41a5118963a8f7253758111b05b9700eethannicholas        const char* jsonStyle = blur[SKJSONCANVAS_ATTRIBUTE_STYLE].asCString();
40378fc22af41a5118963a8f7253758111b05b9700eethannicholas        if (!strcmp(jsonStyle, SKJSONCANVAS_BLURSTYLE_NORMAL)) {
40478fc22af41a5118963a8f7253758111b05b9700eethannicholas            style = SkBlurStyle::kNormal_SkBlurStyle;
40578fc22af41a5118963a8f7253758111b05b9700eethannicholas        }
40678fc22af41a5118963a8f7253758111b05b9700eethannicholas        else if (!strcmp(jsonStyle, SKJSONCANVAS_BLURSTYLE_SOLID)) {
40778fc22af41a5118963a8f7253758111b05b9700eethannicholas            style = SkBlurStyle::kSolid_SkBlurStyle;
40878fc22af41a5118963a8f7253758111b05b9700eethannicholas        }
40978fc22af41a5118963a8f7253758111b05b9700eethannicholas        else if (!strcmp(jsonStyle, SKJSONCANVAS_BLURSTYLE_OUTER)) {
41078fc22af41a5118963a8f7253758111b05b9700eethannicholas            style = SkBlurStyle::kOuter_SkBlurStyle;
41178fc22af41a5118963a8f7253758111b05b9700eethannicholas        }
41278fc22af41a5118963a8f7253758111b05b9700eethannicholas        else if (!strcmp(jsonStyle, SKJSONCANVAS_BLURSTYLE_INNER)) {
41378fc22af41a5118963a8f7253758111b05b9700eethannicholas            style = SkBlurStyle::kInner_SkBlurStyle;
41478fc22af41a5118963a8f7253758111b05b9700eethannicholas        }
41578fc22af41a5118963a8f7253758111b05b9700eethannicholas        else {
41678fc22af41a5118963a8f7253758111b05b9700eethannicholas            SkASSERT(false);
41778fc22af41a5118963a8f7253758111b05b9700eethannicholas            style = SkBlurStyle::kNormal_SkBlurStyle;
41878fc22af41a5118963a8f7253758111b05b9700eethannicholas        }
41978fc22af41a5118963a8f7253758111b05b9700eethannicholas        SkBlurMaskFilter::BlurFlags flags;
42078fc22af41a5118963a8f7253758111b05b9700eethannicholas        const char* jsonQuality = blur[SKJSONCANVAS_ATTRIBUTE_QUALITY].asCString();
42178fc22af41a5118963a8f7253758111b05b9700eethannicholas        if (!strcmp(jsonQuality, SKJSONCANVAS_BLURQUALITY_LOW)) {
42278fc22af41a5118963a8f7253758111b05b9700eethannicholas            flags = SkBlurMaskFilter::BlurFlags::kNone_BlurFlag;
42378fc22af41a5118963a8f7253758111b05b9700eethannicholas        }
42478fc22af41a5118963a8f7253758111b05b9700eethannicholas        else if (!strcmp(jsonQuality, SKJSONCANVAS_BLURQUALITY_HIGH)) {
42578fc22af41a5118963a8f7253758111b05b9700eethannicholas            flags = SkBlurMaskFilter::BlurFlags::kHighQuality_BlurFlag;
42678fc22af41a5118963a8f7253758111b05b9700eethannicholas        }
42778fc22af41a5118963a8f7253758111b05b9700eethannicholas        else {
42878fc22af41a5118963a8f7253758111b05b9700eethannicholas            SkASSERT(false);
42978fc22af41a5118963a8f7253758111b05b9700eethannicholas            flags = SkBlurMaskFilter::BlurFlags::kNone_BlurFlag;
43078fc22af41a5118963a8f7253758111b05b9700eethannicholas        }
43130c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        target->setMaskFilter(SkBlurMaskFilter::Create(style, sigma, flags));
43278fc22af41a5118963a8f7253758111b05b9700eethannicholas    }
43330c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas}
43430c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas
43530c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholasstatic void apply_paint_dashing(Json::Value& jsonPaint, SkPaint* target) {
43678fc22af41a5118963a8f7253758111b05b9700eethannicholas    if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_DASHING)) {
43778fc22af41a5118963a8f7253758111b05b9700eethannicholas        Json::Value dash = jsonPaint[SKJSONCANVAS_ATTRIBUTE_DASHING];
43878fc22af41a5118963a8f7253758111b05b9700eethannicholas        Json::Value jsonIntervals = dash[SKJSONCANVAS_ATTRIBUTE_INTERVALS];
43978fc22af41a5118963a8f7253758111b05b9700eethannicholas        Json::ArrayIndex count = jsonIntervals.size();
44078fc22af41a5118963a8f7253758111b05b9700eethannicholas        SkScalar* intervals = (SkScalar*) sk_malloc_throw(count * sizeof(SkScalar));
44178fc22af41a5118963a8f7253758111b05b9700eethannicholas        for (Json::ArrayIndex i = 0; i < count; i++) {
44278fc22af41a5118963a8f7253758111b05b9700eethannicholas            intervals[i] = jsonIntervals[i].asFloat();
44378fc22af41a5118963a8f7253758111b05b9700eethannicholas        }
44478fc22af41a5118963a8f7253758111b05b9700eethannicholas        SkScalar phase = dash[SKJSONCANVAS_ATTRIBUTE_PHASE].asFloat();
44530c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        target->setPathEffect(SkDashPathEffect::Create(intervals, count, phase));
44678fc22af41a5118963a8f7253758111b05b9700eethannicholas        free(intervals);
44778fc22af41a5118963a8f7253758111b05b9700eethannicholas    }
44830c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas}
44930c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas
45030c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholasstatic void apply_paint_textalign(Json::Value& jsonPaint, SkPaint* target) {
45178fc22af41a5118963a8f7253758111b05b9700eethannicholas    if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_TEXTALIGN)) {
45278fc22af41a5118963a8f7253758111b05b9700eethannicholas        SkPaint::Align textAlign;
45378fc22af41a5118963a8f7253758111b05b9700eethannicholas        const char* jsonAlign = jsonPaint[SKJSONCANVAS_ATTRIBUTE_TEXTALIGN].asCString();
45478fc22af41a5118963a8f7253758111b05b9700eethannicholas        if (!strcmp(jsonAlign, SKJSONCANVAS_ALIGN_LEFT)) {
45578fc22af41a5118963a8f7253758111b05b9700eethannicholas            textAlign = SkPaint::kLeft_Align;
45678fc22af41a5118963a8f7253758111b05b9700eethannicholas        }
45778fc22af41a5118963a8f7253758111b05b9700eethannicholas        else if (!strcmp(jsonAlign, SKJSONCANVAS_ALIGN_CENTER)) {
45878fc22af41a5118963a8f7253758111b05b9700eethannicholas            textAlign = SkPaint::kCenter_Align;
45978fc22af41a5118963a8f7253758111b05b9700eethannicholas        }
46078fc22af41a5118963a8f7253758111b05b9700eethannicholas        else if (!strcmp(jsonAlign, SKJSONCANVAS_ALIGN_RIGHT)) {
46178fc22af41a5118963a8f7253758111b05b9700eethannicholas            textAlign = SkPaint::kRight_Align;
46278fc22af41a5118963a8f7253758111b05b9700eethannicholas        }
46378fc22af41a5118963a8f7253758111b05b9700eethannicholas        else {
46478fc22af41a5118963a8f7253758111b05b9700eethannicholas            SkASSERT(false);
46578fc22af41a5118963a8f7253758111b05b9700eethannicholas            textAlign = SkPaint::kLeft_Align;
46678fc22af41a5118963a8f7253758111b05b9700eethannicholas        }
46730c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        target->setTextAlign(textAlign);
46878fc22af41a5118963a8f7253758111b05b9700eethannicholas    }
46930c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas}
47030c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas
47130c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholasstatic void apply_paint_textsize(Json::Value& jsonPaint, SkPaint* target) {
47278fc22af41a5118963a8f7253758111b05b9700eethannicholas    if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_TEXTSIZE)) {
47378fc22af41a5118963a8f7253758111b05b9700eethannicholas        float textSize = jsonPaint[SKJSONCANVAS_ATTRIBUTE_TEXTSIZE].asFloat();
47430c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        target->setTextSize(textSize);
47578fc22af41a5118963a8f7253758111b05b9700eethannicholas    }
47630c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas}
47730c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas
47830c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholasstatic void apply_paint_textscalex(Json::Value& jsonPaint, SkPaint* target) {
47978fc22af41a5118963a8f7253758111b05b9700eethannicholas    if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_TEXTSCALEX)) {
48078fc22af41a5118963a8f7253758111b05b9700eethannicholas        float textScaleX = jsonPaint[SKJSONCANVAS_ATTRIBUTE_TEXTSCALEX].asFloat();
48130c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        target->setTextScaleX(textScaleX);
48278fc22af41a5118963a8f7253758111b05b9700eethannicholas    }
48330c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas}
48430c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas
48530c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholasstatic void apply_paint_textskewx(Json::Value& jsonPaint, SkPaint* target) {
48678fc22af41a5118963a8f7253758111b05b9700eethannicholas    if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_TEXTSKEWX)) {
48778fc22af41a5118963a8f7253758111b05b9700eethannicholas        float textSkewX = jsonPaint[SKJSONCANVAS_ATTRIBUTE_TEXTSKEWX].asFloat();
48830c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        target->setTextSkewX(textSkewX);
48978fc22af41a5118963a8f7253758111b05b9700eethannicholas    }
490978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas}
491978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas
492f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholasstatic void apply_paint_typeface(Json::Value& jsonPaint, SkPaint* target) {
493f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas    if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_TYPEFACE)) {
494f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas        Json::Value jsonTypeface = jsonPaint[SKJSONCANVAS_ATTRIBUTE_TYPEFACE];
495f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas        Json::Value bytes = jsonTypeface[SKJSONCANVAS_ATTRIBUTE_BYTES];
496f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas        void* data;
497f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas        Json::ArrayIndex length = decode_data(bytes, &data);
498f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas        SkMemoryStream buffer(data, length);
499f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas        SkTypeface* typeface = SkTypeface::Deserialize(&buffer);
500f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas        free(data);
501f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas        target->setTypeface(typeface);
502f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas    }
503f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas}
504f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas
5057471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholasvoid Renderer::getPaint(Json::Value& paint, SkPaint* result) {
5067471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    apply_paint_color(paint, result);
5077471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    apply_paint_shader(paint, result);
5087471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    apply_paint_patheffect(paint, result);
5097471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    apply_paint_maskfilter(paint, result);
510f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas    apply_paint_colorfilter(paint, result);
5117471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    apply_paint_xfermode(paint, result);
5127471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    apply_paint_imagefilter(paint, result);
5137471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    apply_paint_style(paint, result);
5147471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    apply_paint_strokewidth(paint, result);
5157471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    apply_paint_strokemiter(paint, result);
5167471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    apply_paint_cap(paint, result);
5177471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    apply_paint_antialias(paint, result);
5187471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    apply_paint_blur(paint, result);
5197471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    apply_paint_dashing(paint, result);
5207471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    apply_paint_textalign(paint, result);
5217471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    apply_paint_textsize(paint, result);
5227471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    apply_paint_textscalex(paint, result);
5237471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    apply_paint_textskewx(paint, result);
524f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas    apply_paint_typeface(paint, result);
5257471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas}
5267471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas
5277471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholasvoid Renderer::getRect(Json::Value& rect, SkRect* result) {
528978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    result->set(rect[0].asFloat(), rect[1].asFloat(), rect[2].asFloat(), rect[3].asFloat());
529978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas}
530978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas
5317471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholasvoid Renderer::getRRect(Json::Value& rrect, SkRRect* result) {
532978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    SkVector radii[4] = {
533978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas                            { rrect[1][0].asFloat(), rrect[1][1].asFloat() },
534978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas                            { rrect[2][0].asFloat(), rrect[2][1].asFloat() },
535978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas                            { rrect[3][0].asFloat(), rrect[3][1].asFloat() },
536978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas                            { rrect[4][0].asFloat(), rrect[4][1].asFloat() }
537978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas                        };
538978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    result->setRectRadii(SkRect::MakeLTRB(rrect[0][0].asFloat(), rrect[0][1].asFloat(),
539978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas                                          rrect[0][2].asFloat(), rrect[0][3].asFloat()),
5407471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas                                          radii);
541978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas}
542978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas
5437471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholasvoid Renderer::getMatrix(Json::Value& matrix, SkMatrix* result) {
5447471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    SkScalar values[] = {
5457471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas        matrix[0][0].asFloat(), matrix[0][1].asFloat(), matrix[0][2].asFloat(),
5467471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas        matrix[1][0].asFloat(), matrix[1][1].asFloat(), matrix[1][2].asFloat(),
5477471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas        matrix[2][0].asFloat(), matrix[2][1].asFloat(), matrix[2][2].asFloat()
5487471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    };
5497471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    result->set9(values);
5507471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas}
5517471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas
5527471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholasvoid Renderer::getPath(Json::Value& path, SkPath* result) {
55378fc22af41a5118963a8f7253758111b05b9700eethannicholas    const char* fillType = path[SKJSONCANVAS_ATTRIBUTE_FILLTYPE].asCString();
55478fc22af41a5118963a8f7253758111b05b9700eethannicholas    if (!strcmp(fillType, SKJSONCANVAS_FILLTYPE_WINDING)) {
55578fc22af41a5118963a8f7253758111b05b9700eethannicholas        result->setFillType(SkPath::kWinding_FillType);
55678fc22af41a5118963a8f7253758111b05b9700eethannicholas    }
55778fc22af41a5118963a8f7253758111b05b9700eethannicholas    else if (!strcmp(fillType, SKJSONCANVAS_FILLTYPE_EVENODD)) {
55878fc22af41a5118963a8f7253758111b05b9700eethannicholas        result->setFillType(SkPath::kEvenOdd_FillType);
55978fc22af41a5118963a8f7253758111b05b9700eethannicholas    }
56078fc22af41a5118963a8f7253758111b05b9700eethannicholas    else if (!strcmp(fillType, SKJSONCANVAS_FILLTYPE_INVERSEWINDING)) {
56178fc22af41a5118963a8f7253758111b05b9700eethannicholas        result->setFillType(SkPath::kInverseWinding_FillType);
56278fc22af41a5118963a8f7253758111b05b9700eethannicholas    }
56378fc22af41a5118963a8f7253758111b05b9700eethannicholas    else if (!strcmp(fillType, SKJSONCANVAS_FILLTYPE_INVERSEEVENODD)) {
56478fc22af41a5118963a8f7253758111b05b9700eethannicholas        result->setFillType(SkPath::kInverseEvenOdd_FillType);
56578fc22af41a5118963a8f7253758111b05b9700eethannicholas    }
56678fc22af41a5118963a8f7253758111b05b9700eethannicholas    Json::Value verbs = path[SKJSONCANVAS_ATTRIBUTE_VERBS];
56778fc22af41a5118963a8f7253758111b05b9700eethannicholas    for (Json::ArrayIndex i = 0; i < verbs.size(); i++) {
56878fc22af41a5118963a8f7253758111b05b9700eethannicholas        Json::Value verb = verbs[i];
56978fc22af41a5118963a8f7253758111b05b9700eethannicholas        if (verb.isString()) {
57078fc22af41a5118963a8f7253758111b05b9700eethannicholas            SkASSERT(!strcmp(verb.asCString(), SKJSONCANVAS_VERB_CLOSE));
57178fc22af41a5118963a8f7253758111b05b9700eethannicholas            result->close();
57278fc22af41a5118963a8f7253758111b05b9700eethannicholas        }
57378fc22af41a5118963a8f7253758111b05b9700eethannicholas        else {
57478fc22af41a5118963a8f7253758111b05b9700eethannicholas            if (verb.isMember(SKJSONCANVAS_VERB_MOVE)) {
57578fc22af41a5118963a8f7253758111b05b9700eethannicholas                Json::Value move = verb[SKJSONCANVAS_VERB_MOVE];
57678fc22af41a5118963a8f7253758111b05b9700eethannicholas                result->moveTo(move[0].asFloat(), move[1].asFloat());
57778fc22af41a5118963a8f7253758111b05b9700eethannicholas            }
57878fc22af41a5118963a8f7253758111b05b9700eethannicholas            else if (verb.isMember(SKJSONCANVAS_VERB_LINE)) {
57978fc22af41a5118963a8f7253758111b05b9700eethannicholas                Json::Value line = verb[SKJSONCANVAS_VERB_LINE];
58078fc22af41a5118963a8f7253758111b05b9700eethannicholas                result->lineTo(line[0].asFloat(), line[1].asFloat());
58178fc22af41a5118963a8f7253758111b05b9700eethannicholas            }
58278fc22af41a5118963a8f7253758111b05b9700eethannicholas            else if (verb.isMember(SKJSONCANVAS_VERB_QUAD)) {
58378fc22af41a5118963a8f7253758111b05b9700eethannicholas                Json::Value quad = verb[SKJSONCANVAS_VERB_QUAD];
58478fc22af41a5118963a8f7253758111b05b9700eethannicholas                result->quadTo(quad[0][0].asFloat(), quad[0][1].asFloat(),
58578fc22af41a5118963a8f7253758111b05b9700eethannicholas                               quad[1][0].asFloat(), quad[1][1].asFloat());
58678fc22af41a5118963a8f7253758111b05b9700eethannicholas            }
58778fc22af41a5118963a8f7253758111b05b9700eethannicholas            else if (verb.isMember(SKJSONCANVAS_VERB_CUBIC)) {
58878fc22af41a5118963a8f7253758111b05b9700eethannicholas                Json::Value cubic = verb[SKJSONCANVAS_VERB_CUBIC];
58978fc22af41a5118963a8f7253758111b05b9700eethannicholas                result->cubicTo(cubic[0][0].asFloat(), cubic[0][1].asFloat(),
59078fc22af41a5118963a8f7253758111b05b9700eethannicholas                                cubic[1][0].asFloat(), cubic[1][1].asFloat(),
59178fc22af41a5118963a8f7253758111b05b9700eethannicholas                                cubic[2][0].asFloat(), cubic[2][1].asFloat());
59278fc22af41a5118963a8f7253758111b05b9700eethannicholas            }
59378fc22af41a5118963a8f7253758111b05b9700eethannicholas            else if (verb.isMember(SKJSONCANVAS_VERB_CONIC)) {
59478fc22af41a5118963a8f7253758111b05b9700eethannicholas                Json::Value conic = verb[SKJSONCANVAS_VERB_CONIC];
59578fc22af41a5118963a8f7253758111b05b9700eethannicholas                result->conicTo(conic[0][0].asFloat(), conic[0][1].asFloat(),
59678fc22af41a5118963a8f7253758111b05b9700eethannicholas                                conic[1][0].asFloat(), conic[1][1].asFloat(),
59778fc22af41a5118963a8f7253758111b05b9700eethannicholas                                conic[2].asFloat());
59878fc22af41a5118963a8f7253758111b05b9700eethannicholas            }
59978fc22af41a5118963a8f7253758111b05b9700eethannicholas            else {
60078fc22af41a5118963a8f7253758111b05b9700eethannicholas                SkASSERT(false);
60178fc22af41a5118963a8f7253758111b05b9700eethannicholas            }
60278fc22af41a5118963a8f7253758111b05b9700eethannicholas        }
60378fc22af41a5118963a8f7253758111b05b9700eethannicholas    }
60478fc22af41a5118963a8f7253758111b05b9700eethannicholas}
60578fc22af41a5118963a8f7253758111b05b9700eethannicholas
6067471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholasSkRegion::Op Renderer::getRegionOp(Json::Value& jsonOp) {
6077471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    const char* op = jsonOp.asCString();
60878fc22af41a5118963a8f7253758111b05b9700eethannicholas    if (!strcmp(op, SKJSONCANVAS_REGIONOP_DIFFERENCE)) {
60978fc22af41a5118963a8f7253758111b05b9700eethannicholas        return SkRegion::kDifference_Op;
61078fc22af41a5118963a8f7253758111b05b9700eethannicholas    }
61178fc22af41a5118963a8f7253758111b05b9700eethannicholas    else if (!strcmp(op, SKJSONCANVAS_REGIONOP_INTERSECT)) {
61278fc22af41a5118963a8f7253758111b05b9700eethannicholas        return SkRegion::kIntersect_Op;
61378fc22af41a5118963a8f7253758111b05b9700eethannicholas    }
61478fc22af41a5118963a8f7253758111b05b9700eethannicholas    else if (!strcmp(op, SKJSONCANVAS_REGIONOP_UNION)) {
61578fc22af41a5118963a8f7253758111b05b9700eethannicholas        return SkRegion::kUnion_Op;
61678fc22af41a5118963a8f7253758111b05b9700eethannicholas    }
61778fc22af41a5118963a8f7253758111b05b9700eethannicholas    else if (!strcmp(op, SKJSONCANVAS_REGIONOP_XOR)) {
61878fc22af41a5118963a8f7253758111b05b9700eethannicholas        return SkRegion::kXOR_Op;
61978fc22af41a5118963a8f7253758111b05b9700eethannicholas    }
62078fc22af41a5118963a8f7253758111b05b9700eethannicholas    else if (!strcmp(op, SKJSONCANVAS_REGIONOP_REVERSE_DIFFERENCE)) {
62178fc22af41a5118963a8f7253758111b05b9700eethannicholas        return SkRegion::kReverseDifference_Op;
62278fc22af41a5118963a8f7253758111b05b9700eethannicholas    }
62378fc22af41a5118963a8f7253758111b05b9700eethannicholas    else if (!strcmp(op, SKJSONCANVAS_REGIONOP_REPLACE)) {
62478fc22af41a5118963a8f7253758111b05b9700eethannicholas        return SkRegion::kReplace_Op;
62578fc22af41a5118963a8f7253758111b05b9700eethannicholas    }
62678fc22af41a5118963a8f7253758111b05b9700eethannicholas    SkASSERT(false);
62778fc22af41a5118963a8f7253758111b05b9700eethannicholas    return SkRegion::kIntersect_Op;
62878fc22af41a5118963a8f7253758111b05b9700eethannicholas}
62978fc22af41a5118963a8f7253758111b05b9700eethannicholas
6307471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholasvoid Renderer::processTranslate(Json::Value& command, SkCanvas* target) {
6317471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    target->translate(command[SKJSONCANVAS_ATTRIBUTE_X].asFloat(),
6327471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas                      command[SKJSONCANVAS_ATTRIBUTE_Y].asFloat());
6337471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas}
6347471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas
6357471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholasvoid Renderer::processScale(Json::Value& command, SkCanvas* target) {
6367471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    target->scale(command[SKJSONCANVAS_ATTRIBUTE_X].asFloat(),
6377471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas                  command[SKJSONCANVAS_ATTRIBUTE_Y].asFloat());
6387471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas}
6397471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas
640978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholasvoid Renderer::processMatrix(Json::Value& command, SkCanvas* target) {
641978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    SkMatrix matrix;
6427471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    this->getMatrix(command[SKJSONCANVAS_ATTRIBUTE_MATRIX], &matrix);
643978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    target->setMatrix(matrix);
644978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas}
645978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas
646978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholasvoid Renderer::processSave(Json::Value& command, SkCanvas* target) {
647978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    target->save();
648978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas}
649978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas
650978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholasvoid Renderer::processRestore(Json::Value& command, SkCanvas* target) {
651978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    target->restore();
652978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas}
653978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas
65430c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholasvoid Renderer::processSaveLayer(Json::Value& command, SkCanvas* target) {
65530c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    SkCanvas::SaveLayerRec rec;
65630c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    SkRect bounds;
65730c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    if (command.isMember(SKJSONCANVAS_ATTRIBUTE_BOUNDS)) {
6587471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas        this->getRect(command[SKJSONCANVAS_ATTRIBUTE_BOUNDS], &bounds);
65930c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        rec.fBounds = &bounds;
66030c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
66130c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    SkPaint paint;
66230c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    if (command.isMember(SKJSONCANVAS_ATTRIBUTE_PAINT)) {
6637471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas        this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
66430c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        rec.fPaint = &paint;
66530c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
66630c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    if (command.isMember(SKJSONCANVAS_ATTRIBUTE_BACKDROP)) {
66730c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        rec.fBackdrop = (SkImageFilter*) load_flattenable(command[SKJSONCANVAS_ATTRIBUTE_BACKDROP]);
66830c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
66930c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    target->saveLayer(rec);
67030c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    if (rec.fBackdrop != nullptr) {
67130c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        rec.fBackdrop->unref();
67230c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
67330c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas}
67430c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas
675978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholasvoid Renderer::processPaint(Json::Value& command, SkCanvas* target) {
676978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    SkPaint paint;
6777471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
678978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    target->drawPaint(paint);
679978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas}
680978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas
681978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholasvoid Renderer::processRect(Json::Value& command, SkCanvas* target) {
682978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    SkRect rect;
6837471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    this->getRect(command[SKJSONCANVAS_ATTRIBUTE_COORDS], &rect);
684978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    SkPaint paint;
6857471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
686978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    target->drawRect(rect, paint);
687978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas}
688978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas
689978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholasvoid Renderer::processRRect(Json::Value& command, SkCanvas* target) {
690978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    SkRRect rrect;
6917471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    this->getRRect(command[SKJSONCANVAS_ATTRIBUTE_COORDS], &rrect);
692978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    SkPaint paint;
6937471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
694978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    target->drawRRect(rrect, paint);
695978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas}
696978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas
697978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholasvoid Renderer::processOval(Json::Value& command, SkCanvas* target) {
698978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    SkRect rect;
6997471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    this->getRect(command[SKJSONCANVAS_ATTRIBUTE_COORDS], &rect);
700978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    SkPaint paint;
7017471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
702978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    target->drawOval(rect, paint);
703978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas}
704978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas
705978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholasvoid Renderer::processPath(Json::Value& command, SkCanvas* target) {
706978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    SkPath path;
7077471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    this->getPath(command[SKJSONCANVAS_ATTRIBUTE_PATH], &path);
708978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    SkPaint paint;
7097471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
710978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    target->drawPath(path, paint);
711978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas}
712978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas
713978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholasvoid Renderer::processText(Json::Value& command, SkCanvas* target) {
714978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    const char* text = command[SKJSONCANVAS_ATTRIBUTE_TEXT].asCString();
715978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    SkPaint paint;
7167471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
717978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    Json::Value coords = command[SKJSONCANVAS_ATTRIBUTE_COORDS];
718978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    target->drawText(text, strlen(text), coords[0].asFloat(), coords[1].asFloat(), paint);
719978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas}
720978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas
72178fc22af41a5118963a8f7253758111b05b9700eethannicholasvoid Renderer::processPosText(Json::Value& command, SkCanvas* target) {
72278fc22af41a5118963a8f7253758111b05b9700eethannicholas    const char* text = command[SKJSONCANVAS_ATTRIBUTE_TEXT].asCString();
72378fc22af41a5118963a8f7253758111b05b9700eethannicholas    SkPaint paint;
7247471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
72578fc22af41a5118963a8f7253758111b05b9700eethannicholas    Json::Value coords = command[SKJSONCANVAS_ATTRIBUTE_COORDS];
72678fc22af41a5118963a8f7253758111b05b9700eethannicholas    int count = (int) coords.size();
72778fc22af41a5118963a8f7253758111b05b9700eethannicholas    SkPoint* points = (SkPoint*) sk_malloc_throw(count * sizeof(SkPoint));
72878fc22af41a5118963a8f7253758111b05b9700eethannicholas    for (int i = 0; i < count; i++) {
72978fc22af41a5118963a8f7253758111b05b9700eethannicholas        points[i] = SkPoint::Make(coords[i][0].asFloat(), coords[i][1].asFloat());
73078fc22af41a5118963a8f7253758111b05b9700eethannicholas    }
73178fc22af41a5118963a8f7253758111b05b9700eethannicholas    target->drawPosText(text, strlen(text), points, paint);
73278fc22af41a5118963a8f7253758111b05b9700eethannicholas    free(points);
73378fc22af41a5118963a8f7253758111b05b9700eethannicholas}
73478fc22af41a5118963a8f7253758111b05b9700eethannicholas
7357471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholasvoid Renderer::processTextOnPath(Json::Value& command, SkCanvas* target) {
7367471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    const char* text = command[SKJSONCANVAS_ATTRIBUTE_TEXT].asCString();
7377471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    SkPath path;
7387471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    this->getPath(command[SKJSONCANVAS_ATTRIBUTE_PATH], &path);
7397471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    SkMatrix* matrixPtr;
7407471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    SkMatrix matrix;
7417471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    if (command.isMember(SKJSONCANVAS_ATTRIBUTE_MATRIX)) {
7427471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas        this->getMatrix(command[SKJSONCANVAS_ATTRIBUTE_MATRIX], &matrix);
7437471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas        matrixPtr = &matrix;
7447471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    }
7457471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    else {
7467471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas        matrixPtr = nullptr;
7477471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    }
7487471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    SkPaint paint;
7497471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
7507471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    target->drawTextOnPath(text, strlen(text), path, matrixPtr, paint);
7517471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas}
7527471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas
753f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholasvoid Renderer::processTextBlob(Json::Value& command, SkCanvas* target) {
754f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas    SkTextBlobBuilder builder;
755f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas    Json::Value runs = command[SKJSONCANVAS_ATTRIBUTE_RUNS];
756f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas    for (Json::ArrayIndex i = 0 ; i < runs.size(); i++) {
757f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas        Json::Value run = runs[i];
758f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas        SkPaint font;
759f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas        font.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
760f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas        this->getPaint(run[SKJSONCANVAS_ATTRIBUTE_FONT], &font);
761f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas        Json::Value glyphs = run[SKJSONCANVAS_ATTRIBUTE_GLYPHS];
762f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas        int count = glyphs.size();
763f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas        Json::Value coords = run[SKJSONCANVAS_ATTRIBUTE_COORDS];
764f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas        SkScalar x = coords[0].asFloat();
765f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas        SkScalar y = coords[1].asFloat();
766f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas        if (run.isMember(SKJSONCANVAS_ATTRIBUTE_POSITIONS)) {
767f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas            Json::Value positions = run[SKJSONCANVAS_ATTRIBUTE_POSITIONS];
768f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas            if (positions.size() > 0 && positions[0].isNumeric()) {
769f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas                SkTextBlobBuilder::RunBuffer buffer = builder.allocRunPosH(font, count, y);
770f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas                for (int j = 0; j < count; j++) {
771f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas                    buffer.glyphs[j] = glyphs[j].asUInt();
772f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas                    buffer.pos[j] = positions[j].asFloat();
773f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas                }
774f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas            }
775f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas            else {
776f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas                SkTextBlobBuilder::RunBuffer buffer = builder.allocRunPos(font, count);
777f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas                for (int j = 0; j < count; j++) {
778f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas                    buffer.glyphs[j] = glyphs[j].asUInt();
779f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas                    buffer.pos[j * 2] = positions[j][0].asFloat();
780f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas                    buffer.pos[j * 2 + 1] = positions[j][1].asFloat();
781f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas                }
782f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas            }
783f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas        }
784f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas        else {
785f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas            SkTextBlobBuilder::RunBuffer buffer = builder.allocRun(font, count, x, y);
786f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas            for (int j = 0; j < count; j++) {
787f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas                buffer.glyphs[j] = glyphs[j].asUInt();
788f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas            }
789f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas        }
790f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas    }
791f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas    SkScalar x = command[SKJSONCANVAS_ATTRIBUTE_X].asFloat();
792f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas    SkScalar y = command[SKJSONCANVAS_ATTRIBUTE_Y].asFloat();
793f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas    SkPaint paint;
794f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas    this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
795f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas    target->drawTextBlob(builder.build(), x, y, paint);
796f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas}
797f6a84bdb477f1430b575d9e5743d055c0c170265ethannicholas
798978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholasvoid Renderer::processPoints(Json::Value& command, SkCanvas* target) {
799978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    SkCanvas::PointMode mode;
800978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    const char* jsonMode = command[SKJSONCANVAS_ATTRIBUTE_MODE].asCString();
801978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    if (!strcmp(jsonMode, SKJSONCANVAS_POINTMODE_POINTS)) {
802978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas        mode = SkCanvas::kPoints_PointMode;
803978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    }
804978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    else if (!strcmp(jsonMode, SKJSONCANVAS_POINTMODE_LINES)) {
805978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas        mode = SkCanvas::kLines_PointMode;
806978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    }
807978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    else if (!strcmp(jsonMode, SKJSONCANVAS_POINTMODE_POLYGON)) {
808978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas        mode = SkCanvas::kPolygon_PointMode;
809978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    }
810978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    else {
811978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas        SkASSERT(false);
812978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas        return;
813978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    }
814978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    Json::Value jsonPoints = command[SKJSONCANVAS_ATTRIBUTE_POINTS];
815978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    int count = (int) jsonPoints.size();
816978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    SkPoint* points = (SkPoint*) sk_malloc_throw(count * sizeof(SkPoint));
817978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    for (int i = 0; i < count; i++) {
818978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas        points[i] = SkPoint::Make(jsonPoints[i][0].asFloat(), jsonPoints[i][1].asFloat());
819978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    }
820978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    SkPaint paint;
8217471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
822978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    target->drawPoints(mode, count, points, paint);
823978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    free(points);
824978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas}
825978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas
826978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholasvoid Renderer::processClipRect(Json::Value& command, SkCanvas* target) {
827978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    SkRect rect;
8287471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    this->getRect(command[SKJSONCANVAS_ATTRIBUTE_COORDS], &rect);
8297471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    target->clipRect(rect, this->getRegionOp(command[SKJSONCANVAS_ATTRIBUTE_REGIONOP]),
83078fc22af41a5118963a8f7253758111b05b9700eethannicholas                     command[SKJSONCANVAS_ATTRIBUTE_ANTIALIAS].asBool());
83178fc22af41a5118963a8f7253758111b05b9700eethannicholas}
83278fc22af41a5118963a8f7253758111b05b9700eethannicholas
83378fc22af41a5118963a8f7253758111b05b9700eethannicholasvoid Renderer::processClipRRect(Json::Value& command, SkCanvas* target) {
83478fc22af41a5118963a8f7253758111b05b9700eethannicholas    SkRRect rrect;
8357471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    this->getRRect(command[SKJSONCANVAS_ATTRIBUTE_COORDS], &rrect);
8367471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    target->clipRRect(rrect, this->getRegionOp(command[SKJSONCANVAS_ATTRIBUTE_REGIONOP]),
83778fc22af41a5118963a8f7253758111b05b9700eethannicholas                      command[SKJSONCANVAS_ATTRIBUTE_ANTIALIAS].asBool());
83878fc22af41a5118963a8f7253758111b05b9700eethannicholas}
83978fc22af41a5118963a8f7253758111b05b9700eethannicholas
84078fc22af41a5118963a8f7253758111b05b9700eethannicholasvoid Renderer::processClipPath(Json::Value& command, SkCanvas* target) {
84178fc22af41a5118963a8f7253758111b05b9700eethannicholas    SkPath path;
8427471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    this->getPath(command[SKJSONCANVAS_ATTRIBUTE_PATH], &path);
8437471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    target->clipPath(path, this->getRegionOp(command[SKJSONCANVAS_ATTRIBUTE_REGIONOP]),
84478fc22af41a5118963a8f7253758111b05b9700eethannicholas                     command[SKJSONCANVAS_ATTRIBUTE_ANTIALIAS].asBool());
845978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas}
846978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas
84730c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholasvoid Renderer::processImage(Json::Value& command, SkCanvas* target) {
84830c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    SkImage* image = load_image(command[SKJSONCANVAS_ATTRIBUTE_IMAGE]);
84930c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    if (image == nullptr) {
85030c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        return;
85130c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
85230c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    Json::Value point = command[SKJSONCANVAS_ATTRIBUTE_COORDS];
85330c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    SkPaint* paintPtr;
85430c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    SkPaint paint;
85530c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    if (command.isMember(SKJSONCANVAS_ATTRIBUTE_PAINT)) {
8567471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas        this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
85730c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        paintPtr = &paint;
85830c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
85930c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    else {
86030c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        paintPtr = nullptr;
86130c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
86230c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    target->drawImage(image, point[0].asFloat(), point[1].asFloat(), paintPtr);
86330c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    image->unref();
86430c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas}
86530c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas
86630c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholasvoid Renderer::processImageRect(Json::Value& command, SkCanvas* target) {
86730c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    SkImage* image = load_image(command[SKJSONCANVAS_ATTRIBUTE_IMAGE]);
86830c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    if (image == nullptr) {
86930c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        return;
87030c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
87130c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    SkRect dst;
8727471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    this->getRect(command[SKJSONCANVAS_ATTRIBUTE_DST], &dst);
87330c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    SkPaint* paintPtr;
87430c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    SkPaint paint;
87530c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    if (command.isMember(SKJSONCANVAS_ATTRIBUTE_PAINT)) {
8767471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas        this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
87730c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        paintPtr = &paint;
87830c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
87930c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    else {
88030c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        paintPtr = nullptr;
88130c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
88230c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    SkCanvas::SrcRectConstraint constraint;
88330c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    if (command.isMember(SKJSONCANVAS_ATTRIBUTE_STRICT) &&
88430c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        command[SKJSONCANVAS_ATTRIBUTE_STRICT].asBool()) {
88530c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        constraint = SkCanvas::kStrict_SrcRectConstraint;
88630c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
88730c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    else {
88830c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        constraint = SkCanvas::kFast_SrcRectConstraint;
88930c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
89030c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    if (command.isMember(SKJSONCANVAS_ATTRIBUTE_SRC)) {
89130c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        SkRect src;
8927471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas        this->getRect(command[SKJSONCANVAS_ATTRIBUTE_SRC], &src);
89330c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        target->drawImageRect(image, src, dst, paintPtr, constraint);
89430c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
89530c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    else {
89630c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        target->drawImageRect(image, dst, paintPtr, constraint);
89730c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
89830c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    image->unref();
89930c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas}
90030c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas
90130c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholasvoid Renderer::processBitmap(Json::Value& command, SkCanvas* target) {
90230c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    SkImage* image = load_image(command[SKJSONCANVAS_ATTRIBUTE_BITMAP]);
90330c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    if (image == nullptr) {
90430c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        return;
90530c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
90630c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    Json::Value point = command[SKJSONCANVAS_ATTRIBUTE_COORDS];
90730c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    SkPaint* paintPtr;
90830c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    SkPaint paint;
90930c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    if (command.isMember(SKJSONCANVAS_ATTRIBUTE_PAINT)) {
9107471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas        this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
91130c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        paintPtr = &paint;
91230c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
91330c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    else {
91430c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        paintPtr = nullptr;
91530c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
91630c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    target->drawImage(image, point[0].asFloat(), point[1].asFloat(), paintPtr);
91730c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    image->unref();
91830c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas}
91930c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas
92030c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholasvoid Renderer::processBitmapRect(Json::Value& command, SkCanvas* target) {
92130c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    SkBitmap* bitmap = load_bitmap(command[SKJSONCANVAS_ATTRIBUTE_BITMAP]);
92230c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    if (bitmap == nullptr) {
92330c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        return;
92430c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
92530c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    SkRect dst;
9267471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas    this->getRect(command[SKJSONCANVAS_ATTRIBUTE_DST], &dst);
92730c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    SkPaint* paintPtr;
92830c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    SkPaint paint;
92930c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    if (command.isMember(SKJSONCANVAS_ATTRIBUTE_PAINT)) {
9307471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas        this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
93130c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        paintPtr = &paint;
93230c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
93330c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    else {
93430c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        paintPtr = nullptr;
93530c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
93630c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    SkCanvas::SrcRectConstraint constraint;
93730c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    if (command.isMember(SKJSONCANVAS_ATTRIBUTE_STRICT) &&
93830c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        command[SKJSONCANVAS_ATTRIBUTE_STRICT].asBool()) {
93930c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        constraint = SkCanvas::kStrict_SrcRectConstraint;
94030c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
94130c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    else {
94230c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        constraint = SkCanvas::kFast_SrcRectConstraint;
94330c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
94430c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    if (command.isMember(SKJSONCANVAS_ATTRIBUTE_SRC)) {
94530c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        SkRect src;
9467471c780d48afd4dc02ed45c60a2fd2efa9e5a84ethannicholas        this->getRect(command[SKJSONCANVAS_ATTRIBUTE_SRC], &src);
94730c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        target->drawBitmapRect(*bitmap, src, dst, paintPtr, constraint);
94830c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
94930c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    else {
95030c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas        target->drawBitmapRect(*bitmap, dst, paintPtr, constraint);
95130c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    }
95230c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas    free(bitmap);
95330c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas}
95430c5dde90d099c7651b5f77f5b1b7a485fd69dc9ethannicholas
955978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholasvoid render(const char* json, SkCanvas* target) {
956978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    Renderer renderer;
957978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    Json::Reader reader;
958978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    Json::Value root;
959978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    if (reader.parse(std::string(json), root)) {
960978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas        SkASSERT(root[SKJSONCANVAS_VERSION].asInt() == 1);
961978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas        Json::Value commands = root[SKJSONCANVAS_COMMANDS];
962978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas        for (Json::ArrayIndex i = 0; i < commands.size(); i++) {
963978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas            renderer.processCommand(commands[i], target);
964978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas        }
965978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    }
966978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    else {
967978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas        SkDebugf(json);
968978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas        SkFAIL("json parse failure");
969978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas    }
970978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas}
971978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas
972978d08a4a90d69961bd53811ed3ab222b88e2d30ethannicholas} // namespace
973