blob: a44503af5e5ae1bbdea208a68fec7b7311cdecbf [file] [log] [blame]
ethannicholas978d08a2016-01-26 07:47:57 -08001/*
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"
ethannicholas78fc22a2016-01-29 07:15:08 -08009
10#include "SkBlurMaskFilter.h"
11#include "SkDashPathEffect.h"
ethannicholas978d08a2016-01-26 07:47:57 -080012#include "SkJSONCanvas.h"
13#include "SkJSONCPP.h"
14#include "SkPath.h"
ethannicholas30c5dde2016-02-02 08:36:58 -080015#include "SkValidatingReadBuffer.h"
ethannicholas978d08a2016-01-26 07:47:57 -080016
17namespace SkJSONRenderer {
18
19class Renderer {
20public:
ethannicholas7471c782016-02-04 10:37:50 -080021 void getPaint(Json::Value& paint, SkPaint* result);
ethannicholas978d08a2016-01-26 07:47:57 -080022
ethannicholas7471c782016-02-04 10:37:50 -080023 void getRect(Json::Value& rect, SkRect* result);
ethannicholas978d08a2016-01-26 07:47:57 -080024
ethannicholas7471c782016-02-04 10:37:50 -080025 void getRRect(Json::Value& rrect, SkRRect* result);
ethannicholas978d08a2016-01-26 07:47:57 -080026
ethannicholas7471c782016-02-04 10:37:50 -080027 void getPath(Json::Value& path, SkPath* result);
ethannicholas78fc22a2016-01-29 07:15:08 -080028
ethannicholas7471c782016-02-04 10:37:50 -080029 void getMatrix(Json::Value& matrix, SkMatrix* result);
30
31 SkRegion::Op getRegionOp(Json::Value& op);
ethannicholas78fc22a2016-01-29 07:15:08 -080032
ethannicholas978d08a2016-01-26 07:47:57 -080033 void processCommand(Json::Value& command, SkCanvas* target);
34
ethannicholas7471c782016-02-04 10:37:50 -080035 void processTranslate(Json::Value& command, SkCanvas* target);
36
37 void processScale(Json::Value& command, SkCanvas* target);
38
ethannicholas978d08a2016-01-26 07:47:57 -080039 void processMatrix(Json::Value& command, SkCanvas* target);
40
41 void processSave(Json::Value& command, SkCanvas* target);
42
43 void processRestore(Json::Value& command, SkCanvas* target);
44
ethannicholas30c5dde2016-02-02 08:36:58 -080045 void processSaveLayer(Json::Value& command, SkCanvas* target);
46
ethannicholas978d08a2016-01-26 07:47:57 -080047 void processPaint(Json::Value& command, SkCanvas* target);
48
49 void processRect(Json::Value& command, SkCanvas* target);
50
51 void processRRect(Json::Value& command, SkCanvas* target);
52
53 void processOval(Json::Value& command, SkCanvas* target);
54
55 void processPath(Json::Value& command, SkCanvas* target);
56
57 void processText(Json::Value& command, SkCanvas* target);
58
ethannicholas78fc22a2016-01-29 07:15:08 -080059 void processPosText(Json::Value& command, SkCanvas* target);
60
ethannicholas7471c782016-02-04 10:37:50 -080061 void processTextOnPath(Json::Value& command, SkCanvas* target);
62
ethannicholas978d08a2016-01-26 07:47:57 -080063 void processPoints(Json::Value& command, SkCanvas* target);
64
ethannicholas30c5dde2016-02-02 08:36:58 -080065 void processImage(Json::Value& command, SkCanvas* target);
66
67 void processImageRect(Json::Value& command, SkCanvas* target);
68
69 void processBitmap(Json::Value& command, SkCanvas* target);
70
71 void processBitmapRect(Json::Value& command, SkCanvas* target);
72
ethannicholas978d08a2016-01-26 07:47:57 -080073 void processClipRect(Json::Value& command, SkCanvas* target);
ethannicholas78fc22a2016-01-29 07:15:08 -080074
75 void processClipRRect(Json::Value& command, SkCanvas* target);
76
77 void processClipPath(Json::Value& command, SkCanvas* target);
ethannicholas978d08a2016-01-26 07:47:57 -080078};
79
80void Renderer::processCommand(Json::Value& command, SkCanvas* target) {
81 const char* name = command[SKJSONCANVAS_COMMAND].asCString();
82 // TODO speed this up with a hash
ethannicholas7471c782016-02-04 10:37:50 -080083 if (!strcmp(name, SKJSONCANVAS_COMMAND_TRANSLATE)) {
84 this->processTranslate(command, target);
85 }
86 else if (!strcmp(name, SKJSONCANVAS_COMMAND_SCALE)) {
87 this->processScale(command, target);
88 }
89 else if (!strcmp(name, SKJSONCANVAS_COMMAND_MATRIX)) {
ethannicholas978d08a2016-01-26 07:47:57 -080090 this->processMatrix(command, target);
91 }
92 else if (!strcmp(name, SKJSONCANVAS_COMMAND_SAVE)) {
93 this->processSave(command, target);
94 }
95 else if (!strcmp(name, SKJSONCANVAS_COMMAND_RESTORE)) {
96 this->processRestore(command, target);
97 }
ethannicholas30c5dde2016-02-02 08:36:58 -080098 else if (!strcmp(name, SKJSONCANVAS_COMMAND_SAVELAYER)) {
99 this->processSaveLayer(command, target);
100 }
ethannicholas978d08a2016-01-26 07:47:57 -0800101 else if (!strcmp(name, SKJSONCANVAS_COMMAND_PAINT)) {
102 this->processPaint(command, target);
103 }
104 else if (!strcmp(name, SKJSONCANVAS_COMMAND_RECT)) {
105 this->processRect(command, target);
106 }
107 else if (!strcmp(name, SKJSONCANVAS_COMMAND_RRECT)) {
108 this->processRRect(command, target);
109 }
110 else if (!strcmp(name, SKJSONCANVAS_COMMAND_OVAL)) {
111 this->processOval(command, target);
112 }
113 else if (!strcmp(name, SKJSONCANVAS_COMMAND_PATH)) {
114 this->processPath(command, target);
115 }
116 else if (!strcmp(name, SKJSONCANVAS_COMMAND_TEXT)) {
117 this->processText(command, target);
118 }
ethannicholas78fc22a2016-01-29 07:15:08 -0800119 else if (!strcmp(name, SKJSONCANVAS_COMMAND_POSTEXT)) {
120 this->processPosText(command, target);
121 }
ethannicholas7471c782016-02-04 10:37:50 -0800122 else if (!strcmp(name, SKJSONCANVAS_COMMAND_TEXTONPATH)) {
123 this->processTextOnPath(command, target);
124 }
ethannicholas978d08a2016-01-26 07:47:57 -0800125 else if (!strcmp(name, SKJSONCANVAS_COMMAND_POINTS)) {
126 this->processPoints(command, target);
127 }
ethannicholas30c5dde2016-02-02 08:36:58 -0800128 else if (!strcmp(name, SKJSONCANVAS_COMMAND_IMAGE)) {
129 this->processImage(command, target);
130 }
131 else if (!strcmp(name, SKJSONCANVAS_COMMAND_IMAGERECT)) {
132 this->processImageRect(command, target);
133 }
134 else if (!strcmp(name, SKJSONCANVAS_COMMAND_BITMAP)) {
135 this->processBitmap(command, target);
136 }
137 else if (!strcmp(name, SKJSONCANVAS_COMMAND_BITMAPRECT)) {
138 this->processBitmapRect(command, target);
139 }
ethannicholas978d08a2016-01-26 07:47:57 -0800140 else if (!strcmp(name, SKJSONCANVAS_COMMAND_CLIPRECT)) {
141 this->processClipRect(command, target);
142 }
ethannicholas78fc22a2016-01-29 07:15:08 -0800143 else if (!strcmp(name, SKJSONCANVAS_COMMAND_CLIPRRECT)) {
144 this->processClipRRect(command, target);
145 }
146 else if (!strcmp(name, SKJSONCANVAS_COMMAND_CLIPPATH)) {
147 this->processClipPath(command, target);
148 }
ethannicholas978d08a2016-01-26 07:47:57 -0800149 else {
150 SkDebugf("unsupported JSON command: %s\n", name);
151 }
152}
153
ethannicholas30c5dde2016-02-02 08:36:58 -0800154static void apply_paint_color(Json::Value& jsonPaint, SkPaint* target) {
ethannicholas978d08a2016-01-26 07:47:57 -0800155 if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_COLOR)) {
156 Json::Value color = jsonPaint[SKJSONCANVAS_ATTRIBUTE_COLOR];
ethannicholas30c5dde2016-02-02 08:36:58 -0800157 target->setColor(SkColorSetARGB(color[0].asInt(), color[1].asInt(), color[2].asInt(),
ethannicholas978d08a2016-01-26 07:47:57 -0800158 color[3].asInt()));
159 }
ethannicholas30c5dde2016-02-02 08:36:58 -0800160}
161
162// note that the caller is responsible for freeing the pointer
163static Json::ArrayIndex decode_data(Json::Value bytes, void** target) {
164 Json::ArrayIndex size = bytes.size();
165 *target = sk_malloc_throw(size);
166 for (Json::ArrayIndex i = 0; i < size; i++) {
167 ((uint8_t*) *target)[i] = bytes[i].asInt();
168 }
169 return size;
170}
171
172static SkFlattenable* load_flattenable(Json::Value jsonFlattenable) {
173 if (!jsonFlattenable.isMember(SKJSONCANVAS_ATTRIBUTE_NAME)) {
174 return nullptr;
175 }
176 const char* name = jsonFlattenable[SKJSONCANVAS_ATTRIBUTE_NAME].asCString();
177 SkFlattenable::Factory factory = SkFlattenable::NameToFactory(name);
178 if (factory == nullptr) {
ethannicholas0bd10342016-02-04 06:45:25 -0800179 SkDebugf("no factory for loading '%s'\n", name);
ethannicholas30c5dde2016-02-02 08:36:58 -0800180 return nullptr;
181 }
182 void* data;
183 int size = decode_data(jsonFlattenable[SKJSONCANVAS_ATTRIBUTE_BYTES], &data);
184 SkValidatingReadBuffer buffer(data, size);
185 SkFlattenable* result = factory(buffer);
186 free(data);
187 if (!buffer.isValid()) {
ethannicholas0bd10342016-02-04 06:45:25 -0800188 SkDebugf("invalid buffer loading flattenable\n");
ethannicholas30c5dde2016-02-02 08:36:58 -0800189 return nullptr;
190 }
191 return result;
192}
193
ethannicholas0bd10342016-02-04 06:45:25 -0800194static SkColorType colortype_from_name(const char* name) {
195 if (!strcmp(name, SKJSONCANVAS_COLORTYPE_ARGB4444)) {
196 return kARGB_4444_SkColorType;
197 }
198 else if (!strcmp(name, SKJSONCANVAS_COLORTYPE_RGBA8888)) {
199 return kRGBA_8888_SkColorType;
200 }
201 else if (!strcmp(name, SKJSONCANVAS_COLORTYPE_BGRA8888)) {
202 return kBGRA_8888_SkColorType;
203 }
204 else if (!strcmp(name, SKJSONCANVAS_COLORTYPE_565)) {
205 return kRGB_565_SkColorType;
206 }
207 else if (!strcmp(name, SKJSONCANVAS_COLORTYPE_GRAY8)) {
208 return kGray_8_SkColorType;
209 }
210 else if (!strcmp(name, SKJSONCANVAS_COLORTYPE_INDEX8)) {
211 return kIndex_8_SkColorType;
212 }
213 else if (!strcmp(name, SKJSONCANVAS_COLORTYPE_ALPHA8)) {
214 return kAlpha_8_SkColorType;
215 }
216 SkASSERT(false);
217 return kN32_SkColorType;
218}
219
220static SkBitmap* convert_colortype(SkBitmap* bitmap, SkColorType colorType) {
221 if (bitmap->colorType() == colorType ) {
222 return bitmap;
223 }
224 SkBitmap* dst = new SkBitmap();
225 if (bitmap->copyTo(dst, colorType)) {
226 delete bitmap;
227 return dst;
228 }
229 SkASSERT(false);
230 delete dst;
231 return bitmap;
232}
233
ethannicholas30c5dde2016-02-02 08:36:58 -0800234// caller is responsible for freeing return value
ethannicholas0bd10342016-02-04 06:45:25 -0800235static SkBitmap* load_bitmap(const Json::Value& jsonBitmap) {
ethannicholas30c5dde2016-02-02 08:36:58 -0800236 if (!jsonBitmap.isMember(SKJSONCANVAS_ATTRIBUTE_BYTES)) {
ethannicholas0bd10342016-02-04 06:45:25 -0800237 SkDebugf("invalid bitmap\n");
ethannicholas30c5dde2016-02-02 08:36:58 -0800238 return nullptr;
239 }
240 void* data;
241 int size = decode_data(jsonBitmap[SKJSONCANVAS_ATTRIBUTE_BYTES], &data);
242 SkMemoryStream stream(data, size);
243 SkImageDecoder* decoder = SkImageDecoder::Factory(&stream);
244 SkBitmap* bitmap = new SkBitmap();
245 SkImageDecoder::Result result = decoder->decode(&stream, bitmap,
246 SkImageDecoder::kDecodePixels_Mode);
247 free(decoder);
248 if (result != SkImageDecoder::kFailure) {
249 free(data);
ethannicholas0bd10342016-02-04 06:45:25 -0800250 if (jsonBitmap.isMember(SKJSONCANVAS_ATTRIBUTE_COLOR)) {
251 const char* ctName = jsonBitmap[SKJSONCANVAS_ATTRIBUTE_COLOR].asCString();
252 SkColorType ct = colortype_from_name(ctName);
253 if (ct != kIndex_8_SkColorType) {
254 bitmap = convert_colortype(bitmap, ct);
255 }
256 }
ethannicholas30c5dde2016-02-02 08:36:58 -0800257 return bitmap;
258 }
ethannicholas0bd10342016-02-04 06:45:25 -0800259 SkDebugf("image decode failed\n");
ethannicholas30c5dde2016-02-02 08:36:58 -0800260 free(data);
261 return nullptr;
262}
263
ethannicholas0bd10342016-02-04 06:45:25 -0800264static SkImage* load_image(const Json::Value& jsonImage) {
ethannicholas30c5dde2016-02-02 08:36:58 -0800265 SkBitmap* bitmap = load_bitmap(jsonImage);
266 if (bitmap == nullptr) {
267 return nullptr;
268 }
269 SkImage* result = SkImage::NewFromBitmap(*bitmap);
ethannicholas0bd10342016-02-04 06:45:25 -0800270 delete bitmap;
ethannicholas30c5dde2016-02-02 08:36:58 -0800271 return result;
272}
273
274static void apply_paint_shader(Json::Value& jsonPaint, SkPaint* target) {
275 if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_SHADER)) {
276 Json::Value jsonShader = jsonPaint[SKJSONCANVAS_ATTRIBUTE_SHADER];
277 SkShader* shader = (SkShader*) load_flattenable(jsonShader);
278 if (shader != nullptr) {
279 target->setShader(shader);
280 shader->unref();
281 }
282 }
283}
284
285static void apply_paint_patheffect(Json::Value& jsonPaint, SkPaint* target) {
286 if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_PATHEFFECT)) {
287 Json::Value jsonPathEffect = jsonPaint[SKJSONCANVAS_ATTRIBUTE_PATHEFFECT];
288 SkPathEffect* pathEffect = (SkPathEffect*) load_flattenable(jsonPathEffect);
289 if (pathEffect != nullptr) {
290 target->setPathEffect(pathEffect);
291 pathEffect->unref();
292 }
293 }
294}
295
296static void apply_paint_maskfilter(Json::Value& jsonPaint, SkPaint* target) {
297 if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_MASKFILTER)) {
298 Json::Value jsonMaskFilter = jsonPaint[SKJSONCANVAS_ATTRIBUTE_MASKFILTER];
299 SkMaskFilter* maskFilter = (SkMaskFilter*) load_flattenable(jsonMaskFilter);
300 if (maskFilter != nullptr) {
301 target->setMaskFilter(maskFilter);
302 maskFilter->unref();
303 }
304 }
305}
306
307static void apply_paint_xfermode(Json::Value& jsonPaint, SkPaint* target) {
308 if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_XFERMODE)) {
309 Json::Value jsonXfermode = jsonPaint[SKJSONCANVAS_ATTRIBUTE_XFERMODE];
310 SkXfermode* xfermode = (SkXfermode*) load_flattenable(jsonXfermode);
311 if (xfermode != nullptr) {
312 target->setXfermode(xfermode);
313 xfermode->unref();
314 }
315 }
316}
317
ethannicholas0bd10342016-02-04 06:45:25 -0800318static void apply_paint_imagefilter(Json::Value& jsonPaint, SkPaint* target) {
319 if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_IMAGEFILTER)) {
320 Json::Value jsonImageFilter = jsonPaint[SKJSONCANVAS_ATTRIBUTE_IMAGEFILTER];
321 SkImageFilter* imageFilter = (SkImageFilter*) load_flattenable(jsonImageFilter);
322 if (imageFilter != nullptr) {
323 target->setImageFilter(imageFilter);
324 imageFilter->unref();
325 }
326 }
327}
328
ethannicholas30c5dde2016-02-02 08:36:58 -0800329static void apply_paint_style(Json::Value& jsonPaint, SkPaint* target) {
ethannicholas978d08a2016-01-26 07:47:57 -0800330 if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_STYLE)) {
331 const char* style = jsonPaint[SKJSONCANVAS_ATTRIBUTE_STYLE].asCString();
332 if (!strcmp(style, SKJSONCANVAS_STYLE_FILL)) {
ethannicholas30c5dde2016-02-02 08:36:58 -0800333 target->setStyle(SkPaint::kFill_Style);
ethannicholas978d08a2016-01-26 07:47:57 -0800334 }
335 else if (!strcmp(style, SKJSONCANVAS_STYLE_STROKE)) {
ethannicholas30c5dde2016-02-02 08:36:58 -0800336 target->setStyle(SkPaint::kStroke_Style);
ethannicholas978d08a2016-01-26 07:47:57 -0800337 }
338 else if (!strcmp(style, SKJSONCANVAS_STYLE_STROKEANDFILL)) {
ethannicholas30c5dde2016-02-02 08:36:58 -0800339 target->setStyle(SkPaint::kStrokeAndFill_Style);
ethannicholas978d08a2016-01-26 07:47:57 -0800340 }
341 }
ethannicholas30c5dde2016-02-02 08:36:58 -0800342}
343
344static void apply_paint_strokewidth(Json::Value& jsonPaint, SkPaint* target) {
ethannicholas978d08a2016-01-26 07:47:57 -0800345 if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_STROKEWIDTH)) {
346 float strokeWidth = jsonPaint[SKJSONCANVAS_ATTRIBUTE_STROKEWIDTH].asFloat();
ethannicholas30c5dde2016-02-02 08:36:58 -0800347 target->setStrokeWidth(strokeWidth);
348 }
349}
350
351static void apply_paint_strokemiter(Json::Value& jsonPaint, SkPaint* target) {
352 if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_STROKEMITER)) {
353 float strokeMiter = jsonPaint[SKJSONCANVAS_ATTRIBUTE_STROKEMITER].asFloat();
354 target->setStrokeMiter(strokeMiter);
355 }
356}
357
358static void apply_paint_cap(Json::Value& jsonPaint, SkPaint* target) {
359 if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_CAP)) {
360 const char* cap = jsonPaint[SKJSONCANVAS_ATTRIBUTE_CAP].asCString();
361 if (!strcmp(cap, SKJSONCANVAS_CAP_BUTT)) {
362 target->setStrokeCap(SkPaint::kButt_Cap);
363 }
364 else if (!strcmp(cap, SKJSONCANVAS_CAP_ROUND)) {
365 target->setStrokeCap(SkPaint::kRound_Cap);
366 }
367 else if (!strcmp(cap, SKJSONCANVAS_CAP_SQUARE)) {
368 target->setStrokeCap(SkPaint::kSquare_Cap);
369 }
ethannicholas978d08a2016-01-26 07:47:57 -0800370 }
ethannicholas30c5dde2016-02-02 08:36:58 -0800371}
372
373static void apply_paint_antialias(Json::Value& jsonPaint, SkPaint* target) {
ethannicholas978d08a2016-01-26 07:47:57 -0800374 if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_ANTIALIAS)) {
ethannicholas30c5dde2016-02-02 08:36:58 -0800375 target->setAntiAlias(jsonPaint[SKJSONCANVAS_ATTRIBUTE_ANTIALIAS].asBool());
ethannicholas978d08a2016-01-26 07:47:57 -0800376 }
ethannicholas30c5dde2016-02-02 08:36:58 -0800377}
378
379static void apply_paint_blur(Json::Value& jsonPaint, SkPaint* target) {
ethannicholas78fc22a2016-01-29 07:15:08 -0800380 if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_BLUR)) {
381 Json::Value blur = jsonPaint[SKJSONCANVAS_ATTRIBUTE_BLUR];
382 SkScalar sigma = blur[SKJSONCANVAS_ATTRIBUTE_SIGMA].asFloat();
383 SkBlurStyle style;
384 const char* jsonStyle = blur[SKJSONCANVAS_ATTRIBUTE_STYLE].asCString();
385 if (!strcmp(jsonStyle, SKJSONCANVAS_BLURSTYLE_NORMAL)) {
386 style = SkBlurStyle::kNormal_SkBlurStyle;
387 }
388 else if (!strcmp(jsonStyle, SKJSONCANVAS_BLURSTYLE_SOLID)) {
389 style = SkBlurStyle::kSolid_SkBlurStyle;
390 }
391 else if (!strcmp(jsonStyle, SKJSONCANVAS_BLURSTYLE_OUTER)) {
392 style = SkBlurStyle::kOuter_SkBlurStyle;
393 }
394 else if (!strcmp(jsonStyle, SKJSONCANVAS_BLURSTYLE_INNER)) {
395 style = SkBlurStyle::kInner_SkBlurStyle;
396 }
397 else {
398 SkASSERT(false);
399 style = SkBlurStyle::kNormal_SkBlurStyle;
400 }
401 SkBlurMaskFilter::BlurFlags flags;
402 const char* jsonQuality = blur[SKJSONCANVAS_ATTRIBUTE_QUALITY].asCString();
403 if (!strcmp(jsonQuality, SKJSONCANVAS_BLURQUALITY_LOW)) {
404 flags = SkBlurMaskFilter::BlurFlags::kNone_BlurFlag;
405 }
406 else if (!strcmp(jsonQuality, SKJSONCANVAS_BLURQUALITY_HIGH)) {
407 flags = SkBlurMaskFilter::BlurFlags::kHighQuality_BlurFlag;
408 }
409 else {
410 SkASSERT(false);
411 flags = SkBlurMaskFilter::BlurFlags::kNone_BlurFlag;
412 }
ethannicholas30c5dde2016-02-02 08:36:58 -0800413 target->setMaskFilter(SkBlurMaskFilter::Create(style, sigma, flags));
ethannicholas78fc22a2016-01-29 07:15:08 -0800414 }
ethannicholas30c5dde2016-02-02 08:36:58 -0800415}
416
417static void apply_paint_dashing(Json::Value& jsonPaint, SkPaint* target) {
ethannicholas78fc22a2016-01-29 07:15:08 -0800418 if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_DASHING)) {
419 Json::Value dash = jsonPaint[SKJSONCANVAS_ATTRIBUTE_DASHING];
420 Json::Value jsonIntervals = dash[SKJSONCANVAS_ATTRIBUTE_INTERVALS];
421 Json::ArrayIndex count = jsonIntervals.size();
422 SkScalar* intervals = (SkScalar*) sk_malloc_throw(count * sizeof(SkScalar));
423 for (Json::ArrayIndex i = 0; i < count; i++) {
424 intervals[i] = jsonIntervals[i].asFloat();
425 }
426 SkScalar phase = dash[SKJSONCANVAS_ATTRIBUTE_PHASE].asFloat();
ethannicholas30c5dde2016-02-02 08:36:58 -0800427 target->setPathEffect(SkDashPathEffect::Create(intervals, count, phase));
ethannicholas78fc22a2016-01-29 07:15:08 -0800428 free(intervals);
429 }
ethannicholas30c5dde2016-02-02 08:36:58 -0800430}
431
432static void apply_paint_textalign(Json::Value& jsonPaint, SkPaint* target) {
ethannicholas78fc22a2016-01-29 07:15:08 -0800433 if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_TEXTALIGN)) {
434 SkPaint::Align textAlign;
435 const char* jsonAlign = jsonPaint[SKJSONCANVAS_ATTRIBUTE_TEXTALIGN].asCString();
436 if (!strcmp(jsonAlign, SKJSONCANVAS_ALIGN_LEFT)) {
437 textAlign = SkPaint::kLeft_Align;
438 }
439 else if (!strcmp(jsonAlign, SKJSONCANVAS_ALIGN_CENTER)) {
440 textAlign = SkPaint::kCenter_Align;
441 }
442 else if (!strcmp(jsonAlign, SKJSONCANVAS_ALIGN_RIGHT)) {
443 textAlign = SkPaint::kRight_Align;
444 }
445 else {
446 SkASSERT(false);
447 textAlign = SkPaint::kLeft_Align;
448 }
ethannicholas30c5dde2016-02-02 08:36:58 -0800449 target->setTextAlign(textAlign);
ethannicholas78fc22a2016-01-29 07:15:08 -0800450 }
ethannicholas30c5dde2016-02-02 08:36:58 -0800451}
452
453static void apply_paint_textsize(Json::Value& jsonPaint, SkPaint* target) {
ethannicholas78fc22a2016-01-29 07:15:08 -0800454 if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_TEXTSIZE)) {
455 float textSize = jsonPaint[SKJSONCANVAS_ATTRIBUTE_TEXTSIZE].asFloat();
ethannicholas30c5dde2016-02-02 08:36:58 -0800456 target->setTextSize(textSize);
ethannicholas78fc22a2016-01-29 07:15:08 -0800457 }
ethannicholas30c5dde2016-02-02 08:36:58 -0800458}
459
460static void apply_paint_textscalex(Json::Value& jsonPaint, SkPaint* target) {
ethannicholas78fc22a2016-01-29 07:15:08 -0800461 if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_TEXTSCALEX)) {
462 float textScaleX = jsonPaint[SKJSONCANVAS_ATTRIBUTE_TEXTSCALEX].asFloat();
ethannicholas30c5dde2016-02-02 08:36:58 -0800463 target->setTextScaleX(textScaleX);
ethannicholas78fc22a2016-01-29 07:15:08 -0800464 }
ethannicholas30c5dde2016-02-02 08:36:58 -0800465}
466
467static void apply_paint_textskewx(Json::Value& jsonPaint, SkPaint* target) {
ethannicholas78fc22a2016-01-29 07:15:08 -0800468 if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_TEXTSKEWX)) {
469 float textSkewX = jsonPaint[SKJSONCANVAS_ATTRIBUTE_TEXTSKEWX].asFloat();
ethannicholas30c5dde2016-02-02 08:36:58 -0800470 target->setTextSkewX(textSkewX);
ethannicholas78fc22a2016-01-29 07:15:08 -0800471 }
ethannicholas978d08a2016-01-26 07:47:57 -0800472}
473
ethannicholas7471c782016-02-04 10:37:50 -0800474void Renderer::getPaint(Json::Value& paint, SkPaint* result) {
475 apply_paint_color(paint, result);
476 apply_paint_shader(paint, result);
477 apply_paint_patheffect(paint, result);
478 apply_paint_maskfilter(paint, result);
479 apply_paint_xfermode(paint, result);
480 apply_paint_imagefilter(paint, result);
481 apply_paint_style(paint, result);
482 apply_paint_strokewidth(paint, result);
483 apply_paint_strokemiter(paint, result);
484 apply_paint_cap(paint, result);
485 apply_paint_antialias(paint, result);
486 apply_paint_blur(paint, result);
487 apply_paint_dashing(paint, result);
488 apply_paint_textalign(paint, result);
489 apply_paint_textsize(paint, result);
490 apply_paint_textscalex(paint, result);
491 apply_paint_textskewx(paint, result);
ethannicholas30c5dde2016-02-02 08:36:58 -0800492}
493
ethannicholas7471c782016-02-04 10:37:50 -0800494void Renderer::getRect(Json::Value& rect, SkRect* result) {
ethannicholas978d08a2016-01-26 07:47:57 -0800495 result->set(rect[0].asFloat(), rect[1].asFloat(), rect[2].asFloat(), rect[3].asFloat());
496}
497
ethannicholas7471c782016-02-04 10:37:50 -0800498void Renderer::getRRect(Json::Value& rrect, SkRRect* result) {
ethannicholas978d08a2016-01-26 07:47:57 -0800499 SkVector radii[4] = {
500 { rrect[1][0].asFloat(), rrect[1][1].asFloat() },
501 { rrect[2][0].asFloat(), rrect[2][1].asFloat() },
502 { rrect[3][0].asFloat(), rrect[3][1].asFloat() },
503 { rrect[4][0].asFloat(), rrect[4][1].asFloat() }
504 };
505 result->setRectRadii(SkRect::MakeLTRB(rrect[0][0].asFloat(), rrect[0][1].asFloat(),
506 rrect[0][2].asFloat(), rrect[0][3].asFloat()),
ethannicholas7471c782016-02-04 10:37:50 -0800507 radii);
ethannicholas978d08a2016-01-26 07:47:57 -0800508}
509
ethannicholas7471c782016-02-04 10:37:50 -0800510void Renderer::getMatrix(Json::Value& matrix, SkMatrix* result) {
511 SkScalar values[] = {
512 matrix[0][0].asFloat(), matrix[0][1].asFloat(), matrix[0][2].asFloat(),
513 matrix[1][0].asFloat(), matrix[1][1].asFloat(), matrix[1][2].asFloat(),
514 matrix[2][0].asFloat(), matrix[2][1].asFloat(), matrix[2][2].asFloat()
515 };
516 result->set9(values);
517}
518
519void Renderer::getPath(Json::Value& path, SkPath* result) {
ethannicholas78fc22a2016-01-29 07:15:08 -0800520 const char* fillType = path[SKJSONCANVAS_ATTRIBUTE_FILLTYPE].asCString();
521 if (!strcmp(fillType, SKJSONCANVAS_FILLTYPE_WINDING)) {
522 result->setFillType(SkPath::kWinding_FillType);
523 }
524 else if (!strcmp(fillType, SKJSONCANVAS_FILLTYPE_EVENODD)) {
525 result->setFillType(SkPath::kEvenOdd_FillType);
526 }
527 else if (!strcmp(fillType, SKJSONCANVAS_FILLTYPE_INVERSEWINDING)) {
528 result->setFillType(SkPath::kInverseWinding_FillType);
529 }
530 else if (!strcmp(fillType, SKJSONCANVAS_FILLTYPE_INVERSEEVENODD)) {
531 result->setFillType(SkPath::kInverseEvenOdd_FillType);
532 }
533 Json::Value verbs = path[SKJSONCANVAS_ATTRIBUTE_VERBS];
534 for (Json::ArrayIndex i = 0; i < verbs.size(); i++) {
535 Json::Value verb = verbs[i];
536 if (verb.isString()) {
537 SkASSERT(!strcmp(verb.asCString(), SKJSONCANVAS_VERB_CLOSE));
538 result->close();
539 }
540 else {
541 if (verb.isMember(SKJSONCANVAS_VERB_MOVE)) {
542 Json::Value move = verb[SKJSONCANVAS_VERB_MOVE];
543 result->moveTo(move[0].asFloat(), move[1].asFloat());
544 }
545 else if (verb.isMember(SKJSONCANVAS_VERB_LINE)) {
546 Json::Value line = verb[SKJSONCANVAS_VERB_LINE];
547 result->lineTo(line[0].asFloat(), line[1].asFloat());
548 }
549 else if (verb.isMember(SKJSONCANVAS_VERB_QUAD)) {
550 Json::Value quad = verb[SKJSONCANVAS_VERB_QUAD];
551 result->quadTo(quad[0][0].asFloat(), quad[0][1].asFloat(),
552 quad[1][0].asFloat(), quad[1][1].asFloat());
553 }
554 else if (verb.isMember(SKJSONCANVAS_VERB_CUBIC)) {
555 Json::Value cubic = verb[SKJSONCANVAS_VERB_CUBIC];
556 result->cubicTo(cubic[0][0].asFloat(), cubic[0][1].asFloat(),
557 cubic[1][0].asFloat(), cubic[1][1].asFloat(),
558 cubic[2][0].asFloat(), cubic[2][1].asFloat());
559 }
560 else if (verb.isMember(SKJSONCANVAS_VERB_CONIC)) {
561 Json::Value conic = verb[SKJSONCANVAS_VERB_CONIC];
562 result->conicTo(conic[0][0].asFloat(), conic[0][1].asFloat(),
563 conic[1][0].asFloat(), conic[1][1].asFloat(),
564 conic[2].asFloat());
565 }
566 else {
567 SkASSERT(false);
568 }
569 }
570 }
571}
572
ethannicholas7471c782016-02-04 10:37:50 -0800573SkRegion::Op Renderer::getRegionOp(Json::Value& jsonOp) {
574 const char* op = jsonOp.asCString();
ethannicholas78fc22a2016-01-29 07:15:08 -0800575 if (!strcmp(op, SKJSONCANVAS_REGIONOP_DIFFERENCE)) {
576 return SkRegion::kDifference_Op;
577 }
578 else if (!strcmp(op, SKJSONCANVAS_REGIONOP_INTERSECT)) {
579 return SkRegion::kIntersect_Op;
580 }
581 else if (!strcmp(op, SKJSONCANVAS_REGIONOP_UNION)) {
582 return SkRegion::kUnion_Op;
583 }
584 else if (!strcmp(op, SKJSONCANVAS_REGIONOP_XOR)) {
585 return SkRegion::kXOR_Op;
586 }
587 else if (!strcmp(op, SKJSONCANVAS_REGIONOP_REVERSE_DIFFERENCE)) {
588 return SkRegion::kReverseDifference_Op;
589 }
590 else if (!strcmp(op, SKJSONCANVAS_REGIONOP_REPLACE)) {
591 return SkRegion::kReplace_Op;
592 }
593 SkASSERT(false);
594 return SkRegion::kIntersect_Op;
595}
596
ethannicholas7471c782016-02-04 10:37:50 -0800597void Renderer::processTranslate(Json::Value& command, SkCanvas* target) {
598 target->translate(command[SKJSONCANVAS_ATTRIBUTE_X].asFloat(),
599 command[SKJSONCANVAS_ATTRIBUTE_Y].asFloat());
600}
601
602void Renderer::processScale(Json::Value& command, SkCanvas* target) {
603 target->scale(command[SKJSONCANVAS_ATTRIBUTE_X].asFloat(),
604 command[SKJSONCANVAS_ATTRIBUTE_Y].asFloat());
605}
606
ethannicholas978d08a2016-01-26 07:47:57 -0800607void Renderer::processMatrix(Json::Value& command, SkCanvas* target) {
ethannicholas978d08a2016-01-26 07:47:57 -0800608 SkMatrix matrix;
ethannicholas7471c782016-02-04 10:37:50 -0800609 this->getMatrix(command[SKJSONCANVAS_ATTRIBUTE_MATRIX], &matrix);
ethannicholas978d08a2016-01-26 07:47:57 -0800610 target->setMatrix(matrix);
611}
612
613void Renderer::processSave(Json::Value& command, SkCanvas* target) {
614 target->save();
615}
616
617void Renderer::processRestore(Json::Value& command, SkCanvas* target) {
618 target->restore();
619}
620
ethannicholas30c5dde2016-02-02 08:36:58 -0800621void Renderer::processSaveLayer(Json::Value& command, SkCanvas* target) {
622 SkCanvas::SaveLayerRec rec;
623 SkRect bounds;
624 if (command.isMember(SKJSONCANVAS_ATTRIBUTE_BOUNDS)) {
ethannicholas7471c782016-02-04 10:37:50 -0800625 this->getRect(command[SKJSONCANVAS_ATTRIBUTE_BOUNDS], &bounds);
ethannicholas30c5dde2016-02-02 08:36:58 -0800626 rec.fBounds = &bounds;
627 }
628 SkPaint paint;
629 if (command.isMember(SKJSONCANVAS_ATTRIBUTE_PAINT)) {
ethannicholas7471c782016-02-04 10:37:50 -0800630 this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
ethannicholas30c5dde2016-02-02 08:36:58 -0800631 rec.fPaint = &paint;
632 }
633 if (command.isMember(SKJSONCANVAS_ATTRIBUTE_BACKDROP)) {
634 rec.fBackdrop = (SkImageFilter*) load_flattenable(command[SKJSONCANVAS_ATTRIBUTE_BACKDROP]);
635 }
636 target->saveLayer(rec);
637 if (rec.fBackdrop != nullptr) {
638 rec.fBackdrop->unref();
639 }
640}
641
ethannicholas978d08a2016-01-26 07:47:57 -0800642void Renderer::processPaint(Json::Value& command, SkCanvas* target) {
643 SkPaint paint;
ethannicholas7471c782016-02-04 10:37:50 -0800644 this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
ethannicholas978d08a2016-01-26 07:47:57 -0800645 target->drawPaint(paint);
646}
647
648void Renderer::processRect(Json::Value& command, SkCanvas* target) {
649 SkRect rect;
ethannicholas7471c782016-02-04 10:37:50 -0800650 this->getRect(command[SKJSONCANVAS_ATTRIBUTE_COORDS], &rect);
ethannicholas978d08a2016-01-26 07:47:57 -0800651 SkPaint paint;
ethannicholas7471c782016-02-04 10:37:50 -0800652 this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
ethannicholas978d08a2016-01-26 07:47:57 -0800653 target->drawRect(rect, paint);
654}
655
656void Renderer::processRRect(Json::Value& command, SkCanvas* target) {
657 SkRRect rrect;
ethannicholas7471c782016-02-04 10:37:50 -0800658 this->getRRect(command[SKJSONCANVAS_ATTRIBUTE_COORDS], &rrect);
ethannicholas978d08a2016-01-26 07:47:57 -0800659 SkPaint paint;
ethannicholas7471c782016-02-04 10:37:50 -0800660 this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
ethannicholas978d08a2016-01-26 07:47:57 -0800661 target->drawRRect(rrect, paint);
662}
663
664void Renderer::processOval(Json::Value& command, SkCanvas* target) {
665 SkRect rect;
ethannicholas7471c782016-02-04 10:37:50 -0800666 this->getRect(command[SKJSONCANVAS_ATTRIBUTE_COORDS], &rect);
ethannicholas978d08a2016-01-26 07:47:57 -0800667 SkPaint paint;
ethannicholas7471c782016-02-04 10:37:50 -0800668 this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
ethannicholas978d08a2016-01-26 07:47:57 -0800669 target->drawOval(rect, paint);
670}
671
672void Renderer::processPath(Json::Value& command, SkCanvas* target) {
ethannicholas978d08a2016-01-26 07:47:57 -0800673 SkPath path;
ethannicholas7471c782016-02-04 10:37:50 -0800674 this->getPath(command[SKJSONCANVAS_ATTRIBUTE_PATH], &path);
ethannicholas978d08a2016-01-26 07:47:57 -0800675 SkPaint paint;
ethannicholas7471c782016-02-04 10:37:50 -0800676 this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
ethannicholas978d08a2016-01-26 07:47:57 -0800677 target->drawPath(path, paint);
678}
679
680void Renderer::processText(Json::Value& command, SkCanvas* target) {
681 const char* text = command[SKJSONCANVAS_ATTRIBUTE_TEXT].asCString();
682 SkPaint paint;
ethannicholas7471c782016-02-04 10:37:50 -0800683 this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
ethannicholas978d08a2016-01-26 07:47:57 -0800684 Json::Value coords = command[SKJSONCANVAS_ATTRIBUTE_COORDS];
685 target->drawText(text, strlen(text), coords[0].asFloat(), coords[1].asFloat(), paint);
686}
687
ethannicholas78fc22a2016-01-29 07:15:08 -0800688void Renderer::processPosText(Json::Value& command, SkCanvas* target) {
689 const char* text = command[SKJSONCANVAS_ATTRIBUTE_TEXT].asCString();
690 SkPaint paint;
ethannicholas7471c782016-02-04 10:37:50 -0800691 this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
ethannicholas78fc22a2016-01-29 07:15:08 -0800692 Json::Value coords = command[SKJSONCANVAS_ATTRIBUTE_COORDS];
693 int count = (int) coords.size();
694 SkPoint* points = (SkPoint*) sk_malloc_throw(count * sizeof(SkPoint));
695 for (int i = 0; i < count; i++) {
696 points[i] = SkPoint::Make(coords[i][0].asFloat(), coords[i][1].asFloat());
697 }
698 target->drawPosText(text, strlen(text), points, paint);
699 free(points);
700}
701
ethannicholas7471c782016-02-04 10:37:50 -0800702void Renderer::processTextOnPath(Json::Value& command, SkCanvas* target) {
703 const char* text = command[SKJSONCANVAS_ATTRIBUTE_TEXT].asCString();
704 SkPath path;
705 this->getPath(command[SKJSONCANVAS_ATTRIBUTE_PATH], &path);
706 SkMatrix* matrixPtr;
707 SkMatrix matrix;
708 if (command.isMember(SKJSONCANVAS_ATTRIBUTE_MATRIX)) {
709 this->getMatrix(command[SKJSONCANVAS_ATTRIBUTE_MATRIX], &matrix);
710 matrixPtr = &matrix;
711 }
712 else {
713 matrixPtr = nullptr;
714 }
715 SkPaint paint;
716 this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
717 target->drawTextOnPath(text, strlen(text), path, matrixPtr, paint);
718}
719
ethannicholas978d08a2016-01-26 07:47:57 -0800720void Renderer::processPoints(Json::Value& command, SkCanvas* target) {
721 SkCanvas::PointMode mode;
722 const char* jsonMode = command[SKJSONCANVAS_ATTRIBUTE_MODE].asCString();
723 if (!strcmp(jsonMode, SKJSONCANVAS_POINTMODE_POINTS)) {
724 mode = SkCanvas::kPoints_PointMode;
725 }
726 else if (!strcmp(jsonMode, SKJSONCANVAS_POINTMODE_LINES)) {
727 mode = SkCanvas::kLines_PointMode;
728 }
729 else if (!strcmp(jsonMode, SKJSONCANVAS_POINTMODE_POLYGON)) {
730 mode = SkCanvas::kPolygon_PointMode;
731 }
732 else {
733 SkASSERT(false);
734 return;
735 }
736 Json::Value jsonPoints = command[SKJSONCANVAS_ATTRIBUTE_POINTS];
737 int count = (int) jsonPoints.size();
738 SkPoint* points = (SkPoint*) sk_malloc_throw(count * sizeof(SkPoint));
739 for (int i = 0; i < count; i++) {
740 points[i] = SkPoint::Make(jsonPoints[i][0].asFloat(), jsonPoints[i][1].asFloat());
741 }
742 SkPaint paint;
ethannicholas7471c782016-02-04 10:37:50 -0800743 this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
ethannicholas978d08a2016-01-26 07:47:57 -0800744 target->drawPoints(mode, count, points, paint);
745 free(points);
746}
747
748void Renderer::processClipRect(Json::Value& command, SkCanvas* target) {
749 SkRect rect;
ethannicholas7471c782016-02-04 10:37:50 -0800750 this->getRect(command[SKJSONCANVAS_ATTRIBUTE_COORDS], &rect);
751 target->clipRect(rect, this->getRegionOp(command[SKJSONCANVAS_ATTRIBUTE_REGIONOP]),
ethannicholas78fc22a2016-01-29 07:15:08 -0800752 command[SKJSONCANVAS_ATTRIBUTE_ANTIALIAS].asBool());
753}
754
755void Renderer::processClipRRect(Json::Value& command, SkCanvas* target) {
756 SkRRect rrect;
ethannicholas7471c782016-02-04 10:37:50 -0800757 this->getRRect(command[SKJSONCANVAS_ATTRIBUTE_COORDS], &rrect);
758 target->clipRRect(rrect, this->getRegionOp(command[SKJSONCANVAS_ATTRIBUTE_REGIONOP]),
ethannicholas78fc22a2016-01-29 07:15:08 -0800759 command[SKJSONCANVAS_ATTRIBUTE_ANTIALIAS].asBool());
760}
761
762void Renderer::processClipPath(Json::Value& command, SkCanvas* target) {
763 SkPath path;
ethannicholas7471c782016-02-04 10:37:50 -0800764 this->getPath(command[SKJSONCANVAS_ATTRIBUTE_PATH], &path);
765 target->clipPath(path, this->getRegionOp(command[SKJSONCANVAS_ATTRIBUTE_REGIONOP]),
ethannicholas78fc22a2016-01-29 07:15:08 -0800766 command[SKJSONCANVAS_ATTRIBUTE_ANTIALIAS].asBool());
ethannicholas978d08a2016-01-26 07:47:57 -0800767}
768
ethannicholas30c5dde2016-02-02 08:36:58 -0800769void Renderer::processImage(Json::Value& command, SkCanvas* target) {
770 SkImage* image = load_image(command[SKJSONCANVAS_ATTRIBUTE_IMAGE]);
771 if (image == nullptr) {
772 return;
773 }
774 Json::Value point = command[SKJSONCANVAS_ATTRIBUTE_COORDS];
775 SkPaint* paintPtr;
776 SkPaint paint;
777 if (command.isMember(SKJSONCANVAS_ATTRIBUTE_PAINT)) {
ethannicholas7471c782016-02-04 10:37:50 -0800778 this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
ethannicholas30c5dde2016-02-02 08:36:58 -0800779 paintPtr = &paint;
780 }
781 else {
782 paintPtr = nullptr;
783 }
784 target->drawImage(image, point[0].asFloat(), point[1].asFloat(), paintPtr);
785 image->unref();
786}
787
788void Renderer::processImageRect(Json::Value& command, SkCanvas* target) {
789 SkImage* image = load_image(command[SKJSONCANVAS_ATTRIBUTE_IMAGE]);
790 if (image == nullptr) {
791 return;
792 }
793 SkRect dst;
ethannicholas7471c782016-02-04 10:37:50 -0800794 this->getRect(command[SKJSONCANVAS_ATTRIBUTE_DST], &dst);
ethannicholas30c5dde2016-02-02 08:36:58 -0800795 SkPaint* paintPtr;
796 SkPaint paint;
797 if (command.isMember(SKJSONCANVAS_ATTRIBUTE_PAINT)) {
ethannicholas7471c782016-02-04 10:37:50 -0800798 this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
ethannicholas30c5dde2016-02-02 08:36:58 -0800799 paintPtr = &paint;
800 }
801 else {
802 paintPtr = nullptr;
803 }
804 SkCanvas::SrcRectConstraint constraint;
805 if (command.isMember(SKJSONCANVAS_ATTRIBUTE_STRICT) &&
806 command[SKJSONCANVAS_ATTRIBUTE_STRICT].asBool()) {
807 constraint = SkCanvas::kStrict_SrcRectConstraint;
808 }
809 else {
810 constraint = SkCanvas::kFast_SrcRectConstraint;
811 }
812 if (command.isMember(SKJSONCANVAS_ATTRIBUTE_SRC)) {
813 SkRect src;
ethannicholas7471c782016-02-04 10:37:50 -0800814 this->getRect(command[SKJSONCANVAS_ATTRIBUTE_SRC], &src);
ethannicholas30c5dde2016-02-02 08:36:58 -0800815 target->drawImageRect(image, src, dst, paintPtr, constraint);
816 }
817 else {
818 target->drawImageRect(image, dst, paintPtr, constraint);
819 }
820 image->unref();
821}
822
823void Renderer::processBitmap(Json::Value& command, SkCanvas* target) {
824 SkImage* image = load_image(command[SKJSONCANVAS_ATTRIBUTE_BITMAP]);
825 if (image == nullptr) {
826 return;
827 }
828 Json::Value point = command[SKJSONCANVAS_ATTRIBUTE_COORDS];
829 SkPaint* paintPtr;
830 SkPaint paint;
831 if (command.isMember(SKJSONCANVAS_ATTRIBUTE_PAINT)) {
ethannicholas7471c782016-02-04 10:37:50 -0800832 this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
ethannicholas30c5dde2016-02-02 08:36:58 -0800833 paintPtr = &paint;
834 }
835 else {
836 paintPtr = nullptr;
837 }
838 target->drawImage(image, point[0].asFloat(), point[1].asFloat(), paintPtr);
839 image->unref();
840}
841
842void Renderer::processBitmapRect(Json::Value& command, SkCanvas* target) {
843 SkBitmap* bitmap = load_bitmap(command[SKJSONCANVAS_ATTRIBUTE_BITMAP]);
844 if (bitmap == nullptr) {
845 return;
846 }
847 SkRect dst;
ethannicholas7471c782016-02-04 10:37:50 -0800848 this->getRect(command[SKJSONCANVAS_ATTRIBUTE_DST], &dst);
ethannicholas30c5dde2016-02-02 08:36:58 -0800849 SkPaint* paintPtr;
850 SkPaint paint;
851 if (command.isMember(SKJSONCANVAS_ATTRIBUTE_PAINT)) {
ethannicholas7471c782016-02-04 10:37:50 -0800852 this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint);
ethannicholas30c5dde2016-02-02 08:36:58 -0800853 paintPtr = &paint;
854 }
855 else {
856 paintPtr = nullptr;
857 }
858 SkCanvas::SrcRectConstraint constraint;
859 if (command.isMember(SKJSONCANVAS_ATTRIBUTE_STRICT) &&
860 command[SKJSONCANVAS_ATTRIBUTE_STRICT].asBool()) {
861 constraint = SkCanvas::kStrict_SrcRectConstraint;
862 }
863 else {
864 constraint = SkCanvas::kFast_SrcRectConstraint;
865 }
866 if (command.isMember(SKJSONCANVAS_ATTRIBUTE_SRC)) {
867 SkRect src;
ethannicholas7471c782016-02-04 10:37:50 -0800868 this->getRect(command[SKJSONCANVAS_ATTRIBUTE_SRC], &src);
ethannicholas30c5dde2016-02-02 08:36:58 -0800869 target->drawBitmapRect(*bitmap, src, dst, paintPtr, constraint);
870 }
871 else {
872 target->drawBitmapRect(*bitmap, dst, paintPtr, constraint);
873 }
874 free(bitmap);
875}
876
ethannicholas978d08a2016-01-26 07:47:57 -0800877void render(const char* json, SkCanvas* target) {
878 Renderer renderer;
879 Json::Reader reader;
880 Json::Value root;
881 if (reader.parse(std::string(json), root)) {
882 SkASSERT(root[SKJSONCANVAS_VERSION].asInt() == 1);
883 Json::Value commands = root[SKJSONCANVAS_COMMANDS];
884 for (Json::ArrayIndex i = 0; i < commands.size(); i++) {
885 renderer.processCommand(commands[i], target);
886 }
887 }
888 else {
889 SkDebugf(json);
890 SkFAIL("json parse failure");
891 }
892}
893
894} // namespace