blob: 2272f881520bb38fa433a6cca3f0683567f75e97 [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 "SkJSONCanvas.h"
ethannicholas30c5dde2016-02-02 08:36:58 -08009#include "SkImageFilter.h"
ethannicholas78fc22a2016-01-29 07:15:08 -080010#include "SkMaskFilter.h"
11#include "SkPaintDefaults.h"
ethannicholas978d08a2016-01-26 07:47:57 -080012#include "SkPath.h"
ethannicholas78fc22a2016-01-29 07:15:08 -080013#include "SkPathEffect.h"
ethannicholas978d08a2016-01-26 07:47:57 -080014#include "SkRRect.h"
ethannicholas30c5dde2016-02-02 08:36:58 -080015#include "SkWriteBuffer.h"
ethannicholas978d08a2016-01-26 07:47:57 -080016
ethannicholas30c5dde2016-02-02 08:36:58 -080017SkJSONCanvas::SkJSONCanvas(int width, int height, SkWStream& out, bool sendBinaries)
ethannicholas2bbc3432016-01-27 09:06:35 -080018 : INHERITED(width, height)
19 , fOut(out)
20 , fRoot(Json::objectValue)
ethannicholas30c5dde2016-02-02 08:36:58 -080021 , fCommands(Json::arrayValue)
22 , fSendBinaries(sendBinaries) {
ethannicholas2bbc3432016-01-27 09:06:35 -080023 fRoot[SKJSONCANVAS_VERSION] = Json::Value(1);
ethannicholas978d08a2016-01-26 07:47:57 -080024}
25
26void SkJSONCanvas::finish() {
ethannicholas2bbc3432016-01-27 09:06:35 -080027 fRoot[SKJSONCANVAS_COMMANDS] = fCommands;
28 fOut.writeText(Json::FastWriter().write(fRoot).c_str());
ethannicholas978d08a2016-01-26 07:47:57 -080029}
30
ethannicholas2bbc3432016-01-27 09:06:35 -080031Json::Value SkJSONCanvas::makePoint(const SkPoint& point) {
32 Json::Value result(Json::arrayValue);
33 result.append(Json::Value(point.x()));
34 result.append(Json::Value(point.y()));
35 return result;
ethannicholas978d08a2016-01-26 07:47:57 -080036}
37
ethannicholas2bbc3432016-01-27 09:06:35 -080038Json::Value SkJSONCanvas::makePoint(SkScalar x, SkScalar y) {
39 Json::Value result(Json::arrayValue);
40 result.append(Json::Value(x));
41 result.append(Json::Value(y));
42 return result;
ethannicholas978d08a2016-01-26 07:47:57 -080043}
44
ethannicholas2bbc3432016-01-27 09:06:35 -080045Json::Value SkJSONCanvas::makeRect(const SkRect& rect) {
46 Json::Value result(Json::arrayValue);
47 result.append(Json::Value(rect.left()));
48 result.append(Json::Value(rect.top()));
49 result.append(Json::Value(rect.right()));
50 result.append(Json::Value(rect.bottom()));
51 return result;
ethannicholas978d08a2016-01-26 07:47:57 -080052}
53
ethannicholas2bbc3432016-01-27 09:06:35 -080054Json::Value SkJSONCanvas::makeRRect(const SkRRect& rrect) {
55 Json::Value result(Json::arrayValue);
56 result.append(this->makeRect(rrect.rect()));
57 result.append(this->makePoint(rrect.radii(SkRRect::kUpperLeft_Corner)));
58 result.append(this->makePoint(rrect.radii(SkRRect::kUpperRight_Corner)));
ethannicholas2bbc3432016-01-27 09:06:35 -080059 result.append(this->makePoint(rrect.radii(SkRRect::kLowerRight_Corner)));
ethannicholas78fc22a2016-01-29 07:15:08 -080060 result.append(this->makePoint(rrect.radii(SkRRect::kLowerLeft_Corner)));
ethannicholas2bbc3432016-01-27 09:06:35 -080061 return result;
ethannicholas978d08a2016-01-26 07:47:57 -080062}
63
ethannicholas2bbc3432016-01-27 09:06:35 -080064Json::Value SkJSONCanvas::makePath(const SkPath& path) {
ethannicholas78fc22a2016-01-29 07:15:08 -080065 Json::Value result(Json::objectValue);
66 switch (path.getFillType()) {
67 case SkPath::kWinding_FillType:
68 result[SKJSONCANVAS_ATTRIBUTE_FILLTYPE] = SKJSONCANVAS_FILLTYPE_WINDING;
69 break;
70 case SkPath::kEvenOdd_FillType:
71 result[SKJSONCANVAS_ATTRIBUTE_FILLTYPE] = SKJSONCANVAS_FILLTYPE_EVENODD;
72 break;
73 case SkPath::kInverseWinding_FillType:
74 result[SKJSONCANVAS_ATTRIBUTE_FILLTYPE] = SKJSONCANVAS_FILLTYPE_INVERSEWINDING;
75 break;
76 case SkPath::kInverseEvenOdd_FillType:
77 result[SKJSONCANVAS_ATTRIBUTE_FILLTYPE] = SKJSONCANVAS_FILLTYPE_INVERSEEVENODD;
78 break;
79 }
80 Json::Value verbs(Json::arrayValue);
ethannicholas978d08a2016-01-26 07:47:57 -080081 SkPath::Iter iter(path, false);
82 SkPoint pts[4];
ethannicholas978d08a2016-01-26 07:47:57 -080083 SkPath::Verb verb;
84 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
ethannicholas978d08a2016-01-26 07:47:57 -080085 switch (verb) {
ethannicholas2bbc3432016-01-27 09:06:35 -080086 case SkPath::kLine_Verb: {
87 Json::Value line(Json::objectValue);
88 line[SKJSONCANVAS_VERB_LINE] = this->makePoint(pts[1]);
ethannicholas78fc22a2016-01-29 07:15:08 -080089 verbs.append(line);
ethannicholas978d08a2016-01-26 07:47:57 -080090 break;
ethannicholas2bbc3432016-01-27 09:06:35 -080091 }
92 case SkPath::kQuad_Verb: {
93 Json::Value quad(Json::objectValue);
94 Json::Value coords(Json::arrayValue);
95 coords.append(this->makePoint(pts[1]));
96 coords.append(this->makePoint(pts[2]));
97 quad[SKJSONCANVAS_VERB_QUAD] = coords;
ethannicholas78fc22a2016-01-29 07:15:08 -080098 verbs.append(quad);
ethannicholas978d08a2016-01-26 07:47:57 -080099 break;
ethannicholas2bbc3432016-01-27 09:06:35 -0800100 }
101 case SkPath::kCubic_Verb: {
102 Json::Value cubic(Json::objectValue);
103 Json::Value coords(Json::arrayValue);
104 coords.append(this->makePoint(pts[1]));
105 coords.append(this->makePoint(pts[2]));
106 coords.append(this->makePoint(pts[3]));
107 cubic[SKJSONCANVAS_VERB_CUBIC] = coords;
ethannicholas78fc22a2016-01-29 07:15:08 -0800108 verbs.append(cubic);
ethannicholas978d08a2016-01-26 07:47:57 -0800109 break;
ethannicholas2bbc3432016-01-27 09:06:35 -0800110 }
111 case SkPath::kConic_Verb: {
112 Json::Value conic(Json::objectValue);
113 Json::Value coords(Json::arrayValue);
114 coords.append(this->makePoint(pts[1]));
115 coords.append(this->makePoint(pts[2]));
116 coords.append(Json::Value(iter.conicWeight()));
117 conic[SKJSONCANVAS_VERB_CONIC] = coords;
ethannicholas78fc22a2016-01-29 07:15:08 -0800118 verbs.append(conic);
ethannicholas978d08a2016-01-26 07:47:57 -0800119 break;
ethannicholas2bbc3432016-01-27 09:06:35 -0800120 }
121 case SkPath::kMove_Verb: {
122 Json::Value move(Json::objectValue);
123 move[SKJSONCANVAS_VERB_MOVE] = this->makePoint(pts[0]);
ethannicholas78fc22a2016-01-29 07:15:08 -0800124 verbs.append(move);
ethannicholas978d08a2016-01-26 07:47:57 -0800125 break;
ethannicholas2bbc3432016-01-27 09:06:35 -0800126 }
ethannicholas978d08a2016-01-26 07:47:57 -0800127 case SkPath::kClose_Verb:
ethannicholas78fc22a2016-01-29 07:15:08 -0800128 verbs.append(Json::Value(SKJSONCANVAS_VERB_CLOSE));
ethannicholas978d08a2016-01-26 07:47:57 -0800129 break;
130 case SkPath::kDone_Verb:
131 break;
132 }
133 }
ethannicholas78fc22a2016-01-29 07:15:08 -0800134 result[SKJSONCANVAS_ATTRIBUTE_VERBS] = verbs;
ethannicholas2bbc3432016-01-27 09:06:35 -0800135 return result;
ethannicholas978d08a2016-01-26 07:47:57 -0800136}
137
ethannicholas2bbc3432016-01-27 09:06:35 -0800138Json::Value SkJSONCanvas::makeRegion(const SkRegion& region) {
139 return Json::Value("<unimplemented>");
ethannicholas978d08a2016-01-26 07:47:57 -0800140}
141
ethannicholas78fc22a2016-01-29 07:15:08 -0800142void store_scalar(Json::Value* target, const char* key, SkScalar value, SkScalar defaultValue) {
143 if (value != defaultValue) {
144 (*target)[key] = Json::Value(value);
145 }
146}
147
148void store_bool(Json::Value* target, const char* key, bool value, bool defaultValue) {
149 if (value != defaultValue) {
150 (*target)[key] = Json::Value(value);
151 }
152}
153
ethannicholas30c5dde2016-02-02 08:36:58 -0800154static void encode_data(const void* data, size_t count, Json::Value* target) {
155 // just use a brain-dead JSON array for now, switch to base64 or something else smarter down the
156 // road
157 for (size_t i = 0; i < count; i++) {
158 target->append(((const uint8_t*)data)[i]);
159 }
160}
161
162static void flatten(const SkFlattenable* flattenable, Json::Value* target, bool sendBinaries) {
163 if (sendBinaries) {
164 SkWriteBuffer buffer;
165 flattenable->flatten(buffer);
166 void* data = sk_malloc_throw(buffer.bytesWritten());
167 buffer.writeToMemory(data);
168 Json::Value bytes;
169 encode_data(data, buffer.bytesWritten(), &bytes);
170 Json::Value jsonFlattenable;
171 jsonFlattenable[SKJSONCANVAS_ATTRIBUTE_NAME] = Json::Value(flattenable->getTypeName());
172 jsonFlattenable[SKJSONCANVAS_ATTRIBUTE_BYTES] = bytes;
173 (*target) = jsonFlattenable;
174 free(data);
175 }
176 else {
177 (*target)[SKJSONCANVAS_ATTRIBUTE_DESCRIPTION] = Json::Value(flattenable->getTypeName());
178 }
179}
180
181static bool SK_WARN_UNUSED_RESULT flatten(const SkImage& image, Json::Value* target,
182 bool sendBinaries) {
183 if (sendBinaries) {
184 SkData* png = image.encode(SkImageEncoder::kPNG_Type, 100);
185 if (png == nullptr) {
186 SkDebugf("could not encode image\n");
187 return false;
188 }
189 Json::Value bytes;
190 encode_data(png->data(), png->size(), &bytes);
191 (*target)[SKJSONCANVAS_ATTRIBUTE_BYTES] = bytes;
192 png->unref();
193 }
194 else {
195 SkString description = SkStringPrintf("%dx%d pixel image", image.width(), image.height());
196 (*target)[SKJSONCANVAS_ATTRIBUTE_DESCRIPTION] = Json::Value(description.c_str());
197 }
198 return true;
199}
200
201static bool SK_WARN_UNUSED_RESULT flatten(const SkBitmap& bitmap, Json::Value* target,
202 bool sendBinaries) {
203 SkImage* image = SkImage::NewFromBitmap(bitmap);
204 bool success = flatten(*image, target, sendBinaries);
205 image->unref();
206 return success;
207}
208
209static void apply_paint_color(const SkPaint& paint, Json::Value* target) {
ethannicholas2bbc3432016-01-27 09:06:35 -0800210 SkColor color = paint.getColor();
211 if (color != SK_ColorBLACK) {
212 Json::Value colorValue(Json::arrayValue);
213 colorValue.append(Json::Value(SkColorGetA(color)));
214 colorValue.append(Json::Value(SkColorGetR(color)));
215 colorValue.append(Json::Value(SkColorGetG(color)));
216 colorValue.append(Json::Value(SkColorGetB(color)));
ethannicholas30c5dde2016-02-02 08:36:58 -0800217 (*target)[SKJSONCANVAS_ATTRIBUTE_COLOR] = colorValue;;
ethannicholas2bbc3432016-01-27 09:06:35 -0800218 }
ethannicholas30c5dde2016-02-02 08:36:58 -0800219}
220
221static void apply_paint_style(const SkPaint& paint, Json::Value* target) {
ethannicholas978d08a2016-01-26 07:47:57 -0800222 SkPaint::Style style = paint.getStyle();
223 if (style != SkPaint::kFill_Style) {
ethannicholas978d08a2016-01-26 07:47:57 -0800224 switch (style) {
ethannicholas2bbc3432016-01-27 09:06:35 -0800225 case SkPaint::kStroke_Style: {
226 Json::Value stroke(SKJSONCANVAS_STYLE_STROKE);
ethannicholas30c5dde2016-02-02 08:36:58 -0800227 (*target)[SKJSONCANVAS_ATTRIBUTE_STYLE] = stroke;
ethannicholas978d08a2016-01-26 07:47:57 -0800228 break;
ethannicholas2bbc3432016-01-27 09:06:35 -0800229 }
230 case SkPaint::kStrokeAndFill_Style: {
231 Json::Value strokeAndFill(SKJSONCANVAS_STYLE_STROKEANDFILL);
ethannicholas30c5dde2016-02-02 08:36:58 -0800232 (*target)[SKJSONCANVAS_ATTRIBUTE_STYLE] = strokeAndFill;
ethannicholas978d08a2016-01-26 07:47:57 -0800233 break;
ethannicholas2bbc3432016-01-27 09:06:35 -0800234 }
ethannicholas978d08a2016-01-26 07:47:57 -0800235 default: SkASSERT(false);
236 }
237 }
ethannicholas30c5dde2016-02-02 08:36:58 -0800238}
239
240static void apply_paint_cap(const SkPaint& paint, Json::Value* target) {
241 SkPaint::Cap cap = paint.getStrokeCap();
242 if (cap != SkPaint::kDefault_Cap) {
243 switch (cap) {
244 case SkPaint::kButt_Cap: {
245 (*target)[SKJSONCANVAS_ATTRIBUTE_CAP] = Json::Value(SKJSONCANVAS_CAP_BUTT);
246 break;
247 }
248 case SkPaint::kRound_Cap: {
249 (*target)[SKJSONCANVAS_ATTRIBUTE_CAP] = Json::Value(SKJSONCANVAS_CAP_ROUND);
250 break;
251 }
252 case SkPaint::kSquare_Cap: {
253 (*target)[SKJSONCANVAS_ATTRIBUTE_CAP] = Json::Value(SKJSONCANVAS_CAP_SQUARE);
254 break;
255 }
256 default: SkASSERT(false);
257 }
258 }
259}
260static void apply_paint_maskfilter(const SkPaint& paint, Json::Value* target, bool sendBinaries) {
ethannicholas78fc22a2016-01-29 07:15:08 -0800261 SkMaskFilter* maskFilter = paint.getMaskFilter();
262 if (maskFilter != nullptr) {
263 SkMaskFilter::BlurRec blurRec;
264 if (maskFilter->asABlur(&blurRec)) {
265 Json::Value blur(Json::objectValue);
266 blur[SKJSONCANVAS_ATTRIBUTE_SIGMA] = Json::Value(blurRec.fSigma);
267 switch (blurRec.fStyle) {
268 case SkBlurStyle::kNormal_SkBlurStyle:
269 blur[SKJSONCANVAS_ATTRIBUTE_STYLE] = Json::Value(SKJSONCANVAS_BLURSTYLE_NORMAL);
270 break;
271 case SkBlurStyle::kSolid_SkBlurStyle:
272 blur[SKJSONCANVAS_ATTRIBUTE_STYLE] = Json::Value(SKJSONCANVAS_BLURSTYLE_SOLID);
273 break;
274 case SkBlurStyle::kOuter_SkBlurStyle:
275 blur[SKJSONCANVAS_ATTRIBUTE_STYLE] = Json::Value(SKJSONCANVAS_BLURSTYLE_OUTER);
276 break;
277 case SkBlurStyle::kInner_SkBlurStyle:
278 blur[SKJSONCANVAS_ATTRIBUTE_STYLE] = Json::Value(SKJSONCANVAS_BLURSTYLE_INNER);
279 break;
280 default:
281 SkASSERT(false);
282 }
283 switch (blurRec.fQuality) {
284 case SkBlurQuality::kLow_SkBlurQuality:
285 blur[SKJSONCANVAS_ATTRIBUTE_QUALITY] = Json::Value(SKJSONCANVAS_BLURQUALITY_LOW);
286 break;
287 case SkBlurQuality::kHigh_SkBlurQuality:
288 blur[SKJSONCANVAS_ATTRIBUTE_QUALITY] = Json::Value(SKJSONCANVAS_BLURQUALITY_HIGH);
289 break;
290 default:
291 SkASSERT(false);
292 }
ethannicholas30c5dde2016-02-02 08:36:58 -0800293 (*target)[SKJSONCANVAS_ATTRIBUTE_BLUR] = blur;
ethannicholas78fc22a2016-01-29 07:15:08 -0800294 }
295 else {
ethannicholas30c5dde2016-02-02 08:36:58 -0800296 Json::Value jsonMaskFilter;
297 flatten(maskFilter, &jsonMaskFilter, sendBinaries);
298 (*target)[SKJSONCANVAS_ATTRIBUTE_MASKFILTER] = jsonMaskFilter;
ethannicholas78fc22a2016-01-29 07:15:08 -0800299 }
ethannicholas978d08a2016-01-26 07:47:57 -0800300 }
ethannicholas30c5dde2016-02-02 08:36:58 -0800301}
302
303static void apply_paint_patheffect(const SkPaint& paint, Json::Value* target, bool sendBinaries) {
ethannicholas78fc22a2016-01-29 07:15:08 -0800304 SkPathEffect* pathEffect = paint.getPathEffect();
305 if (pathEffect != nullptr) {
306 SkPathEffect::DashInfo dashInfo;
307 SkPathEffect::DashType dashType = pathEffect->asADash(&dashInfo);
308 if (dashType == SkPathEffect::kDash_DashType) {
309 dashInfo.fIntervals = (SkScalar*) sk_malloc_throw(dashInfo.fCount * sizeof(SkScalar));
310 pathEffect->asADash(&dashInfo);
311 Json::Value dashing(Json::objectValue);
312 Json::Value intervals(Json::arrayValue);
313 for (int32_t i = 0; i < dashInfo.fCount; i++) {
314 intervals.append(Json::Value(dashInfo.fIntervals[i]));
315 }
316 free(dashInfo.fIntervals);
317 dashing[SKJSONCANVAS_ATTRIBUTE_INTERVALS] = intervals;
318 dashing[SKJSONCANVAS_ATTRIBUTE_PHASE] = dashInfo.fPhase;
ethannicholas30c5dde2016-02-02 08:36:58 -0800319 (*target)[SKJSONCANVAS_ATTRIBUTE_DASHING] = dashing;
ethannicholas78fc22a2016-01-29 07:15:08 -0800320 }
321 else {
ethannicholas30c5dde2016-02-02 08:36:58 -0800322 Json::Value jsonPathEffect;
323 flatten(pathEffect, &jsonPathEffect, sendBinaries);
324 (*target)[SKJSONCANVAS_ATTRIBUTE_PATHEFFECT] = jsonPathEffect;
ethannicholas78fc22a2016-01-29 07:15:08 -0800325 }
326 }
ethannicholas30c5dde2016-02-02 08:36:58 -0800327}
328
329static void apply_paint_textalign(const SkPaint& paint, Json::Value* target) {
ethannicholas78fc22a2016-01-29 07:15:08 -0800330 SkPaint::Align textAlign = paint.getTextAlign();
331 if (textAlign != SkPaint::kLeft_Align) {
332 switch (textAlign) {
333 case SkPaint::kCenter_Align: {
ethannicholas30c5dde2016-02-02 08:36:58 -0800334 (*target)[SKJSONCANVAS_ATTRIBUTE_TEXTALIGN] = SKJSONCANVAS_ALIGN_CENTER;
ethannicholas78fc22a2016-01-29 07:15:08 -0800335 break;
336 }
337 case SkPaint::kRight_Align: {
ethannicholas30c5dde2016-02-02 08:36:58 -0800338 (*target)[SKJSONCANVAS_ATTRIBUTE_TEXTALIGN] = SKJSONCANVAS_ALIGN_RIGHT;
ethannicholas78fc22a2016-01-29 07:15:08 -0800339 break;
340 }
341 default: SkASSERT(false);
342 }
ethannicholas978d08a2016-01-26 07:47:57 -0800343 }
ethannicholas30c5dde2016-02-02 08:36:58 -0800344}
345
346static void apply_paint_shader(const SkPaint& paint, Json::Value* target, bool sendBinaries) {
347 SkFlattenable* shader = paint.getShader();
348 if (shader != nullptr) {
349 Json::Value jsonShader;
350 flatten(shader, &jsonShader, sendBinaries);
351 (*target)[SKJSONCANVAS_ATTRIBUTE_SHADER] = jsonShader;
352 }
353}
354
355static void apply_paint_xfermode(const SkPaint& paint, Json::Value* target, bool sendBinaries) {
356 SkFlattenable* xfermode = paint.getXfermode();
357 if (xfermode != nullptr) {
358 Json::Value jsonXfermode;
359 flatten(xfermode, &jsonXfermode, sendBinaries);
360 (*target)[SKJSONCANVAS_ATTRIBUTE_XFERMODE] = jsonXfermode;
361 }
362}
363
364Json::Value SkJSONCanvas::makePaint(const SkPaint& paint) {
365 Json::Value result(Json::objectValue);
366 store_scalar(&result, SKJSONCANVAS_ATTRIBUTE_STROKEWIDTH, paint.getStrokeWidth(), 0.0f);
367 store_scalar(&result, SKJSONCANVAS_ATTRIBUTE_STROKEMITER, paint.getStrokeMiter(),
368 SkPaintDefaults_MiterLimit);
369 store_bool(&result, SKJSONCANVAS_ATTRIBUTE_ANTIALIAS, paint.isAntiAlias(), false);
370 store_scalar(&result, SKJSONCANVAS_ATTRIBUTE_TEXTSIZE, paint.getTextSize(),
371 SkPaintDefaults_TextSize);
372 store_scalar(&result, SKJSONCANVAS_ATTRIBUTE_TEXTSCALEX, paint.getTextScaleX(), SK_Scalar1);
373 store_scalar(&result, SKJSONCANVAS_ATTRIBUTE_TEXTSCALEX, paint.getTextSkewX(), 0.0f);
374 apply_paint_color(paint, &result);
375 apply_paint_style(paint, &result);
376 apply_paint_cap(paint, &result);
377 apply_paint_textalign(paint, &result);
378 apply_paint_patheffect(paint, &result, fSendBinaries);
379 apply_paint_maskfilter(paint, &result, fSendBinaries);
380 apply_paint_shader(paint, &result, fSendBinaries);
381 apply_paint_xfermode(paint, &result, fSendBinaries);
ethannicholas2bbc3432016-01-27 09:06:35 -0800382 return result;
ethannicholas978d08a2016-01-26 07:47:57 -0800383}
384
joshualitt29e5a892016-02-04 06:08:33 -0800385Json::Value SkJSONCanvas::MakeIRect(const SkIRect& rect) {
386 Json::Value result(Json::arrayValue);
387 result.append(Json::Value(rect.left()));
388 result.append(Json::Value(rect.top()));
389 result.append(Json::Value(rect.right()));
390 result.append(Json::Value(rect.bottom()));
391 return result;
392}
393
394Json::Value SkJSONCanvas::MakeMatrix(const SkMatrix& matrix) {
ethannicholas2bbc3432016-01-27 09:06:35 -0800395 Json::Value result(Json::arrayValue);
396 Json::Value row1(Json::arrayValue);
397 row1.append(Json::Value(matrix[0]));
398 row1.append(Json::Value(matrix[1]));
399 row1.append(Json::Value(matrix[2]));
400 result.append(row1);
401 Json::Value row2(Json::arrayValue);
402 row2.append(Json::Value(matrix[3]));
403 row2.append(Json::Value(matrix[4]));
404 row2.append(Json::Value(matrix[5]));
405 result.append(row2);
406 Json::Value row3(Json::arrayValue);
407 row3.append(Json::Value(matrix[6]));
408 row3.append(Json::Value(matrix[7]));
409 row3.append(Json::Value(matrix[8]));
410 result.append(row3);
411 return result;
ethannicholas978d08a2016-01-26 07:47:57 -0800412}
413
ethannicholas2bbc3432016-01-27 09:06:35 -0800414Json::Value SkJSONCanvas::makeRegionOp(SkRegion::Op op) {
415 switch (op) {
ethannicholas978d08a2016-01-26 07:47:57 -0800416 case SkRegion::kDifference_Op:
ethannicholas2bbc3432016-01-27 09:06:35 -0800417 return Json::Value(SKJSONCANVAS_REGIONOP_DIFFERENCE);
ethannicholas978d08a2016-01-26 07:47:57 -0800418 case SkRegion::kIntersect_Op:
ethannicholas2bbc3432016-01-27 09:06:35 -0800419 return Json::Value(SKJSONCANVAS_REGIONOP_INTERSECT);
ethannicholas978d08a2016-01-26 07:47:57 -0800420 case SkRegion::kUnion_Op:
ethannicholas2bbc3432016-01-27 09:06:35 -0800421 return Json::Value(SKJSONCANVAS_REGIONOP_UNION);
ethannicholas978d08a2016-01-26 07:47:57 -0800422 case SkRegion::kXOR_Op:
ethannicholas2bbc3432016-01-27 09:06:35 -0800423 return Json::Value(SKJSONCANVAS_REGIONOP_XOR);
ethannicholas978d08a2016-01-26 07:47:57 -0800424 case SkRegion::kReverseDifference_Op:
ethannicholas2bbc3432016-01-27 09:06:35 -0800425 return Json::Value(SKJSONCANVAS_REGIONOP_REVERSE_DIFFERENCE);
ethannicholas978d08a2016-01-26 07:47:57 -0800426 case SkRegion::kReplace_Op:
ethannicholas2bbc3432016-01-27 09:06:35 -0800427 return Json::Value(SKJSONCANVAS_REGIONOP_REPLACE);
ethannicholas978d08a2016-01-26 07:47:57 -0800428 default:
429 SkASSERT(false);
ethannicholas2bbc3432016-01-27 09:06:35 -0800430 return Json::Value("<invalid region op>");
ethannicholas978d08a2016-01-26 07:47:57 -0800431 };
ethannicholas978d08a2016-01-26 07:47:57 -0800432}
433
ethannicholas2bbc3432016-01-27 09:06:35 -0800434Json::Value SkJSONCanvas::makePointMode(SkCanvas::PointMode mode) {
ethannicholas978d08a2016-01-26 07:47:57 -0800435 switch (mode) {
ethannicholas2bbc3432016-01-27 09:06:35 -0800436 case SkCanvas::kPoints_PointMode:
437 return Json::Value(SKJSONCANVAS_POINTMODE_POINTS);
438 case SkCanvas::kLines_PointMode:
439 return Json::Value(SKJSONCANVAS_POINTMODE_LINES);
440 case SkCanvas::kPolygon_PointMode:
441 return Json::Value(SKJSONCANVAS_POINTMODE_POLYGON);
442 default:
443 SkASSERT(false);
444 return Json::Value("<invalid point mode>");
ethannicholas978d08a2016-01-26 07:47:57 -0800445 };
ethannicholas978d08a2016-01-26 07:47:57 -0800446}
447
448void SkJSONCanvas::updateMatrix() {
ethannicholas2bbc3432016-01-27 09:06:35 -0800449 const SkMatrix& matrix = this->getTotalMatrix();
450 if (matrix != fLastMatrix) {
451 Json::Value command(Json::objectValue);
452 command[SKJSONCANVAS_COMMAND] = Json::Value(SKJSONCANVAS_COMMAND_MATRIX);
joshualitt29e5a892016-02-04 06:08:33 -0800453 command[SKJSONCANVAS_ATTRIBUTE_MATRIX] = MakeMatrix(matrix);
ethannicholas2bbc3432016-01-27 09:06:35 -0800454 fCommands.append(command);
455 fLastMatrix = matrix;
456 }
ethannicholas978d08a2016-01-26 07:47:57 -0800457}
458
459void SkJSONCanvas::onDrawPaint(const SkPaint& paint) {
ethannicholas2bbc3432016-01-27 09:06:35 -0800460 Json::Value command(Json::objectValue);
461 command[SKJSONCANVAS_COMMAND] = Json::Value(SKJSONCANVAS_COMMAND_PAINT);
462 command[SKJSONCANVAS_ATTRIBUTE_PAINT] = this->makePaint(paint);
463 fCommands.append(command);
ethannicholas978d08a2016-01-26 07:47:57 -0800464}
465
466void SkJSONCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) {
ethannicholas2bbc3432016-01-27 09:06:35 -0800467 this->updateMatrix();
468 Json::Value command(Json::objectValue);
469 command[SKJSONCANVAS_COMMAND] = Json::Value(SKJSONCANVAS_COMMAND_RECT);
470 command[SKJSONCANVAS_ATTRIBUTE_COORDS] = this->makeRect(rect);
471 command[SKJSONCANVAS_ATTRIBUTE_PAINT] = this->makePaint(paint);
472 fCommands.append(command);
ethannicholas978d08a2016-01-26 07:47:57 -0800473}
474
475void SkJSONCanvas::onDrawOval(const SkRect& rect, const SkPaint& paint) {
ethannicholas2bbc3432016-01-27 09:06:35 -0800476 this->updateMatrix();
477 Json::Value command(Json::objectValue);
478 command[SKJSONCANVAS_COMMAND] = Json::Value(SKJSONCANVAS_COMMAND_OVAL);
479 command[SKJSONCANVAS_ATTRIBUTE_COORDS] = this->makeRect(rect);
480 command[SKJSONCANVAS_ATTRIBUTE_PAINT] = this->makePaint(paint);
481 fCommands.append(command);
ethannicholas978d08a2016-01-26 07:47:57 -0800482}
483
484void SkJSONCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
ethannicholas2bbc3432016-01-27 09:06:35 -0800485 this->updateMatrix();
486 Json::Value command(Json::objectValue);
487 command[SKJSONCANVAS_COMMAND] = Json::Value(SKJSONCANVAS_COMMAND_RRECT);
488 command[SKJSONCANVAS_ATTRIBUTE_COORDS] = this->makeRRect(rrect);
489 command[SKJSONCANVAS_ATTRIBUTE_PAINT] = this->makePaint(paint);
490 fCommands.append(command);
491}
ethannicholas978d08a2016-01-26 07:47:57 -0800492
493void SkJSONCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) {
494 this->updateMatrix();
ethannicholas2bbc3432016-01-27 09:06:35 -0800495 Json::Value command(Json::objectValue);
496 command[SKJSONCANVAS_COMMAND] = Json::Value(SKJSONCANVAS_COMMAND_RRECT);
497 command[SKJSONCANVAS_ATTRIBUTE_INNER] = this->makeRRect(inner);
498 command[SKJSONCANVAS_ATTRIBUTE_OUTER] = this->makeRRect(outer);
499 command[SKJSONCANVAS_ATTRIBUTE_PAINT] = this->makePaint(paint);
500 fCommands.append(command);
ethannicholas978d08a2016-01-26 07:47:57 -0800501}
502
503void SkJSONCanvas::onDrawPoints(SkCanvas::PointMode mode, size_t count, const SkPoint pts[],
ethannicholas2bbc3432016-01-27 09:06:35 -0800504 const SkPaint& paint) {
ethannicholas978d08a2016-01-26 07:47:57 -0800505 this->updateMatrix();
ethannicholas2bbc3432016-01-27 09:06:35 -0800506 Json::Value command(Json::objectValue);
507 command[SKJSONCANVAS_COMMAND] = Json::Value(SKJSONCANVAS_COMMAND_POINTS);
508 command[SKJSONCANVAS_ATTRIBUTE_MODE] = this->makePointMode(mode);
509 Json::Value points(Json::arrayValue);
ethannicholas978d08a2016-01-26 07:47:57 -0800510 for (size_t i = 0; i < count; i++) {
ethannicholas2bbc3432016-01-27 09:06:35 -0800511 points.append(this->makePoint(pts[i]));
ethannicholas978d08a2016-01-26 07:47:57 -0800512 }
ethannicholas2bbc3432016-01-27 09:06:35 -0800513 command[SKJSONCANVAS_ATTRIBUTE_POINTS] = points;
514 command[SKJSONCANVAS_ATTRIBUTE_PAINT] = this->makePaint(paint);
515 fCommands.append(command);
ethannicholas978d08a2016-01-26 07:47:57 -0800516}
517
518void SkJSONCanvas::onDrawVertices(SkCanvas::VertexMode, int vertexCount, const SkPoint vertices[],
519 const SkPoint texs[], const SkColor colors[], SkXfermode*,
520 const uint16_t indices[], int indexCount, const SkPaint&) {
521 SkDebugf("unsupported: drawVertices\n");
522}
523
524void SkJSONCanvas::onDrawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[],
525 int count, SkXfermode::Mode, const SkRect* cull, const SkPaint*) {
526 SkDebugf("unsupported: drawAtlas\n");
527}
528
529void SkJSONCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
ethannicholas2bbc3432016-01-27 09:06:35 -0800530 this->updateMatrix();
531 Json::Value command(Json::objectValue);
532 command[SKJSONCANVAS_COMMAND] = Json::Value(SKJSONCANVAS_COMMAND_PATH);
533 command[SKJSONCANVAS_ATTRIBUTE_PATH] = this->makePath(path);
534 command[SKJSONCANVAS_ATTRIBUTE_PAINT] = this->makePaint(paint);
535 fCommands.append(command);
536}
ethannicholas978d08a2016-01-26 07:47:57 -0800537
ethannicholas30c5dde2016-02-02 08:36:58 -0800538void SkJSONCanvas::onDrawImage(const SkImage* image, SkScalar dx, SkScalar dy,
539 const SkPaint* paint) {
540 Json::Value encoded;
541 if (flatten(*image, &encoded, fSendBinaries)) {
542 this->updateMatrix();
543 Json::Value command(Json::objectValue);
544 command[SKJSONCANVAS_COMMAND] = Json::Value(SKJSONCANVAS_COMMAND_IMAGE);
545 command[SKJSONCANVAS_ATTRIBUTE_IMAGE] = encoded;
546 command[SKJSONCANVAS_ATTRIBUTE_COORDS] = this->makePoint(dx, dy);
547 if (paint != nullptr) {
548 command[SKJSONCANVAS_ATTRIBUTE_PAINT] = this->makePaint(*paint);
549 }
550 fCommands.append(command);
551 }
ethannicholas978d08a2016-01-26 07:47:57 -0800552}
553
ethannicholas30c5dde2016-02-02 08:36:58 -0800554void SkJSONCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
555 const SkPaint* paint, SkCanvas::SrcRectConstraint constraint) {
556 Json::Value encoded;
557 if (flatten(*image, &encoded, fSendBinaries)) {
558 this->updateMatrix();
559 Json::Value command(Json::objectValue);
560 command[SKJSONCANVAS_COMMAND] = Json::Value(SKJSONCANVAS_COMMAND_IMAGERECT);
561 command[SKJSONCANVAS_ATTRIBUTE_IMAGE] = encoded;
562 if (src != nullptr) {
563 command[SKJSONCANVAS_ATTRIBUTE_SRC] = this->makeRect(*src);
564 }
565 command[SKJSONCANVAS_ATTRIBUTE_DST] = this->makeRect(dst);
566 if (paint != nullptr) {
567 command[SKJSONCANVAS_ATTRIBUTE_PAINT] = this->makePaint(*paint);
568 }
569 if (constraint == SkCanvas::kStrict_SrcRectConstraint) {
570 command[SKJSONCANVAS_ATTRIBUTE_STRICT] = Json::Value(true);
571 }
572 fCommands.append(command);
573 }
ethannicholas978d08a2016-01-26 07:47:57 -0800574}
575
576void SkJSONCanvas::onDrawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst,
577 const SkPaint*) {
578 SkDebugf("unsupported: drawImageNine\n");
579}
580
ethannicholas30c5dde2016-02-02 08:36:58 -0800581void SkJSONCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar dx, SkScalar dy,
582 const SkPaint* paint) {
583 Json::Value encoded;
584 if (flatten(bitmap, &encoded, fSendBinaries)) {
585 this->updateMatrix();
586 Json::Value command(Json::objectValue);
587 command[SKJSONCANVAS_COMMAND] = Json::Value(SKJSONCANVAS_COMMAND_BITMAP);
588 command[SKJSONCANVAS_ATTRIBUTE_BITMAP] = encoded;
589 command[SKJSONCANVAS_ATTRIBUTE_COORDS] = this->makePoint(dx, dy);
590 if (paint != nullptr) {
591 command[SKJSONCANVAS_ATTRIBUTE_PAINT] = this->makePaint(*paint);
592 }
593 fCommands.append(command);
594 }
ethannicholas978d08a2016-01-26 07:47:57 -0800595}
596
ethannicholas30c5dde2016-02-02 08:36:58 -0800597void SkJSONCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
598 const SkPaint* paint, SkCanvas::SrcRectConstraint constraint) {
599 Json::Value encoded;
600 if (flatten(bitmap, &encoded, fSendBinaries)) {
601 this->updateMatrix();
602 Json::Value command(Json::objectValue);
603 command[SKJSONCANVAS_COMMAND] = Json::Value(SKJSONCANVAS_COMMAND_BITMAPRECT);
604 command[SKJSONCANVAS_ATTRIBUTE_IMAGE] = encoded;
605 if (src != nullptr) {
606 command[SKJSONCANVAS_ATTRIBUTE_SRC] = this->makeRect(*src);
607 }
608 command[SKJSONCANVAS_ATTRIBUTE_DST] = this->makeRect(dst);
609 if (paint != nullptr) {
610 command[SKJSONCANVAS_ATTRIBUTE_PAINT] = this->makePaint(*paint);
611 }
612 if (constraint == SkCanvas::kStrict_SrcRectConstraint) {
613 command[SKJSONCANVAS_ATTRIBUTE_STRICT] = Json::Value(true);
614 }
615 fCommands.append(command);
616 }
ethannicholas978d08a2016-01-26 07:47:57 -0800617}
618
619void SkJSONCanvas::onDrawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst,
620 const SkPaint*) {
621 SkDebugf("unsupported: drawBitmapNine\n");
622}
623
624void SkJSONCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x,
625 SkScalar y, const SkPaint& paint) {
626 this->updateMatrix();
ethannicholas2bbc3432016-01-27 09:06:35 -0800627 Json::Value command(Json::objectValue);
628 command[SKJSONCANVAS_COMMAND] = Json::Value(SKJSONCANVAS_COMMAND_TEXT);
629 command[SKJSONCANVAS_ATTRIBUTE_TEXT] = Json::Value((const char*) text,
630 ((const char*) text) + byteLength);
631 command[SKJSONCANVAS_ATTRIBUTE_COORDS] = this->makePoint(x, y);
632 command[SKJSONCANVAS_ATTRIBUTE_PAINT] = this->makePaint(paint);
633 fCommands.append(command);
ethannicholas978d08a2016-01-26 07:47:57 -0800634}
635
636void SkJSONCanvas::onDrawPosText(const void* text, size_t byteLength,
637 const SkPoint pos[], const SkPaint& paint) {
ethannicholas78fc22a2016-01-29 07:15:08 -0800638 this->updateMatrix();
639 Json::Value command(Json::objectValue);
640 command[SKJSONCANVAS_COMMAND] = Json::Value(SKJSONCANVAS_COMMAND_POSTEXT);
641 command[SKJSONCANVAS_ATTRIBUTE_TEXT] = Json::Value((const char*) text,
642 ((const char*) text) + byteLength);
643 Json::Value coords(Json::arrayValue);
644 for (size_t i = 0; i < byteLength; i++) {
645 coords.append(this->makePoint(pos[i]));
646 }
647 command[SKJSONCANVAS_ATTRIBUTE_COORDS] = coords;
648 command[SKJSONCANVAS_ATTRIBUTE_PAINT] = this->makePaint(paint);
649 fCommands.append(command);
ethannicholas978d08a2016-01-26 07:47:57 -0800650}
651
652void SkJSONCanvas::onDrawPosTextH(const void* text, size_t byteLength,
653 const SkScalar xpos[], SkScalar constY,
654 const SkPaint& paint) {
655 SkDebugf("unsupported: drawPosTextH\n");
656}
657
658void SkJSONCanvas::onDrawTextOnPath(const void* text, size_t byteLength,
659 const SkPath& path, const SkMatrix* matrix,
660 const SkPaint& paint) {
661 SkDebugf("unsupported: drawTextOnPath\n");
662}
663
664void SkJSONCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
665 const SkPaint& paint) {
666 SkDebugf("unsupported: drawTextBlob\n");
667}
668
669void SkJSONCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
670 const SkPoint texCoords[4], SkXfermode* xmode,
671 const SkPaint& paint) {
672 SkDebugf("unsupported: drawPatch\n");
673}
674
675void SkJSONCanvas::onDrawDrawable(SkDrawable*, const SkMatrix*) {
676 SkDebugf("unsupported: drawDrawable\n");
677}
678
679void SkJSONCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
ethannicholas2bbc3432016-01-27 09:06:35 -0800680 this->updateMatrix();
681 Json::Value command(Json::objectValue);
682 command[SKJSONCANVAS_COMMAND] = Json::Value(SKJSONCANVAS_COMMAND_CLIPRECT);
683 command[SKJSONCANVAS_ATTRIBUTE_COORDS] = this->makeRect(rect);
684 command[SKJSONCANVAS_ATTRIBUTE_REGIONOP] = this->makeRegionOp(op);
ethannicholas78fc22a2016-01-29 07:15:08 -0800685 command[SKJSONCANVAS_ATTRIBUTE_ANTIALIAS] = (edgeStyle == SkCanvas::kSoft_ClipEdgeStyle);
ethannicholas2bbc3432016-01-27 09:06:35 -0800686 fCommands.append(command);
ethannicholas978d08a2016-01-26 07:47:57 -0800687}
688
689void SkJSONCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
ethannicholas2bbc3432016-01-27 09:06:35 -0800690 this->updateMatrix();
691 Json::Value command(Json::objectValue);
692 command[SKJSONCANVAS_COMMAND] = Json::Value(SKJSONCANVAS_COMMAND_CLIPRRECT);
693 command[SKJSONCANVAS_ATTRIBUTE_COORDS] = this->makeRRect(rrect);
694 command[SKJSONCANVAS_ATTRIBUTE_REGIONOP] = this->makeRegionOp(op);
ethannicholas78fc22a2016-01-29 07:15:08 -0800695 command[SKJSONCANVAS_ATTRIBUTE_ANTIALIAS] = (edgeStyle == SkCanvas::kSoft_ClipEdgeStyle);
ethannicholas2bbc3432016-01-27 09:06:35 -0800696 fCommands.append(command);
ethannicholas978d08a2016-01-26 07:47:57 -0800697}
698
699void SkJSONCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
ethannicholas2bbc3432016-01-27 09:06:35 -0800700 this->updateMatrix();
701 Json::Value command(Json::objectValue);
702 command[SKJSONCANVAS_COMMAND] = Json::Value(SKJSONCANVAS_COMMAND_CLIPPATH);
703 command[SKJSONCANVAS_ATTRIBUTE_PATH] = this->makePath(path);
704 command[SKJSONCANVAS_ATTRIBUTE_REGIONOP] = this->makeRegionOp(op);
ethannicholas78fc22a2016-01-29 07:15:08 -0800705 command[SKJSONCANVAS_ATTRIBUTE_ANTIALIAS] = (edgeStyle == SkCanvas::kSoft_ClipEdgeStyle);
ethannicholas2bbc3432016-01-27 09:06:35 -0800706 fCommands.append(command);
ethannicholas978d08a2016-01-26 07:47:57 -0800707}
708
709void SkJSONCanvas::onClipRegion(const SkRegion& deviceRgn, SkRegion::Op op) {
ethannicholas2bbc3432016-01-27 09:06:35 -0800710 this->updateMatrix();
711 Json::Value command(Json::objectValue);
712 command[SKJSONCANVAS_COMMAND] = Json::Value(SKJSONCANVAS_COMMAND_CLIPREGION);
713 command[SKJSONCANVAS_ATTRIBUTE_REGION] = this->makeRegion(deviceRgn);
714 command[SKJSONCANVAS_ATTRIBUTE_REGIONOP] = this->makeRegionOp(op);
715 fCommands.append(command);
ethannicholas978d08a2016-01-26 07:47:57 -0800716}
717
718void SkJSONCanvas::willSave() {
ethannicholas78fc22a2016-01-29 07:15:08 -0800719 this->updateMatrix();
ethannicholas2bbc3432016-01-27 09:06:35 -0800720 Json::Value command(Json::objectValue);
721 command[SKJSONCANVAS_COMMAND] = Json::Value(SKJSONCANVAS_COMMAND_SAVE);
722 fCommands.append(command);
ethannicholas978d08a2016-01-26 07:47:57 -0800723}
724
725void SkJSONCanvas::willRestore() {
ethannicholas2bbc3432016-01-27 09:06:35 -0800726 Json::Value command(Json::objectValue);
727 command[SKJSONCANVAS_COMMAND] = Json::Value(SKJSONCANVAS_COMMAND_RESTORE);
728 fCommands.append(command);
ethannicholas978d08a2016-01-26 07:47:57 -0800729}
ethannicholas30c5dde2016-02-02 08:36:58 -0800730
731SkCanvas::SaveLayerStrategy SkJSONCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) {
732 Json::Value command(Json::objectValue);
733 command[SKJSONCANVAS_COMMAND] = Json::Value(SKJSONCANVAS_COMMAND_SAVELAYER);
734 if (rec.fBounds != nullptr) {
735 command[SKJSONCANVAS_ATTRIBUTE_BOUNDS] = this->makeRect(*rec.fBounds);
736 }
737 if (rec.fPaint != nullptr) {
738 command[SKJSONCANVAS_ATTRIBUTE_PAINT] = this->makePaint(*rec.fPaint);
739 }
740 if (rec.fBackdrop != nullptr) {
741 Json::Value backdrop;
742 flatten(rec.fBackdrop, &backdrop, fSendBinaries);
743 command[SKJSONCANVAS_ATTRIBUTE_BACKDROP] = backdrop;
744 }
745 if (rec.fSaveLayerFlags != 0) {
746 SkDebugf("unsupported: saveLayer flags\n");
747 }
748 fCommands.append(command);
749 return this->INHERITED::getSaveLayerStrategy(rec);
750}