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 "SkJSONRenderer.h" |
| 9 #include "SkJSONCanvas.h" |
| 10 #include "SkJSONCPP.h" |
| 11 #include "SkPath.h" |
| 12 |
| 13 namespace SkJSONRenderer { |
| 14 |
| 15 class Renderer { |
| 16 public: |
| 17 void getPaint(Json::Value& command, SkPaint* paint); |
| 18 |
| 19 void getRect(Json::Value& command, const char* name, SkRect* rect); |
| 20 |
| 21 void getRRect(Json::Value& command, const char* name, SkRRect* rrect); |
| 22 |
| 23 void processCommand(Json::Value& command, SkCanvas* target); |
| 24 |
| 25 void processMatrix(Json::Value& command, SkCanvas* target); |
| 26 |
| 27 void processSave(Json::Value& command, SkCanvas* target); |
| 28 |
| 29 void processRestore(Json::Value& command, SkCanvas* target); |
| 30 |
| 31 void processPaint(Json::Value& command, SkCanvas* target); |
| 32 |
| 33 void processRect(Json::Value& command, SkCanvas* target); |
| 34 |
| 35 void processRRect(Json::Value& command, SkCanvas* target); |
| 36 |
| 37 void processOval(Json::Value& command, SkCanvas* target); |
| 38 |
| 39 void processPath(Json::Value& command, SkCanvas* target); |
| 40 |
| 41 void processText(Json::Value& command, SkCanvas* target); |
| 42 |
| 43 void processPoints(Json::Value& command, SkCanvas* target); |
| 44 |
| 45 void processClipRect(Json::Value& command, SkCanvas* target); |
| 46 }; |
| 47 |
| 48 void Renderer::processCommand(Json::Value& command, SkCanvas* target) { |
| 49 const char* name = command[SKJSONCANVAS_COMMAND].asCString(); |
| 50 // TODO speed this up with a hash |
| 51 if (!strcmp(name, SKJSONCANVAS_COMMAND_MATRIX)) { |
| 52 this->processMatrix(command, target); |
| 53 } |
| 54 else if (!strcmp(name, SKJSONCANVAS_COMMAND_SAVE)) { |
| 55 this->processSave(command, target); |
| 56 } |
| 57 else if (!strcmp(name, SKJSONCANVAS_COMMAND_RESTORE)) { |
| 58 this->processRestore(command, target); |
| 59 } |
| 60 else if (!strcmp(name, SKJSONCANVAS_COMMAND_PAINT)) { |
| 61 this->processPaint(command, target); |
| 62 } |
| 63 else if (!strcmp(name, SKJSONCANVAS_COMMAND_RECT)) { |
| 64 this->processRect(command, target); |
| 65 } |
| 66 else if (!strcmp(name, SKJSONCANVAS_COMMAND_RRECT)) { |
| 67 this->processRRect(command, target); |
| 68 } |
| 69 else if (!strcmp(name, SKJSONCANVAS_COMMAND_OVAL)) { |
| 70 this->processOval(command, target); |
| 71 } |
| 72 else if (!strcmp(name, SKJSONCANVAS_COMMAND_PATH)) { |
| 73 this->processPath(command, target); |
| 74 } |
| 75 else if (!strcmp(name, SKJSONCANVAS_COMMAND_TEXT)) { |
| 76 this->processText(command, target); |
| 77 } |
| 78 else if (!strcmp(name, SKJSONCANVAS_COMMAND_POINTS)) { |
| 79 this->processPoints(command, target); |
| 80 } |
| 81 else if (!strcmp(name, SKJSONCANVAS_COMMAND_CLIPRECT)) { |
| 82 this->processClipRect(command, target); |
| 83 } |
| 84 else { |
| 85 SkDebugf("unsupported JSON command: %s\n", name); |
| 86 } |
| 87 } |
| 88 |
| 89 void Renderer::getPaint(Json::Value& command, SkPaint* result) { |
| 90 Json::Value jsonPaint = command[SKJSONCANVAS_ATTRIBUTE_PAINT]; |
| 91 if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_COLOR)) { |
| 92 Json::Value color = jsonPaint[SKJSONCANVAS_ATTRIBUTE_COLOR]; |
| 93 result->setColor(SkColorSetARGB(color[0].asInt(), color[1].asInt(), colo
r[2].asInt(), |
| 94 color[3].asInt())); |
| 95 } |
| 96 if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_STYLE)) { |
| 97 const char* style = jsonPaint[SKJSONCANVAS_ATTRIBUTE_STYLE].asCString(); |
| 98 if (!strcmp(style, SKJSONCANVAS_STYLE_FILL)) { |
| 99 result->setStyle(SkPaint::kFill_Style); |
| 100 } |
| 101 else if (!strcmp(style, SKJSONCANVAS_STYLE_STROKE)) { |
| 102 result->setStyle(SkPaint::kStroke_Style); |
| 103 } |
| 104 else if (!strcmp(style, SKJSONCANVAS_STYLE_STROKEANDFILL)) { |
| 105 result->setStyle(SkPaint::kStrokeAndFill_Style); |
| 106 } |
| 107 } |
| 108 if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_STROKEWIDTH)) { |
| 109 float strokeWidth = jsonPaint[SKJSONCANVAS_ATTRIBUTE_STROKEWIDTH].asFloa
t(); |
| 110 result->setStrokeWidth(strokeWidth); |
| 111 } |
| 112 if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_ANTIALIAS)) { |
| 113 result->setAntiAlias(jsonPaint[SKJSONCANVAS_ATTRIBUTE_ANTIALIAS].asBool(
)); |
| 114 } |
| 115 } |
| 116 |
| 117 void Renderer::getRect(Json::Value& command, const char* name, SkRect* result) { |
| 118 Json::Value rect = command[name]; |
| 119 result->set(rect[0].asFloat(), rect[1].asFloat(), rect[2].asFloat(), rect[3]
.asFloat()); |
| 120 } |
| 121 |
| 122 void Renderer::getRRect(Json::Value& command, const char* name, SkRRect* result)
{ |
| 123 Json::Value rrect = command[name]; |
| 124 SkVector radii[4] = { |
| 125 { rrect[1][0].asFloat(), rrect[1][1].asFloat() }, |
| 126 { rrect[2][0].asFloat(), rrect[2][1].asFloat() }, |
| 127 { rrect[3][0].asFloat(), rrect[3][1].asFloat() }, |
| 128 { rrect[4][0].asFloat(), rrect[4][1].asFloat() } |
| 129 }; |
| 130 result->setRectRadii(SkRect::MakeLTRB(rrect[0][0].asFloat(), rrect[0][1].asF
loat(), |
| 131 rrect[0][2].asFloat(), rrect[0][3].asF
loat()), |
| 132 radii); |
| 133 } |
| 134 |
| 135 void Renderer::processMatrix(Json::Value& command, SkCanvas* target) { |
| 136 Json::Value jsonMatrix = command[SKJSONCANVAS_ATTRIBUTE_MATRIX]; |
| 137 SkMatrix matrix; |
| 138 SkScalar values[] = { |
| 139 jsonMatrix[0][0].asFloat(), jsonMatrix[0][1].asFloat(), jsonMatrix[0][2]
.asFloat(), |
| 140 jsonMatrix[1][0].asFloat(), jsonMatrix[1][1].asFloat(), jsonMatrix[1][2]
.asFloat(), |
| 141 jsonMatrix[2][0].asFloat(), jsonMatrix[2][1].asFloat(), jsonMatrix[2][2]
.asFloat() |
| 142 }; |
| 143 matrix.set9(values); |
| 144 target->setMatrix(matrix); |
| 145 } |
| 146 |
| 147 void Renderer::processSave(Json::Value& command, SkCanvas* target) { |
| 148 target->save(); |
| 149 } |
| 150 |
| 151 void Renderer::processRestore(Json::Value& command, SkCanvas* target) { |
| 152 target->restore(); |
| 153 } |
| 154 |
| 155 void Renderer::processPaint(Json::Value& command, SkCanvas* target) { |
| 156 SkPaint paint; |
| 157 this->getPaint(command, &paint); |
| 158 target->drawPaint(paint); |
| 159 } |
| 160 |
| 161 void Renderer::processRect(Json::Value& command, SkCanvas* target) { |
| 162 SkRect rect; |
| 163 this->getRect(command, SKJSONCANVAS_ATTRIBUTE_COORDS, &rect); |
| 164 SkPaint paint; |
| 165 this->getPaint(command, &paint); |
| 166 target->drawRect(rect, paint); |
| 167 } |
| 168 |
| 169 void Renderer::processRRect(Json::Value& command, SkCanvas* target) { |
| 170 SkRRect rrect; |
| 171 this->getRRect(command, SKJSONCANVAS_ATTRIBUTE_COORDS, &rrect); |
| 172 SkPaint paint; |
| 173 this->getPaint(command, &paint); |
| 174 target->drawRRect(rrect, paint); |
| 175 } |
| 176 |
| 177 void Renderer::processOval(Json::Value& command, SkCanvas* target) { |
| 178 SkRect rect; |
| 179 this->getRect(command, SKJSONCANVAS_ATTRIBUTE_COORDS, &rect); |
| 180 SkPaint paint; |
| 181 this->getPaint(command, &paint); |
| 182 target->drawOval(rect, paint); |
| 183 } |
| 184 |
| 185 void Renderer::processPath(Json::Value& command, SkCanvas* target) { |
| 186 Json::Value jsonPath = command[SKJSONCANVAS_ATTRIBUTE_PATH]; |
| 187 SkPath path; |
| 188 for (Json::ArrayIndex i = 0; i < jsonPath.size(); i++) { |
| 189 Json::Value verb = jsonPath[i]; |
| 190 if (verb.isString()) { |
| 191 SkASSERT(!strcmp(verb.asCString(), SKJSONCANVAS_VERB_CLOSE)); |
| 192 path.close(); |
| 193 } |
| 194 else { |
| 195 if (verb.isMember(SKJSONCANVAS_VERB_MOVE)) { |
| 196 Json::Value move = verb[SKJSONCANVAS_VERB_MOVE]; |
| 197 path.moveTo(move[0].asFloat(), move[1].asFloat()); |
| 198 } |
| 199 else if (verb.isMember(SKJSONCANVAS_VERB_LINE)) { |
| 200 Json::Value line = verb[SKJSONCANVAS_VERB_LINE]; |
| 201 path.lineTo(line[0].asFloat(), line[1].asFloat()); |
| 202 } |
| 203 else if (verb.isMember(SKJSONCANVAS_VERB_QUAD)) { |
| 204 Json::Value quad = verb[SKJSONCANVAS_VERB_QUAD]; |
| 205 path.quadTo(quad[0][0].asFloat(), quad[0][1].asFloat(), |
| 206 quad[1][0].asFloat(), quad[1][1].asFloat()); |
| 207 } |
| 208 else if (verb.isMember(SKJSONCANVAS_VERB_CUBIC)) { |
| 209 Json::Value cubic = verb[SKJSONCANVAS_VERB_CUBIC]; |
| 210 path.cubicTo(cubic[0][0].asFloat(), cubic[0][1].asFloat(), |
| 211 cubic[1][0].asFloat(), cubic[1][1].asFloat(), |
| 212 cubic[2][0].asFloat(), cubic[2][1].asFloat()); |
| 213 } |
| 214 else if (verb.isMember(SKJSONCANVAS_VERB_CONIC)) { |
| 215 Json::Value conic = verb[SKJSONCANVAS_VERB_CONIC]; |
| 216 path.conicTo(conic[0][0].asFloat(), conic[0][1].asFloat(), |
| 217 conic[1][0].asFloat(), conic[1][1].asFloat(), |
| 218 conic[2].asFloat()); |
| 219 } |
| 220 else { |
| 221 SkASSERT(false); |
| 222 } |
| 223 } |
| 224 } |
| 225 SkPaint paint; |
| 226 this->getPaint(command, &paint); |
| 227 target->drawPath(path, paint); |
| 228 } |
| 229 |
| 230 void Renderer::processText(Json::Value& command, SkCanvas* target) { |
| 231 const char* text = command[SKJSONCANVAS_ATTRIBUTE_TEXT].asCString(); |
| 232 SkPaint paint; |
| 233 this->getPaint(command, &paint); |
| 234 Json::Value coords = command[SKJSONCANVAS_ATTRIBUTE_COORDS]; |
| 235 target->drawText(text, strlen(text), coords[0].asFloat(), coords[1].asFloat(
), paint); |
| 236 } |
| 237 |
| 238 void Renderer::processPoints(Json::Value& command, SkCanvas* target) { |
| 239 SkCanvas::PointMode mode; |
| 240 const char* jsonMode = command[SKJSONCANVAS_ATTRIBUTE_MODE].asCString(); |
| 241 if (!strcmp(jsonMode, SKJSONCANVAS_POINTMODE_POINTS)) { |
| 242 mode = SkCanvas::kPoints_PointMode; |
| 243 } |
| 244 else if (!strcmp(jsonMode, SKJSONCANVAS_POINTMODE_LINES)) { |
| 245 mode = SkCanvas::kLines_PointMode; |
| 246 } |
| 247 else if (!strcmp(jsonMode, SKJSONCANVAS_POINTMODE_POLYGON)) { |
| 248 mode = SkCanvas::kPolygon_PointMode; |
| 249 } |
| 250 else { |
| 251 SkASSERT(false); |
| 252 return; |
| 253 } |
| 254 Json::Value jsonPoints = command[SKJSONCANVAS_ATTRIBUTE_POINTS]; |
| 255 int count = (int) jsonPoints.size(); |
| 256 SkPoint* points = (SkPoint*) sk_malloc_throw(count * sizeof(SkPoint)); |
| 257 for (int i = 0; i < count; i++) { |
| 258 points[i] = SkPoint::Make(jsonPoints[i][0].asFloat(), jsonPoints[i][1].a
sFloat()); |
| 259 } |
| 260 SkPaint paint; |
| 261 this->getPaint(command, &paint); |
| 262 target->drawPoints(mode, count, points, paint); |
| 263 free(points); |
| 264 } |
| 265 |
| 266 void Renderer::processClipRect(Json::Value& command, SkCanvas* target) { |
| 267 SkRect rect; |
| 268 this->getRect(command, SKJSONCANVAS_ATTRIBUTE_COORDS, &rect); |
| 269 target->clipRect(rect); |
| 270 } |
| 271 |
| 272 void render(const char* json, SkCanvas* target) { |
| 273 Renderer renderer; |
| 274 Json::Reader reader; |
| 275 Json::Value root; |
| 276 if (reader.parse(std::string(json), root)) { |
| 277 SkASSERT(root[SKJSONCANVAS_VERSION].asInt() == 1); |
| 278 Json::Value commands = root[SKJSONCANVAS_COMMANDS]; |
| 279 for (Json::ArrayIndex i = 0; i < commands.size(); i++) { |
| 280 renderer.processCommand(commands[i], target); |
| 281 } |
| 282 } |
| 283 else { |
| 284 SkDebugf(json); |
| 285 SkFAIL("json parse failure"); |
| 286 } |
| 287 } |
| 288 |
| 289 } // namespace |
OLD | NEW |