blob: 734ce116b44f46a102be248f78642d503de7740b [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:
21 void getPaint(Json::Value& command, SkPaint* paint);
22
23 void getRect(Json::Value& command, const char* name, SkRect* rect);
24
25 void getRRect(Json::Value& command, const char* name, SkRRect* rrect);
26
ethannicholas78fc22a2016-01-29 07:15:08 -080027 void getPath(Json::Value& command, SkPath* path);
28
29 SkRegion::Op getRegionOp(Json::Value& command);
30
ethannicholas978d08a2016-01-26 07:47:57 -080031 void processCommand(Json::Value& command, SkCanvas* target);
32
33 void processMatrix(Json::Value& command, SkCanvas* target);
34
35 void processSave(Json::Value& command, SkCanvas* target);
36
37 void processRestore(Json::Value& command, SkCanvas* target);
38
ethannicholas30c5dde2016-02-02 08:36:58 -080039 void processSaveLayer(Json::Value& command, SkCanvas* target);
40
ethannicholas978d08a2016-01-26 07:47:57 -080041 void processPaint(Json::Value& command, SkCanvas* target);
42
43 void processRect(Json::Value& command, SkCanvas* target);
44
45 void processRRect(Json::Value& command, SkCanvas* target);
46
47 void processOval(Json::Value& command, SkCanvas* target);
48
49 void processPath(Json::Value& command, SkCanvas* target);
50
51 void processText(Json::Value& command, SkCanvas* target);
52
ethannicholas78fc22a2016-01-29 07:15:08 -080053 void processPosText(Json::Value& command, SkCanvas* target);
54
ethannicholas978d08a2016-01-26 07:47:57 -080055 void processPoints(Json::Value& command, SkCanvas* target);
56
ethannicholas30c5dde2016-02-02 08:36:58 -080057 void processImage(Json::Value& command, SkCanvas* target);
58
59 void processImageRect(Json::Value& command, SkCanvas* target);
60
61 void processBitmap(Json::Value& command, SkCanvas* target);
62
63 void processBitmapRect(Json::Value& command, SkCanvas* target);
64
ethannicholas978d08a2016-01-26 07:47:57 -080065 void processClipRect(Json::Value& command, SkCanvas* target);
ethannicholas78fc22a2016-01-29 07:15:08 -080066
67 void processClipRRect(Json::Value& command, SkCanvas* target);
68
69 void processClipPath(Json::Value& command, SkCanvas* target);
ethannicholas978d08a2016-01-26 07:47:57 -080070};
71
72void Renderer::processCommand(Json::Value& command, SkCanvas* target) {
73 const char* name = command[SKJSONCANVAS_COMMAND].asCString();
74 // TODO speed this up with a hash
75 if (!strcmp(name, SKJSONCANVAS_COMMAND_MATRIX)) {
76 this->processMatrix(command, target);
77 }
78 else if (!strcmp(name, SKJSONCANVAS_COMMAND_SAVE)) {
79 this->processSave(command, target);
80 }
81 else if (!strcmp(name, SKJSONCANVAS_COMMAND_RESTORE)) {
82 this->processRestore(command, target);
83 }
ethannicholas30c5dde2016-02-02 08:36:58 -080084 else if (!strcmp(name, SKJSONCANVAS_COMMAND_SAVELAYER)) {
85 this->processSaveLayer(command, target);
86 }
ethannicholas978d08a2016-01-26 07:47:57 -080087 else if (!strcmp(name, SKJSONCANVAS_COMMAND_PAINT)) {
88 this->processPaint(command, target);
89 }
90 else if (!strcmp(name, SKJSONCANVAS_COMMAND_RECT)) {
91 this->processRect(command, target);
92 }
93 else if (!strcmp(name, SKJSONCANVAS_COMMAND_RRECT)) {
94 this->processRRect(command, target);
95 }
96 else if (!strcmp(name, SKJSONCANVAS_COMMAND_OVAL)) {
97 this->processOval(command, target);
98 }
99 else if (!strcmp(name, SKJSONCANVAS_COMMAND_PATH)) {
100 this->processPath(command, target);
101 }
102 else if (!strcmp(name, SKJSONCANVAS_COMMAND_TEXT)) {
103 this->processText(command, target);
104 }
ethannicholas78fc22a2016-01-29 07:15:08 -0800105 else if (!strcmp(name, SKJSONCANVAS_COMMAND_POSTEXT)) {
106 this->processPosText(command, target);
107 }
ethannicholas978d08a2016-01-26 07:47:57 -0800108 else if (!strcmp(name, SKJSONCANVAS_COMMAND_POINTS)) {
109 this->processPoints(command, target);
110 }
ethannicholas30c5dde2016-02-02 08:36:58 -0800111 else if (!strcmp(name, SKJSONCANVAS_COMMAND_IMAGE)) {
112 this->processImage(command, target);
113 }
114 else if (!strcmp(name, SKJSONCANVAS_COMMAND_IMAGERECT)) {
115 this->processImageRect(command, target);
116 }
117 else if (!strcmp(name, SKJSONCANVAS_COMMAND_BITMAP)) {
118 this->processBitmap(command, target);
119 }
120 else if (!strcmp(name, SKJSONCANVAS_COMMAND_BITMAPRECT)) {
121 this->processBitmapRect(command, target);
122 }
ethannicholas978d08a2016-01-26 07:47:57 -0800123 else if (!strcmp(name, SKJSONCANVAS_COMMAND_CLIPRECT)) {
124 this->processClipRect(command, target);
125 }
ethannicholas78fc22a2016-01-29 07:15:08 -0800126 else if (!strcmp(name, SKJSONCANVAS_COMMAND_CLIPRRECT)) {
127 this->processClipRRect(command, target);
128 }
129 else if (!strcmp(name, SKJSONCANVAS_COMMAND_CLIPPATH)) {
130 this->processClipPath(command, target);
131 }
ethannicholas978d08a2016-01-26 07:47:57 -0800132 else {
133 SkDebugf("unsupported JSON command: %s\n", name);
134 }
135}
136
ethannicholas30c5dde2016-02-02 08:36:58 -0800137static void apply_paint_color(Json::Value& jsonPaint, SkPaint* target) {
ethannicholas978d08a2016-01-26 07:47:57 -0800138 if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_COLOR)) {
139 Json::Value color = jsonPaint[SKJSONCANVAS_ATTRIBUTE_COLOR];
ethannicholas30c5dde2016-02-02 08:36:58 -0800140 target->setColor(SkColorSetARGB(color[0].asInt(), color[1].asInt(), color[2].asInt(),
ethannicholas978d08a2016-01-26 07:47:57 -0800141 color[3].asInt()));
142 }
ethannicholas30c5dde2016-02-02 08:36:58 -0800143}
144
145// note that the caller is responsible for freeing the pointer
146static Json::ArrayIndex decode_data(Json::Value bytes, void** target) {
147 Json::ArrayIndex size = bytes.size();
148 *target = sk_malloc_throw(size);
149 for (Json::ArrayIndex i = 0; i < size; i++) {
150 ((uint8_t*) *target)[i] = bytes[i].asInt();
151 }
152 return size;
153}
154
155static SkFlattenable* load_flattenable(Json::Value jsonFlattenable) {
156 if (!jsonFlattenable.isMember(SKJSONCANVAS_ATTRIBUTE_NAME)) {
157 return nullptr;
158 }
159 const char* name = jsonFlattenable[SKJSONCANVAS_ATTRIBUTE_NAME].asCString();
160 SkFlattenable::Factory factory = SkFlattenable::NameToFactory(name);
161 if (factory == nullptr) {
162 return nullptr;
163 }
164 void* data;
165 int size = decode_data(jsonFlattenable[SKJSONCANVAS_ATTRIBUTE_BYTES], &data);
166 SkValidatingReadBuffer buffer(data, size);
167 SkFlattenable* result = factory(buffer);
168 free(data);
169 if (!buffer.isValid()) {
170 return nullptr;
171 }
172 return result;
173}
174
175// caller is responsible for freeing return value
176static SkBitmap* load_bitmap(Json::Value jsonBitmap) {
177 if (!jsonBitmap.isMember(SKJSONCANVAS_ATTRIBUTE_BYTES)) {
178 return nullptr;
179 }
180 void* data;
181 int size = decode_data(jsonBitmap[SKJSONCANVAS_ATTRIBUTE_BYTES], &data);
182 SkMemoryStream stream(data, size);
183 SkImageDecoder* decoder = SkImageDecoder::Factory(&stream);
184 SkBitmap* bitmap = new SkBitmap();
185 SkImageDecoder::Result result = decoder->decode(&stream, bitmap,
186 SkImageDecoder::kDecodePixels_Mode);
187 free(decoder);
188 if (result != SkImageDecoder::kFailure) {
189 free(data);
190 return bitmap;
191 }
192 SkDebugf("image decode failed");
193 free(data);
194 return nullptr;
195}
196
197static SkImage* load_image(Json::Value jsonImage) {
198 SkBitmap* bitmap = load_bitmap(jsonImage);
199 if (bitmap == nullptr) {
200 return nullptr;
201 }
202 SkImage* result = SkImage::NewFromBitmap(*bitmap);
203 free(bitmap);
204 return result;
205}
206
207static void apply_paint_shader(Json::Value& jsonPaint, SkPaint* target) {
208 if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_SHADER)) {
209 Json::Value jsonShader = jsonPaint[SKJSONCANVAS_ATTRIBUTE_SHADER];
210 SkShader* shader = (SkShader*) load_flattenable(jsonShader);
211 if (shader != nullptr) {
212 target->setShader(shader);
213 shader->unref();
214 }
215 }
216}
217
218static void apply_paint_patheffect(Json::Value& jsonPaint, SkPaint* target) {
219 if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_PATHEFFECT)) {
220 Json::Value jsonPathEffect = jsonPaint[SKJSONCANVAS_ATTRIBUTE_PATHEFFECT];
221 SkPathEffect* pathEffect = (SkPathEffect*) load_flattenable(jsonPathEffect);
222 if (pathEffect != nullptr) {
223 target->setPathEffect(pathEffect);
224 pathEffect->unref();
225 }
226 }
227}
228
229static void apply_paint_maskfilter(Json::Value& jsonPaint, SkPaint* target) {
230 if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_MASKFILTER)) {
231 Json::Value jsonMaskFilter = jsonPaint[SKJSONCANVAS_ATTRIBUTE_MASKFILTER];
232 SkMaskFilter* maskFilter = (SkMaskFilter*) load_flattenable(jsonMaskFilter);
233 if (maskFilter != nullptr) {
234 target->setMaskFilter(maskFilter);
235 maskFilter->unref();
236 }
237 }
238}
239
240static void apply_paint_xfermode(Json::Value& jsonPaint, SkPaint* target) {
241 if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_XFERMODE)) {
242 Json::Value jsonXfermode = jsonPaint[SKJSONCANVAS_ATTRIBUTE_XFERMODE];
243 SkXfermode* xfermode = (SkXfermode*) load_flattenable(jsonXfermode);
244 if (xfermode != nullptr) {
245 target->setXfermode(xfermode);
246 xfermode->unref();
247 }
248 }
249}
250
251static void apply_paint_style(Json::Value& jsonPaint, SkPaint* target) {
ethannicholas978d08a2016-01-26 07:47:57 -0800252 if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_STYLE)) {
253 const char* style = jsonPaint[SKJSONCANVAS_ATTRIBUTE_STYLE].asCString();
254 if (!strcmp(style, SKJSONCANVAS_STYLE_FILL)) {
ethannicholas30c5dde2016-02-02 08:36:58 -0800255 target->setStyle(SkPaint::kFill_Style);
ethannicholas978d08a2016-01-26 07:47:57 -0800256 }
257 else if (!strcmp(style, SKJSONCANVAS_STYLE_STROKE)) {
ethannicholas30c5dde2016-02-02 08:36:58 -0800258 target->setStyle(SkPaint::kStroke_Style);
ethannicholas978d08a2016-01-26 07:47:57 -0800259 }
260 else if (!strcmp(style, SKJSONCANVAS_STYLE_STROKEANDFILL)) {
ethannicholas30c5dde2016-02-02 08:36:58 -0800261 target->setStyle(SkPaint::kStrokeAndFill_Style);
ethannicholas978d08a2016-01-26 07:47:57 -0800262 }
263 }
ethannicholas30c5dde2016-02-02 08:36:58 -0800264}
265
266static void apply_paint_strokewidth(Json::Value& jsonPaint, SkPaint* target) {
ethannicholas978d08a2016-01-26 07:47:57 -0800267 if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_STROKEWIDTH)) {
268 float strokeWidth = jsonPaint[SKJSONCANVAS_ATTRIBUTE_STROKEWIDTH].asFloat();
ethannicholas30c5dde2016-02-02 08:36:58 -0800269 target->setStrokeWidth(strokeWidth);
270 }
271}
272
273static void apply_paint_strokemiter(Json::Value& jsonPaint, SkPaint* target) {
274 if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_STROKEMITER)) {
275 float strokeMiter = jsonPaint[SKJSONCANVAS_ATTRIBUTE_STROKEMITER].asFloat();
276 target->setStrokeMiter(strokeMiter);
277 }
278}
279
280static void apply_paint_cap(Json::Value& jsonPaint, SkPaint* target) {
281 if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_CAP)) {
282 const char* cap = jsonPaint[SKJSONCANVAS_ATTRIBUTE_CAP].asCString();
283 if (!strcmp(cap, SKJSONCANVAS_CAP_BUTT)) {
284 target->setStrokeCap(SkPaint::kButt_Cap);
285 }
286 else if (!strcmp(cap, SKJSONCANVAS_CAP_ROUND)) {
287 target->setStrokeCap(SkPaint::kRound_Cap);
288 }
289 else if (!strcmp(cap, SKJSONCANVAS_CAP_SQUARE)) {
290 target->setStrokeCap(SkPaint::kSquare_Cap);
291 }
ethannicholas978d08a2016-01-26 07:47:57 -0800292 }
ethannicholas30c5dde2016-02-02 08:36:58 -0800293}
294
295static void apply_paint_antialias(Json::Value& jsonPaint, SkPaint* target) {
ethannicholas978d08a2016-01-26 07:47:57 -0800296 if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_ANTIALIAS)) {
ethannicholas30c5dde2016-02-02 08:36:58 -0800297 target->setAntiAlias(jsonPaint[SKJSONCANVAS_ATTRIBUTE_ANTIALIAS].asBool());
ethannicholas978d08a2016-01-26 07:47:57 -0800298 }
ethannicholas30c5dde2016-02-02 08:36:58 -0800299}
300
301static void apply_paint_blur(Json::Value& jsonPaint, SkPaint* target) {
ethannicholas78fc22a2016-01-29 07:15:08 -0800302 if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_BLUR)) {
303 Json::Value blur = jsonPaint[SKJSONCANVAS_ATTRIBUTE_BLUR];
304 SkScalar sigma = blur[SKJSONCANVAS_ATTRIBUTE_SIGMA].asFloat();
305 SkBlurStyle style;
306 const char* jsonStyle = blur[SKJSONCANVAS_ATTRIBUTE_STYLE].asCString();
307 if (!strcmp(jsonStyle, SKJSONCANVAS_BLURSTYLE_NORMAL)) {
308 style = SkBlurStyle::kNormal_SkBlurStyle;
309 }
310 else if (!strcmp(jsonStyle, SKJSONCANVAS_BLURSTYLE_SOLID)) {
311 style = SkBlurStyle::kSolid_SkBlurStyle;
312 }
313 else if (!strcmp(jsonStyle, SKJSONCANVAS_BLURSTYLE_OUTER)) {
314 style = SkBlurStyle::kOuter_SkBlurStyle;
315 }
316 else if (!strcmp(jsonStyle, SKJSONCANVAS_BLURSTYLE_INNER)) {
317 style = SkBlurStyle::kInner_SkBlurStyle;
318 }
319 else {
320 SkASSERT(false);
321 style = SkBlurStyle::kNormal_SkBlurStyle;
322 }
323 SkBlurMaskFilter::BlurFlags flags;
324 const char* jsonQuality = blur[SKJSONCANVAS_ATTRIBUTE_QUALITY].asCString();
325 if (!strcmp(jsonQuality, SKJSONCANVAS_BLURQUALITY_LOW)) {
326 flags = SkBlurMaskFilter::BlurFlags::kNone_BlurFlag;
327 }
328 else if (!strcmp(jsonQuality, SKJSONCANVAS_BLURQUALITY_HIGH)) {
329 flags = SkBlurMaskFilter::BlurFlags::kHighQuality_BlurFlag;
330 }
331 else {
332 SkASSERT(false);
333 flags = SkBlurMaskFilter::BlurFlags::kNone_BlurFlag;
334 }
ethannicholas30c5dde2016-02-02 08:36:58 -0800335 target->setMaskFilter(SkBlurMaskFilter::Create(style, sigma, flags));
ethannicholas78fc22a2016-01-29 07:15:08 -0800336 }
ethannicholas30c5dde2016-02-02 08:36:58 -0800337}
338
339static void apply_paint_dashing(Json::Value& jsonPaint, SkPaint* target) {
ethannicholas78fc22a2016-01-29 07:15:08 -0800340 if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_DASHING)) {
341 Json::Value dash = jsonPaint[SKJSONCANVAS_ATTRIBUTE_DASHING];
342 Json::Value jsonIntervals = dash[SKJSONCANVAS_ATTRIBUTE_INTERVALS];
343 Json::ArrayIndex count = jsonIntervals.size();
344 SkScalar* intervals = (SkScalar*) sk_malloc_throw(count * sizeof(SkScalar));
345 for (Json::ArrayIndex i = 0; i < count; i++) {
346 intervals[i] = jsonIntervals[i].asFloat();
347 }
348 SkScalar phase = dash[SKJSONCANVAS_ATTRIBUTE_PHASE].asFloat();
ethannicholas30c5dde2016-02-02 08:36:58 -0800349 target->setPathEffect(SkDashPathEffect::Create(intervals, count, phase));
ethannicholas78fc22a2016-01-29 07:15:08 -0800350 free(intervals);
351 }
ethannicholas30c5dde2016-02-02 08:36:58 -0800352}
353
354static void apply_paint_textalign(Json::Value& jsonPaint, SkPaint* target) {
ethannicholas78fc22a2016-01-29 07:15:08 -0800355 if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_TEXTALIGN)) {
356 SkPaint::Align textAlign;
357 const char* jsonAlign = jsonPaint[SKJSONCANVAS_ATTRIBUTE_TEXTALIGN].asCString();
358 if (!strcmp(jsonAlign, SKJSONCANVAS_ALIGN_LEFT)) {
359 textAlign = SkPaint::kLeft_Align;
360 }
361 else if (!strcmp(jsonAlign, SKJSONCANVAS_ALIGN_CENTER)) {
362 textAlign = SkPaint::kCenter_Align;
363 }
364 else if (!strcmp(jsonAlign, SKJSONCANVAS_ALIGN_RIGHT)) {
365 textAlign = SkPaint::kRight_Align;
366 }
367 else {
368 SkASSERT(false);
369 textAlign = SkPaint::kLeft_Align;
370 }
ethannicholas30c5dde2016-02-02 08:36:58 -0800371 target->setTextAlign(textAlign);
ethannicholas78fc22a2016-01-29 07:15:08 -0800372 }
ethannicholas30c5dde2016-02-02 08:36:58 -0800373}
374
375static void apply_paint_textsize(Json::Value& jsonPaint, SkPaint* target) {
ethannicholas78fc22a2016-01-29 07:15:08 -0800376 if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_TEXTSIZE)) {
377 float textSize = jsonPaint[SKJSONCANVAS_ATTRIBUTE_TEXTSIZE].asFloat();
ethannicholas30c5dde2016-02-02 08:36:58 -0800378 target->setTextSize(textSize);
ethannicholas78fc22a2016-01-29 07:15:08 -0800379 }
ethannicholas30c5dde2016-02-02 08:36:58 -0800380}
381
382static void apply_paint_textscalex(Json::Value& jsonPaint, SkPaint* target) {
ethannicholas78fc22a2016-01-29 07:15:08 -0800383 if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_TEXTSCALEX)) {
384 float textScaleX = jsonPaint[SKJSONCANVAS_ATTRIBUTE_TEXTSCALEX].asFloat();
ethannicholas30c5dde2016-02-02 08:36:58 -0800385 target->setTextScaleX(textScaleX);
ethannicholas78fc22a2016-01-29 07:15:08 -0800386 }
ethannicholas30c5dde2016-02-02 08:36:58 -0800387}
388
389static void apply_paint_textskewx(Json::Value& jsonPaint, SkPaint* target) {
ethannicholas78fc22a2016-01-29 07:15:08 -0800390 if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_TEXTSKEWX)) {
391 float textSkewX = jsonPaint[SKJSONCANVAS_ATTRIBUTE_TEXTSKEWX].asFloat();
ethannicholas30c5dde2016-02-02 08:36:58 -0800392 target->setTextSkewX(textSkewX);
ethannicholas78fc22a2016-01-29 07:15:08 -0800393 }
ethannicholas978d08a2016-01-26 07:47:57 -0800394}
395
ethannicholas30c5dde2016-02-02 08:36:58 -0800396void Renderer::getPaint(Json::Value& command, SkPaint* result) {
397 Json::Value jsonPaint = command[SKJSONCANVAS_ATTRIBUTE_PAINT];
398 apply_paint_color(jsonPaint, result);
399 apply_paint_shader(jsonPaint, result);
400 apply_paint_patheffect(jsonPaint, result);
401 apply_paint_maskfilter(jsonPaint, result);
402 apply_paint_xfermode(jsonPaint, result);
403 apply_paint_style(jsonPaint, result);
404 apply_paint_strokewidth(jsonPaint, result);
405 apply_paint_strokemiter(jsonPaint, result);
406 apply_paint_cap(jsonPaint, result);
407 apply_paint_antialias(jsonPaint, result);
408 apply_paint_blur(jsonPaint, result);
409 apply_paint_dashing(jsonPaint, result);
410 apply_paint_textalign(jsonPaint, result);
411 apply_paint_textsize(jsonPaint, result);
412 apply_paint_textscalex(jsonPaint, result);
413 apply_paint_textskewx(jsonPaint, result);
414}
415
ethannicholas978d08a2016-01-26 07:47:57 -0800416void Renderer::getRect(Json::Value& command, const char* name, SkRect* result) {
417 Json::Value rect = command[name];
418 result->set(rect[0].asFloat(), rect[1].asFloat(), rect[2].asFloat(), rect[3].asFloat());
419}
420
421void Renderer::getRRect(Json::Value& command, const char* name, SkRRect* result) {
422 Json::Value rrect = command[name];
423 SkVector radii[4] = {
424 { rrect[1][0].asFloat(), rrect[1][1].asFloat() },
425 { rrect[2][0].asFloat(), rrect[2][1].asFloat() },
426 { rrect[3][0].asFloat(), rrect[3][1].asFloat() },
427 { rrect[4][0].asFloat(), rrect[4][1].asFloat() }
428 };
429 result->setRectRadii(SkRect::MakeLTRB(rrect[0][0].asFloat(), rrect[0][1].asFloat(),
430 rrect[0][2].asFloat(), rrect[0][3].asFloat()),
431 radii);
432}
433
ethannicholas78fc22a2016-01-29 07:15:08 -0800434void Renderer::getPath(Json::Value& command, SkPath* result) {
435 Json::Value path = command[SKJSONCANVAS_ATTRIBUTE_PATH];
436 const char* fillType = path[SKJSONCANVAS_ATTRIBUTE_FILLTYPE].asCString();
437 if (!strcmp(fillType, SKJSONCANVAS_FILLTYPE_WINDING)) {
438 result->setFillType(SkPath::kWinding_FillType);
439 }
440 else if (!strcmp(fillType, SKJSONCANVAS_FILLTYPE_EVENODD)) {
441 result->setFillType(SkPath::kEvenOdd_FillType);
442 }
443 else if (!strcmp(fillType, SKJSONCANVAS_FILLTYPE_INVERSEWINDING)) {
444 result->setFillType(SkPath::kInverseWinding_FillType);
445 }
446 else if (!strcmp(fillType, SKJSONCANVAS_FILLTYPE_INVERSEEVENODD)) {
447 result->setFillType(SkPath::kInverseEvenOdd_FillType);
448 }
449 Json::Value verbs = path[SKJSONCANVAS_ATTRIBUTE_VERBS];
450 for (Json::ArrayIndex i = 0; i < verbs.size(); i++) {
451 Json::Value verb = verbs[i];
452 if (verb.isString()) {
453 SkASSERT(!strcmp(verb.asCString(), SKJSONCANVAS_VERB_CLOSE));
454 result->close();
455 }
456 else {
457 if (verb.isMember(SKJSONCANVAS_VERB_MOVE)) {
458 Json::Value move = verb[SKJSONCANVAS_VERB_MOVE];
459 result->moveTo(move[0].asFloat(), move[1].asFloat());
460 }
461 else if (verb.isMember(SKJSONCANVAS_VERB_LINE)) {
462 Json::Value line = verb[SKJSONCANVAS_VERB_LINE];
463 result->lineTo(line[0].asFloat(), line[1].asFloat());
464 }
465 else if (verb.isMember(SKJSONCANVAS_VERB_QUAD)) {
466 Json::Value quad = verb[SKJSONCANVAS_VERB_QUAD];
467 result->quadTo(quad[0][0].asFloat(), quad[0][1].asFloat(),
468 quad[1][0].asFloat(), quad[1][1].asFloat());
469 }
470 else if (verb.isMember(SKJSONCANVAS_VERB_CUBIC)) {
471 Json::Value cubic = verb[SKJSONCANVAS_VERB_CUBIC];
472 result->cubicTo(cubic[0][0].asFloat(), cubic[0][1].asFloat(),
473 cubic[1][0].asFloat(), cubic[1][1].asFloat(),
474 cubic[2][0].asFloat(), cubic[2][1].asFloat());
475 }
476 else if (verb.isMember(SKJSONCANVAS_VERB_CONIC)) {
477 Json::Value conic = verb[SKJSONCANVAS_VERB_CONIC];
478 result->conicTo(conic[0][0].asFloat(), conic[0][1].asFloat(),
479 conic[1][0].asFloat(), conic[1][1].asFloat(),
480 conic[2].asFloat());
481 }
482 else {
483 SkASSERT(false);
484 }
485 }
486 }
487}
488
489SkRegion::Op Renderer::getRegionOp(Json::Value& command) {
490 const char* op = command[SKJSONCANVAS_ATTRIBUTE_REGIONOP].asCString();
491 if (!strcmp(op, SKJSONCANVAS_REGIONOP_DIFFERENCE)) {
492 return SkRegion::kDifference_Op;
493 }
494 else if (!strcmp(op, SKJSONCANVAS_REGIONOP_INTERSECT)) {
495 return SkRegion::kIntersect_Op;
496 }
497 else if (!strcmp(op, SKJSONCANVAS_REGIONOP_UNION)) {
498 return SkRegion::kUnion_Op;
499 }
500 else if (!strcmp(op, SKJSONCANVAS_REGIONOP_XOR)) {
501 return SkRegion::kXOR_Op;
502 }
503 else if (!strcmp(op, SKJSONCANVAS_REGIONOP_REVERSE_DIFFERENCE)) {
504 return SkRegion::kReverseDifference_Op;
505 }
506 else if (!strcmp(op, SKJSONCANVAS_REGIONOP_REPLACE)) {
507 return SkRegion::kReplace_Op;
508 }
509 SkASSERT(false);
510 return SkRegion::kIntersect_Op;
511}
512
ethannicholas978d08a2016-01-26 07:47:57 -0800513void Renderer::processMatrix(Json::Value& command, SkCanvas* target) {
514 Json::Value jsonMatrix = command[SKJSONCANVAS_ATTRIBUTE_MATRIX];
515 SkMatrix matrix;
516 SkScalar values[] = {
517 jsonMatrix[0][0].asFloat(), jsonMatrix[0][1].asFloat(), jsonMatrix[0][2].asFloat(),
518 jsonMatrix[1][0].asFloat(), jsonMatrix[1][1].asFloat(), jsonMatrix[1][2].asFloat(),
519 jsonMatrix[2][0].asFloat(), jsonMatrix[2][1].asFloat(), jsonMatrix[2][2].asFloat()
520 };
521 matrix.set9(values);
522 target->setMatrix(matrix);
523}
524
525void Renderer::processSave(Json::Value& command, SkCanvas* target) {
526 target->save();
527}
528
529void Renderer::processRestore(Json::Value& command, SkCanvas* target) {
530 target->restore();
531}
532
ethannicholas30c5dde2016-02-02 08:36:58 -0800533void Renderer::processSaveLayer(Json::Value& command, SkCanvas* target) {
534 SkCanvas::SaveLayerRec rec;
535 SkRect bounds;
536 if (command.isMember(SKJSONCANVAS_ATTRIBUTE_BOUNDS)) {
537 this->getRect(command, SKJSONCANVAS_ATTRIBUTE_BOUNDS, &bounds);
538 rec.fBounds = &bounds;
539 }
540 SkPaint paint;
541 if (command.isMember(SKJSONCANVAS_ATTRIBUTE_PAINT)) {
542 this->getPaint(command, &paint);
543 rec.fPaint = &paint;
544 }
545 if (command.isMember(SKJSONCANVAS_ATTRIBUTE_BACKDROP)) {
546 rec.fBackdrop = (SkImageFilter*) load_flattenable(command[SKJSONCANVAS_ATTRIBUTE_BACKDROP]);
547 }
548 target->saveLayer(rec);
549 if (rec.fBackdrop != nullptr) {
550 rec.fBackdrop->unref();
551 }
552}
553
ethannicholas978d08a2016-01-26 07:47:57 -0800554void Renderer::processPaint(Json::Value& command, SkCanvas* target) {
555 SkPaint paint;
556 this->getPaint(command, &paint);
557 target->drawPaint(paint);
558}
559
560void Renderer::processRect(Json::Value& command, SkCanvas* target) {
561 SkRect rect;
562 this->getRect(command, SKJSONCANVAS_ATTRIBUTE_COORDS, &rect);
563 SkPaint paint;
564 this->getPaint(command, &paint);
565 target->drawRect(rect, paint);
566}
567
568void Renderer::processRRect(Json::Value& command, SkCanvas* target) {
569 SkRRect rrect;
570 this->getRRect(command, SKJSONCANVAS_ATTRIBUTE_COORDS, &rrect);
571 SkPaint paint;
572 this->getPaint(command, &paint);
573 target->drawRRect(rrect, paint);
574}
575
576void Renderer::processOval(Json::Value& command, SkCanvas* target) {
577 SkRect rect;
578 this->getRect(command, SKJSONCANVAS_ATTRIBUTE_COORDS, &rect);
579 SkPaint paint;
580 this->getPaint(command, &paint);
581 target->drawOval(rect, paint);
582}
583
584void Renderer::processPath(Json::Value& command, SkCanvas* target) {
585 Json::Value jsonPath = command[SKJSONCANVAS_ATTRIBUTE_PATH];
586 SkPath path;
ethannicholas78fc22a2016-01-29 07:15:08 -0800587 this->getPath(command, &path);
ethannicholas978d08a2016-01-26 07:47:57 -0800588 SkPaint paint;
589 this->getPaint(command, &paint);
590 target->drawPath(path, paint);
591}
592
593void Renderer::processText(Json::Value& command, SkCanvas* target) {
594 const char* text = command[SKJSONCANVAS_ATTRIBUTE_TEXT].asCString();
595 SkPaint paint;
596 this->getPaint(command, &paint);
597 Json::Value coords = command[SKJSONCANVAS_ATTRIBUTE_COORDS];
598 target->drawText(text, strlen(text), coords[0].asFloat(), coords[1].asFloat(), paint);
599}
600
ethannicholas78fc22a2016-01-29 07:15:08 -0800601void Renderer::processPosText(Json::Value& command, SkCanvas* target) {
602 const char* text = command[SKJSONCANVAS_ATTRIBUTE_TEXT].asCString();
603 SkPaint paint;
604 this->getPaint(command, &paint);
605 Json::Value coords = command[SKJSONCANVAS_ATTRIBUTE_COORDS];
606 int count = (int) coords.size();
607 SkPoint* points = (SkPoint*) sk_malloc_throw(count * sizeof(SkPoint));
608 for (int i = 0; i < count; i++) {
609 points[i] = SkPoint::Make(coords[i][0].asFloat(), coords[i][1].asFloat());
610 }
611 target->drawPosText(text, strlen(text), points, paint);
612 free(points);
613}
614
ethannicholas978d08a2016-01-26 07:47:57 -0800615void Renderer::processPoints(Json::Value& command, SkCanvas* target) {
616 SkCanvas::PointMode mode;
617 const char* jsonMode = command[SKJSONCANVAS_ATTRIBUTE_MODE].asCString();
618 if (!strcmp(jsonMode, SKJSONCANVAS_POINTMODE_POINTS)) {
619 mode = SkCanvas::kPoints_PointMode;
620 }
621 else if (!strcmp(jsonMode, SKJSONCANVAS_POINTMODE_LINES)) {
622 mode = SkCanvas::kLines_PointMode;
623 }
624 else if (!strcmp(jsonMode, SKJSONCANVAS_POINTMODE_POLYGON)) {
625 mode = SkCanvas::kPolygon_PointMode;
626 }
627 else {
628 SkASSERT(false);
629 return;
630 }
631 Json::Value jsonPoints = command[SKJSONCANVAS_ATTRIBUTE_POINTS];
632 int count = (int) jsonPoints.size();
633 SkPoint* points = (SkPoint*) sk_malloc_throw(count * sizeof(SkPoint));
634 for (int i = 0; i < count; i++) {
635 points[i] = SkPoint::Make(jsonPoints[i][0].asFloat(), jsonPoints[i][1].asFloat());
636 }
637 SkPaint paint;
638 this->getPaint(command, &paint);
639 target->drawPoints(mode, count, points, paint);
640 free(points);
641}
642
643void Renderer::processClipRect(Json::Value& command, SkCanvas* target) {
644 SkRect rect;
645 this->getRect(command, SKJSONCANVAS_ATTRIBUTE_COORDS, &rect);
ethannicholas78fc22a2016-01-29 07:15:08 -0800646 target->clipRect(rect, this->getRegionOp(command),
647 command[SKJSONCANVAS_ATTRIBUTE_ANTIALIAS].asBool());
648}
649
650void Renderer::processClipRRect(Json::Value& command, SkCanvas* target) {
651 SkRRect rrect;
652 this->getRRect(command, SKJSONCANVAS_ATTRIBUTE_COORDS, &rrect);
653 target->clipRRect(rrect, this->getRegionOp(command),
654 command[SKJSONCANVAS_ATTRIBUTE_ANTIALIAS].asBool());
655}
656
657void Renderer::processClipPath(Json::Value& command, SkCanvas* target) {
658 SkPath path;
659 this->getPath(command, &path);
660 target->clipPath(path, this->getRegionOp(command),
661 command[SKJSONCANVAS_ATTRIBUTE_ANTIALIAS].asBool());
ethannicholas978d08a2016-01-26 07:47:57 -0800662}
663
ethannicholas30c5dde2016-02-02 08:36:58 -0800664void Renderer::processImage(Json::Value& command, SkCanvas* target) {
665 SkImage* image = load_image(command[SKJSONCANVAS_ATTRIBUTE_IMAGE]);
666 if (image == nullptr) {
667 return;
668 }
669 Json::Value point = command[SKJSONCANVAS_ATTRIBUTE_COORDS];
670 SkPaint* paintPtr;
671 SkPaint paint;
672 if (command.isMember(SKJSONCANVAS_ATTRIBUTE_PAINT)) {
673 this->getPaint(command, &paint);
674 paintPtr = &paint;
675 }
676 else {
677 paintPtr = nullptr;
678 }
679 target->drawImage(image, point[0].asFloat(), point[1].asFloat(), paintPtr);
680 image->unref();
681}
682
683void Renderer::processImageRect(Json::Value& command, SkCanvas* target) {
684 SkImage* image = load_image(command[SKJSONCANVAS_ATTRIBUTE_IMAGE]);
685 if (image == nullptr) {
686 return;
687 }
688 SkRect dst;
689 this->getRect(command, SKJSONCANVAS_ATTRIBUTE_DST, &dst);
690 SkPaint* paintPtr;
691 SkPaint paint;
692 if (command.isMember(SKJSONCANVAS_ATTRIBUTE_PAINT)) {
693 this->getPaint(command, &paint);
694 paintPtr = &paint;
695 }
696 else {
697 paintPtr = nullptr;
698 }
699 SkCanvas::SrcRectConstraint constraint;
700 if (command.isMember(SKJSONCANVAS_ATTRIBUTE_STRICT) &&
701 command[SKJSONCANVAS_ATTRIBUTE_STRICT].asBool()) {
702 constraint = SkCanvas::kStrict_SrcRectConstraint;
703 }
704 else {
705 constraint = SkCanvas::kFast_SrcRectConstraint;
706 }
707 if (command.isMember(SKJSONCANVAS_ATTRIBUTE_SRC)) {
708 SkRect src;
709 this->getRect(command, SKJSONCANVAS_ATTRIBUTE_SRC, &src);
710 target->drawImageRect(image, src, dst, paintPtr, constraint);
711 }
712 else {
713 target->drawImageRect(image, dst, paintPtr, constraint);
714 }
715 image->unref();
716}
717
718void Renderer::processBitmap(Json::Value& command, SkCanvas* target) {
719 SkImage* image = load_image(command[SKJSONCANVAS_ATTRIBUTE_BITMAP]);
720 if (image == nullptr) {
721 return;
722 }
723 Json::Value point = command[SKJSONCANVAS_ATTRIBUTE_COORDS];
724 SkPaint* paintPtr;
725 SkPaint paint;
726 if (command.isMember(SKJSONCANVAS_ATTRIBUTE_PAINT)) {
727 this->getPaint(command, &paint);
728 paintPtr = &paint;
729 }
730 else {
731 paintPtr = nullptr;
732 }
733 target->drawImage(image, point[0].asFloat(), point[1].asFloat(), paintPtr);
734 image->unref();
735}
736
737void Renderer::processBitmapRect(Json::Value& command, SkCanvas* target) {
738 SkBitmap* bitmap = load_bitmap(command[SKJSONCANVAS_ATTRIBUTE_BITMAP]);
739 if (bitmap == nullptr) {
740 return;
741 }
742 SkRect dst;
743 this->getRect(command, SKJSONCANVAS_ATTRIBUTE_DST, &dst);
744 SkPaint* paintPtr;
745 SkPaint paint;
746 if (command.isMember(SKJSONCANVAS_ATTRIBUTE_PAINT)) {
747 this->getPaint(command, &paint);
748 paintPtr = &paint;
749 }
750 else {
751 paintPtr = nullptr;
752 }
753 SkCanvas::SrcRectConstraint constraint;
754 if (command.isMember(SKJSONCANVAS_ATTRIBUTE_STRICT) &&
755 command[SKJSONCANVAS_ATTRIBUTE_STRICT].asBool()) {
756 constraint = SkCanvas::kStrict_SrcRectConstraint;
757 }
758 else {
759 constraint = SkCanvas::kFast_SrcRectConstraint;
760 }
761 if (command.isMember(SKJSONCANVAS_ATTRIBUTE_SRC)) {
762 SkRect src;
763 this->getRect(command, SKJSONCANVAS_ATTRIBUTE_SRC, &src);
764 target->drawBitmapRect(*bitmap, src, dst, paintPtr, constraint);
765 }
766 else {
767 target->drawBitmapRect(*bitmap, dst, paintPtr, constraint);
768 }
769 free(bitmap);
770}
771
ethannicholas978d08a2016-01-26 07:47:57 -0800772void render(const char* json, SkCanvas* target) {
773 Renderer renderer;
774 Json::Reader reader;
775 Json::Value root;
776 if (reader.parse(std::string(json), root)) {
777 SkASSERT(root[SKJSONCANVAS_VERSION].asInt() == 1);
778 Json::Value commands = root[SKJSONCANVAS_COMMANDS];
779 for (Json::ArrayIndex i = 0; i < commands.size(); i++) {
780 renderer.processCommand(commands[i], target);
781 }
782 }
783 else {
784 SkDebugf(json);
785 SkFAIL("json parse failure");
786 }
787}
788
789} // namespace