OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright 2016 Google Inc. |
| 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. |
| 6 */ |
| 7 |
| 8 #include "SkJSONCanvas.h" |
| 9 #include "SkPath.h" |
| 10 #include "SkRRect.h" |
| 11 #include "stdio.h" |
| 12 #include "stdlib.h" |
| 13 |
| 14 SkJSONCanvas::SkJSONCanvas(int width, int height, SkWStream& out) |
| 15 : INHERITED(width, height) |
| 16 , fOut(out) |
| 17 , fFirstCommand(true) { |
| 18 fOut.writeText("{\"" SKJSONCANVAS_VERSION "\":1, \"" SKJSONCANVAS_COMMAN
DS |
| 19 "\":["); |
| 20 } |
| 21 |
| 22 void SkJSONCanvas::finish() { |
| 23 fOut.writeText("]}"); |
| 24 } |
| 25 |
| 26 void SkJSONCanvas::writef(const char* format, ...) { |
| 27 va_list args; |
| 28 va_start(args, format); |
| 29 SkString s; |
| 30 s.appendVAList(format, args); |
| 31 fOut.writeText(s.c_str()); |
| 32 } |
| 33 |
| 34 void SkJSONCanvas::open(const char* name) { |
| 35 if (fFirstCommand) { |
| 36 fFirstCommand = false; |
| 37 } |
| 38 else { |
| 39 fOut.writeText(","); |
| 40 } |
| 41 this->writef("{\"" SKJSONCANVAS_COMMAND "\":\"%s\"", name); |
| 42 } |
| 43 |
| 44 void SkJSONCanvas::close() { |
| 45 fOut.writeText("}"); |
| 46 } |
| 47 |
| 48 void SkJSONCanvas::writeString(const char* name, const char* text) { |
| 49 this->writeString(name, text, strlen(text)); |
| 50 } |
| 51 |
| 52 void SkJSONCanvas::writeString(const char* name, const void* text, size_t length
) { |
| 53 // TODO: escaping |
| 54 this->writef(",\"%s\":\"", name); |
| 55 fOut.write(text, length); |
| 56 fOut.writeText("\""); |
| 57 } |
| 58 |
| 59 void SkJSONCanvas::writePoint(const char* name, const SkPoint& point) { |
| 60 this->writef(",\"%s\":[%f, %f]", name, point.x(), point.y()); |
| 61 } |
| 62 |
| 63 void SkJSONCanvas::writeRect(const char* name, const SkRect& rect) { |
| 64 this->writef(",\"%s\":[%f, %f, %f, %f]", name, rect.left(), rect.top(),
rect.right(), |
| 65 rect.bottom()); |
| 66 } |
| 67 |
| 68 void SkJSONCanvas::writeRRect(const char* name, const SkRRect& rrect) { |
| 69 SkRect rect = rrect.rect(); |
| 70 SkVector corner1 = rrect.radii(SkRRect::kUpperLeft_Corner); |
| 71 SkVector corner2 = rrect.radii(SkRRect::kUpperRight_Corner); |
| 72 SkVector corner3 = rrect.radii(SkRRect::kLowerLeft_Corner); |
| 73 SkVector corner4 = rrect.radii(SkRRect::kLowerRight_Corner); |
| 74 this->writef(",\"%s\":[[%f, %f, %f, %f],[%f, %f],[%f, %f],[%f, %f],[%f,
%f]]", name, |
| 75 rect.left(), rect.top(), rect.right(), rect.bot
tom(), corner1.x(), corner1.y(), |
| 76 corner2.x(), corner2.y(), corner3.x(), corner3.
y(), corner4.x(), corner4.y()); |
| 77 } |
| 78 |
| 79 void SkJSONCanvas::writePath(const char* name, const SkPath& path) { |
| 80 SkString text("["); |
| 81 SkPath::Iter iter(path, false); |
| 82 SkPoint pts[4]; |
| 83 bool first = true; |
| 84 SkPath::Verb verb; |
| 85 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { |
| 86 if (first) { |
| 87 first = false; |
| 88 } |
| 89 else { |
| 90 text.append(","); |
| 91 } |
| 92 switch (verb) { |
| 93 case SkPath::kLine_Verb: |
| 94 text.appendf("{\"" SKJSONCANVAS_VERB_LINE "\":[%f,%f]}", pts[1].
x(), pts[1].y()); |
| 95 break; |
| 96 case SkPath::kQuad_Verb: |
| 97 text.appendf("{\"" SKJSONCANVAS_VERB_QUAD "\":[[%f,%f],[%f,%f]]}
", pts[1].x(), |
| 98 pts[1].y(), pts[2].x(), pts[2].y()); |
| 99 break; |
| 100 case SkPath::kCubic_Verb: |
| 101 text.appendf("{\"" SKJSONCANVAS_VERB_CUBIC "\":[[%f,%f],[%f,%f],
[%f,%f]]}", |
| 102 pts[1].x(), pts[1].y(), pts[2].x(), pts[2].y(), pts
[3].x(), |
| 103 pts[3].y()); |
| 104 break; |
| 105 case SkPath::kConic_Verb: |
| 106 text.appendf("{\"" SKJSONCANVAS_VERB_CONIC "\":[[%f,%f],[%f,%f],
%f]}", pts[1].x(), |
| 107 pts[1].y(), pts[2].x(), pts[2].y(), iter.conicWeigh
t()); |
| 108 break; |
| 109 case SkPath::kMove_Verb: |
| 110 text.appendf("{\"" SKJSONCANVAS_VERB_MOVE "\":[%f,%f]}", pts[0].
x(), pts[0].y()); |
| 111 break; |
| 112 case SkPath::kClose_Verb: |
| 113 text.appendf("\"" SKJSONCANVAS_VERB_CLOSE "\""); |
| 114 break; |
| 115 case SkPath::kDone_Verb: |
| 116 break; |
| 117 } |
| 118 } |
| 119 text.appendf("]"); |
| 120 this->writef(",\"" SKJSONCANVAS_ATTRIBUTE_PATH "\":%s", text.c_str()); |
| 121 } |
| 122 |
| 123 void SkJSONCanvas::writeRegion(const char* name, const SkRegion& region) { |
| 124 this->writef(",\"%s\":\"<unimplemented>\"", name); |
| 125 } |
| 126 |
| 127 void SkJSONCanvas::writePaint(const SkPaint& paint) { |
| 128 this->writef(",\"" SKJSONCANVAS_ATTRIBUTE_PAINT "\":{"); |
| 129 SkColor color = paint.getColor(); |
| 130 bool first = true; |
| 131 if (color != SK_ColorBLACK) { |
| 132 this->writef("\"" SKJSONCANVAS_ATTRIBUTE_COLOR "\":[%d,%d,%d,%d]
", SkColorGetA(color), |
| 133 SkColorGetR(color), SkColorGetG(color), SkColorGetB(color))
; |
| 134 first = false; |
| 135 } |
| 136 SkPaint::Style style = paint.getStyle(); |
| 137 if (style != SkPaint::kFill_Style) { |
| 138 if (first) { |
| 139 first = false; |
| 140 } |
| 141 else { |
| 142 fOut.writeText(","); |
| 143 } |
| 144 switch (style) { |
| 145 case SkPaint::kStroke_Style: |
| 146 fOut.writeText("\"" SKJSONCANVAS_ATTRIBUTE_STYLE "\":\"" |
| 147 SKJSONCANVAS_STYLE_STROKE "\""); |
| 148 break; |
| 149 case SkPaint::kStrokeAndFill_Style: |
| 150 fOut.writeText("\"" SKJSONCANVAS_ATTRIBUTE_STYLE "\":\"" |
| 151 SKJSONCANVAS_STYLE_STROKEANDFILL "\""); |
| 152 break; |
| 153 default: SkASSERT(false); |
| 154 } |
| 155 } |
| 156 SkScalar strokeWidth = paint.getStrokeWidth(); |
| 157 if (strokeWidth != 0.0f) { |
| 158 if (first) { |
| 159 first = false; |
| 160 } |
| 161 else { |
| 162 fOut.writeText(","); |
| 163 } |
| 164 this->writef("\"" SKJSONCANVAS_ATTRIBUTE_STROKEWIDTH "\":%f", strokeWidt
h); |
| 165 } |
| 166 if (paint.isAntiAlias()) { |
| 167 if (first) { |
| 168 first = false; |
| 169 } |
| 170 else { |
| 171 fOut.writeText(","); |
| 172 } |
| 173 fOut.writeText("\"" SKJSONCANVAS_ATTRIBUTE_ANTIALIAS "\":true"); |
| 174 } |
| 175 fOut.writeText("}"); |
| 176 } |
| 177 |
| 178 void SkJSONCanvas::writeMatrix(const char* name, const SkMatrix& matrix) { |
| 179 this->writef(",\"%s\":[[%f,%f,%f],[%f,%f,%f],[%f,%f,%f]]", name, |
| 180 matrix[0], matrix[1], matrix[2], |
| 181 matrix[3], matrix[4], matrix[5], |
| 182 matrix[6], matrix[7], matrix[8]); |
| 183 } |
| 184 |
| 185 void SkJSONCanvas::writeRegionOp(const char* name, SkRegion::Op op) { |
| 186 this->writef(",\"%s\":\"", name); |
| 187 switch (op) { |
| 188 case SkRegion::kDifference_Op: |
| 189 fOut.writeText(SKJSONCANVAS_REGIONOP_DIFFERENCE); |
| 190 break; |
| 191 case SkRegion::kIntersect_Op: |
| 192 fOut.writeText(SKJSONCANVAS_REGIONOP_INTERSECT); |
| 193 break; |
| 194 case SkRegion::kUnion_Op: |
| 195 fOut.writeText(SKJSONCANVAS_REGIONOP_UNION); |
| 196 break; |
| 197 case SkRegion::kXOR_Op: |
| 198 fOut.writeText(SKJSONCANVAS_REGIONOP_XOR); |
| 199 break; |
| 200 case SkRegion::kReverseDifference_Op: |
| 201 fOut.writeText(SKJSONCANVAS_REGIONOP_REVERSE_DIFFERENCE); |
| 202 break; |
| 203 case SkRegion::kReplace_Op: |
| 204 fOut.writeText(SKJSONCANVAS_REGIONOP_REPLACE); |
| 205 break; |
| 206 default: |
| 207 SkASSERT(false); |
| 208 }; |
| 209 fOut.writeText("\""); |
| 210 } |
| 211 |
| 212 void SkJSONCanvas::writeEdgeStyle(const char* name, SkCanvas::ClipEdgeStyle edge
Style) { |
| 213 this->writef(",\"%s\":\"", name); |
| 214 switch (edgeStyle) { |
| 215 case SkCanvas::kHard_ClipEdgeStyle: fOut.writeText(SKJSONCANVAS_EDGESTYL
E_HARD); break; |
| 216 case SkCanvas::kSoft_ClipEdgeStyle: fOut.writeText(SKJSONCANVAS_EDGESTYL
E_SOFT); break; |
| 217 default: SkASSERT(false); |
| 218 }; |
| 219 fOut.writeText("\""); |
| 220 } |
| 221 |
| 222 void SkJSONCanvas::writePointMode(const char* name, SkCanvas::PointMode mode) { |
| 223 this->writef(",\"%s\":\"", name); |
| 224 switch (mode) { |
| 225 case SkCanvas::kPoints_PointMode: fOut.writeText(SKJSONCANVAS_POINTMODE
_POINTS); break; |
| 226 case SkCanvas::kLines_PointMode: fOut.writeText(SKJSONCANVAS_POINTMODE
_LINES); break; |
| 227 case SkCanvas::kPolygon_PointMode: fOut.writeText(SKJSONCANVAS_POINTMODE
_POLYGON); break; |
| 228 default: SkASSERT(false); |
| 229 }; |
| 230 fOut.writeText("\""); |
| 231 } |
| 232 |
| 233 void SkJSONCanvas::updateMatrix() { |
| 234 const SkMatrix& matrix = this->getTotalMatrix(); |
| 235 if (matrix != fLastMatrix) { |
| 236 this->open(SKJSONCANVAS_COMMAND_MATRIX); |
| 237 this->writeMatrix(SKJSONCANVAS_ATTRIBUTE_MATRIX, matrix); |
| 238 fLastMatrix = matrix; |
| 239 this->close(); |
| 240 } |
| 241 } |
| 242 |
| 243 void SkJSONCanvas::onDrawPaint(const SkPaint& paint) { |
| 244 this->open(SKJSONCANVAS_COMMAND_PAINT); |
| 245 this->writePaint(paint); |
| 246 this->close(); |
| 247 } |
| 248 |
| 249 void SkJSONCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) { |
| 250 this->updateMatrix(); |
| 251 this->open(SKJSONCANVAS_COMMAND_RECT); |
| 252 this->writeRect(SKJSONCANVAS_ATTRIBUTE_COORDS, rect); |
| 253 this->writePaint(paint); |
| 254 this->close(); |
| 255 } |
| 256 |
| 257 void SkJSONCanvas::onDrawOval(const SkRect& rect, const SkPaint& paint) { |
| 258 this->updateMatrix(); |
| 259 this->open(SKJSONCANVAS_COMMAND_OVAL); |
| 260 this->writeRect(SKJSONCANVAS_ATTRIBUTE_COORDS, rect); |
| 261 this->writePaint(paint); |
| 262 this->close(); |
| 263 } |
| 264 |
| 265 void SkJSONCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) { |
| 266 this->updateMatrix(); |
| 267 this->open(SKJSONCANVAS_COMMAND_RRECT); |
| 268 this->writeRRect(SKJSONCANVAS_ATTRIBUTE_COORDS, rrect); |
| 269 this->writePaint(paint); |
| 270 this->close();} |
| 271 |
| 272 void SkJSONCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, cons
t SkPaint& paint) { |
| 273 this->updateMatrix(); |
| 274 this->open(SKJSONCANVAS_COMMAND_DRRECT); |
| 275 this->writeRRect(SKJSONCANVAS_ATTRIBUTE_OUTER, outer); |
| 276 this->writeRRect(SKJSONCANVAS_ATTRIBUTE_INNER, inner); |
| 277 this->writePaint(paint); |
| 278 this->close(); |
| 279 } |
| 280 |
| 281 void SkJSONCanvas::onDrawPoints(SkCanvas::PointMode mode, size_t count, const Sk
Point pts[], |
| 282 const SkPaint& p
aint) { |
| 283 this->updateMatrix(); |
| 284 this->open(SKJSONCANVAS_COMMAND_POINTS); |
| 285 this->writePointMode(SKJSONCANVAS_ATTRIBUTE_MODE, mode); |
| 286 fOut.writeText(",\"" SKJSONCANVAS_ATTRIBUTE_POINTS "\":["); |
| 287 for (size_t i = 0; i < count; i++) { |
| 288 if (i != 0) { |
| 289 fOut.writeText(","); |
| 290 } |
| 291 this->writef("[%f,%f]", pts[i].x(), pts[i].y()); |
| 292 } |
| 293 fOut.writeText("]"); |
| 294 this->writePaint(paint); |
| 295 this->close(); |
| 296 } |
| 297 |
| 298 void SkJSONCanvas::onDrawVertices(SkCanvas::VertexMode, int vertexCount, const S
kPoint vertices[], |
| 299 const SkPoint texs[], const SkColor colors[],
SkXfermode*, |
| 300 const uint16_t indices[], int indexCount, cons
t SkPaint&) { |
| 301 SkDebugf("unsupported: drawVertices\n"); |
| 302 } |
| 303 |
| 304 void SkJSONCanvas::onDrawAtlas(const SkImage*, const SkRSXform[], const SkRect[]
, const SkColor[], |
| 305 int count, SkXfermode::Mode, const SkRect* cull,
const SkPaint*) { |
| 306 SkDebugf("unsupported: drawAtlas\n"); |
| 307 } |
| 308 |
| 309 void SkJSONCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) { |
| 310 this->updateMatrix(); |
| 311 this->open(SKJSONCANVAS_COMMAND_PATH); |
| 312 this->writePath(SKJSONCANVAS_ATTRIBUTE_PATH, path); |
| 313 this->writePaint(paint); |
| 314 this->close();} |
| 315 |
| 316 void SkJSONCanvas::onDrawImage(const SkImage*, SkScalar dx, SkScalar dy, const S
kPaint*) { |
| 317 SkDebugf("unsupported: drawImage\n"); |
| 318 } |
| 319 |
| 320 void SkJSONCanvas::onDrawImageRect(const SkImage*, const SkRect*, const SkRect&,
const SkPaint*, |
| 321 SkCanvas::SrcRectConstraint) { |
| 322 SkDebugf("unsupported: drawImageRect\n"); |
| 323 } |
| 324 |
| 325 void SkJSONCanvas::onDrawImageNine(const SkImage*, const SkIRect& center, const
SkRect& dst, |
| 326 const SkPaint*) { |
| 327 SkDebugf("unsupported: drawImageNine\n"); |
| 328 } |
| 329 |
| 330 void SkJSONCanvas::onDrawBitmap(const SkBitmap&, SkScalar dx, SkScalar dy, const
SkPaint*) { |
| 331 SkDebugf("unsupported: drawBitmap\n"); |
| 332 } |
| 333 |
| 334 void SkJSONCanvas::onDrawBitmapRect(const SkBitmap&, const SkRect*, const SkRect
&, const SkPaint*, |
| 335 SkCanvas::SrcRectConstraint) { |
| 336 SkDebugf("unsupported: drawBitmapRect\n"); |
| 337 } |
| 338 |
| 339 void SkJSONCanvas::onDrawBitmapNine(const SkBitmap&, const SkIRect& center, cons
t SkRect& dst, |
| 340 const SkPaint*) { |
| 341 SkDebugf("unsupported: drawBitmapNine\n"); |
| 342 } |
| 343 |
| 344 void SkJSONCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, |
| 345 SkScalar y, const SkPaint& paint) { |
| 346 this->updateMatrix(); |
| 347 this->open(SKJSONCANVAS_COMMAND_TEXT); |
| 348 this->writeString(SKJSONCANVAS_ATTRIBUTE_TEXT, text, byteLength); |
| 349 this->writePoint(SKJSONCANVAS_ATTRIBUTE_COORDS, { x, y }); |
| 350 this->writePaint(paint); |
| 351 this->close(); |
| 352 } |
| 353 |
| 354 void SkJSONCanvas::onDrawPosText(const void* text, size_t byteLength, |
| 355 const SkPoint pos[], const SkPaint& paint) { |
| 356 SkDebugf("unsupported: drawPosText\n"); |
| 357 } |
| 358 |
| 359 void SkJSONCanvas::onDrawPosTextH(const void* text, size_t byteLength, |
| 360 const SkScalar xpos[], SkScalar constY, |
| 361 const SkPaint& paint) { |
| 362 SkDebugf("unsupported: drawPosTextH\n"); |
| 363 } |
| 364 |
| 365 void SkJSONCanvas::onDrawTextOnPath(const void* text, size_t byteLength, |
| 366 const SkPath& path, const SkMatrix* matrix, |
| 367 const SkPaint& paint) { |
| 368 SkDebugf("unsupported: drawTextOnPath\n"); |
| 369 } |
| 370 |
| 371 void SkJSONCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y
, |
| 372 const SkPaint& paint) { |
| 373 SkDebugf("unsupported: drawTextBlob\n"); |
| 374 } |
| 375 |
| 376 void SkJSONCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4]
, |
| 377 const SkPoint texCoords[4], SkXfermode* xmode, |
| 378 const SkPaint& paint) { |
| 379 SkDebugf("unsupported: drawPatch\n"); |
| 380 } |
| 381 |
| 382 void SkJSONCanvas::onDrawDrawable(SkDrawable*, const SkMatrix*) { |
| 383 SkDebugf("unsupported: drawDrawable\n"); |
| 384 } |
| 385 |
| 386 void SkJSONCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle
edgeStyle) { |
| 387 this->updateMatrix(); |
| 388 this->open(SKJSONCANVAS_COMMAND_CLIPRECT); |
| 389 this->writeRect(SKJSONCANVAS_ATTRIBUTE_COORDS, rect); |
| 390 this->writeRegionOp(SKJSONCANVAS_ATTRIBUTE_REGIONOP, op); |
| 391 this->writeEdgeStyle(SKJSONCANVAS_ATTRIBUTE_EDGESTYLE, edgeStyle); |
| 392 this->close(); |
| 393 } |
| 394 |
| 395 void SkJSONCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeSt
yle edgeStyle) { |
| 396 this->updateMatrix(); |
| 397 this->open(SKJSONCANVAS_COMMAND_CLIPRRECT); |
| 398 this->writeRRect(SKJSONCANVAS_ATTRIBUTE_COORDS, rrect); |
| 399 this->writeRegionOp(SKJSONCANVAS_ATTRIBUTE_REGIONOP, op); |
| 400 this->writeEdgeStyle(SKJSONCANVAS_ATTRIBUTE_EDGESTYLE, edgeStyle); |
| 401 this->close(); |
| 402 } |
| 403 |
| 404 void SkJSONCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle
edgeStyle) { |
| 405 updateMatrix(); |
| 406 this->open(SKJSONCANVAS_COMMAND_CLIPPATH); |
| 407 this->writePath(SKJSONCANVAS_ATTRIBUTE_PATH, path); |
| 408 this->writeRegionOp(SKJSONCANVAS_ATTRIBUTE_REGIONOP, op); |
| 409 this->writeEdgeStyle(SKJSONCANVAS_ATTRIBUTE_EDGESTYLE, edgeStyle); |
| 410 this->close(); |
| 411 } |
| 412 |
| 413 void SkJSONCanvas::onClipRegion(const SkRegion& deviceRgn, SkRegion::Op op) { |
| 414 this->open(SKJSONCANVAS_COMMAND_CLIPREGION); |
| 415 this->writeRegion(SKJSONCANVAS_ATTRIBUTE_DEVICEREGION, deviceRgn); |
| 416 this->writeRegionOp(SKJSONCANVAS_ATTRIBUTE_REGIONOP, op); |
| 417 this->close(); |
| 418 } |
| 419 |
| 420 void SkJSONCanvas::willSave() { |
| 421 this->open(SKJSONCANVAS_COMMAND_SAVE); |
| 422 this->close(); |
| 423 } |
| 424 |
| 425 void SkJSONCanvas::willRestore() { |
| 426 this->open(SKJSONCANVAS_COMMAND_RESTORE); |
| 427 this->close(); |
| 428 } |
OLD | NEW |