Index: tools/json/SkJSONRenderer.cpp |
diff --git a/tools/json/SkJSONRenderer.cpp b/tools/json/SkJSONRenderer.cpp |
index a830fe0fb5f84cb79cc91c975e8bca9e9b57d59b..734ce116b44f46a102be248f78642d503de7740b 100644 |
--- a/tools/json/SkJSONRenderer.cpp |
+++ b/tools/json/SkJSONRenderer.cpp |
@@ -12,6 +12,7 @@ |
#include "SkJSONCanvas.h" |
#include "SkJSONCPP.h" |
#include "SkPath.h" |
+#include "SkValidatingReadBuffer.h" |
namespace SkJSONRenderer { |
@@ -35,6 +36,8 @@ public: |
void processRestore(Json::Value& command, SkCanvas* target); |
+ void processSaveLayer(Json::Value& command, SkCanvas* target); |
+ |
void processPaint(Json::Value& command, SkCanvas* target); |
void processRect(Json::Value& command, SkCanvas* target); |
@@ -51,6 +54,14 @@ public: |
void processPoints(Json::Value& command, SkCanvas* target); |
+ void processImage(Json::Value& command, SkCanvas* target); |
+ |
+ void processImageRect(Json::Value& command, SkCanvas* target); |
+ |
+ void processBitmap(Json::Value& command, SkCanvas* target); |
+ |
+ void processBitmapRect(Json::Value& command, SkCanvas* target); |
+ |
void processClipRect(Json::Value& command, SkCanvas* target); |
void processClipRRect(Json::Value& command, SkCanvas* target); |
@@ -70,6 +81,9 @@ void Renderer::processCommand(Json::Value& command, SkCanvas* target) { |
else if (!strcmp(name, SKJSONCANVAS_COMMAND_RESTORE)) { |
this->processRestore(command, target); |
} |
+ else if (!strcmp(name, SKJSONCANVAS_COMMAND_SAVELAYER)) { |
+ this->processSaveLayer(command, target); |
+ } |
else if (!strcmp(name, SKJSONCANVAS_COMMAND_PAINT)) { |
this->processPaint(command, target); |
} |
@@ -94,6 +108,18 @@ void Renderer::processCommand(Json::Value& command, SkCanvas* target) { |
else if (!strcmp(name, SKJSONCANVAS_COMMAND_POINTS)) { |
this->processPoints(command, target); |
} |
+ else if (!strcmp(name, SKJSONCANVAS_COMMAND_IMAGE)) { |
+ this->processImage(command, target); |
+ } |
+ else if (!strcmp(name, SKJSONCANVAS_COMMAND_IMAGERECT)) { |
+ this->processImageRect(command, target); |
+ } |
+ else if (!strcmp(name, SKJSONCANVAS_COMMAND_BITMAP)) { |
+ this->processBitmap(command, target); |
+ } |
+ else if (!strcmp(name, SKJSONCANVAS_COMMAND_BITMAPRECT)) { |
+ this->processBitmapRect(command, target); |
+ } |
else if (!strcmp(name, SKJSONCANVAS_COMMAND_CLIPRECT)) { |
this->processClipRect(command, target); |
} |
@@ -108,32 +134,171 @@ void Renderer::processCommand(Json::Value& command, SkCanvas* target) { |
} |
} |
-void Renderer::getPaint(Json::Value& command, SkPaint* result) { |
- Json::Value jsonPaint = command[SKJSONCANVAS_ATTRIBUTE_PAINT]; |
+static void apply_paint_color(Json::Value& jsonPaint, SkPaint* target) { |
if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_COLOR)) { |
Json::Value color = jsonPaint[SKJSONCANVAS_ATTRIBUTE_COLOR]; |
- result->setColor(SkColorSetARGB(color[0].asInt(), color[1].asInt(), color[2].asInt(), |
+ target->setColor(SkColorSetARGB(color[0].asInt(), color[1].asInt(), color[2].asInt(), |
color[3].asInt())); |
} |
+} |
+ |
+// note that the caller is responsible for freeing the pointer |
+static Json::ArrayIndex decode_data(Json::Value bytes, void** target) { |
+ Json::ArrayIndex size = bytes.size(); |
+ *target = sk_malloc_throw(size); |
+ for (Json::ArrayIndex i = 0; i < size; i++) { |
+ ((uint8_t*) *target)[i] = bytes[i].asInt(); |
+ } |
+ return size; |
+} |
+ |
+static SkFlattenable* load_flattenable(Json::Value jsonFlattenable) { |
+ if (!jsonFlattenable.isMember(SKJSONCANVAS_ATTRIBUTE_NAME)) { |
+ return nullptr; |
+ } |
+ const char* name = jsonFlattenable[SKJSONCANVAS_ATTRIBUTE_NAME].asCString(); |
+ SkFlattenable::Factory factory = SkFlattenable::NameToFactory(name); |
+ if (factory == nullptr) { |
+ return nullptr; |
+ } |
+ void* data; |
+ int size = decode_data(jsonFlattenable[SKJSONCANVAS_ATTRIBUTE_BYTES], &data); |
+ SkValidatingReadBuffer buffer(data, size); |
+ SkFlattenable* result = factory(buffer); |
+ free(data); |
+ if (!buffer.isValid()) { |
+ return nullptr; |
+ } |
+ return result; |
+} |
+ |
+// caller is responsible for freeing return value |
+static SkBitmap* load_bitmap(Json::Value jsonBitmap) { |
+ if (!jsonBitmap.isMember(SKJSONCANVAS_ATTRIBUTE_BYTES)) { |
+ return nullptr; |
+ } |
+ void* data; |
+ int size = decode_data(jsonBitmap[SKJSONCANVAS_ATTRIBUTE_BYTES], &data); |
+ SkMemoryStream stream(data, size); |
+ SkImageDecoder* decoder = SkImageDecoder::Factory(&stream); |
+ SkBitmap* bitmap = new SkBitmap(); |
+ SkImageDecoder::Result result = decoder->decode(&stream, bitmap, |
+ SkImageDecoder::kDecodePixels_Mode); |
+ free(decoder); |
+ if (result != SkImageDecoder::kFailure) { |
+ free(data); |
+ return bitmap; |
+ } |
+ SkDebugf("image decode failed"); |
+ free(data); |
+ return nullptr; |
+} |
+ |
+static SkImage* load_image(Json::Value jsonImage) { |
+ SkBitmap* bitmap = load_bitmap(jsonImage); |
+ if (bitmap == nullptr) { |
+ return nullptr; |
+ } |
+ SkImage* result = SkImage::NewFromBitmap(*bitmap); |
+ free(bitmap); |
+ return result; |
+} |
+ |
+static void apply_paint_shader(Json::Value& jsonPaint, SkPaint* target) { |
+ if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_SHADER)) { |
+ Json::Value jsonShader = jsonPaint[SKJSONCANVAS_ATTRIBUTE_SHADER]; |
+ SkShader* shader = (SkShader*) load_flattenable(jsonShader); |
+ if (shader != nullptr) { |
+ target->setShader(shader); |
+ shader->unref(); |
+ } |
+ } |
+} |
+ |
+static void apply_paint_patheffect(Json::Value& jsonPaint, SkPaint* target) { |
+ if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_PATHEFFECT)) { |
+ Json::Value jsonPathEffect = jsonPaint[SKJSONCANVAS_ATTRIBUTE_PATHEFFECT]; |
+ SkPathEffect* pathEffect = (SkPathEffect*) load_flattenable(jsonPathEffect); |
+ if (pathEffect != nullptr) { |
+ target->setPathEffect(pathEffect); |
+ pathEffect->unref(); |
+ } |
+ } |
+} |
+ |
+static void apply_paint_maskfilter(Json::Value& jsonPaint, SkPaint* target) { |
+ if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_MASKFILTER)) { |
+ Json::Value jsonMaskFilter = jsonPaint[SKJSONCANVAS_ATTRIBUTE_MASKFILTER]; |
+ SkMaskFilter* maskFilter = (SkMaskFilter*) load_flattenable(jsonMaskFilter); |
+ if (maskFilter != nullptr) { |
+ target->setMaskFilter(maskFilter); |
+ maskFilter->unref(); |
+ } |
+ } |
+} |
+ |
+static void apply_paint_xfermode(Json::Value& jsonPaint, SkPaint* target) { |
+ if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_XFERMODE)) { |
+ Json::Value jsonXfermode = jsonPaint[SKJSONCANVAS_ATTRIBUTE_XFERMODE]; |
+ SkXfermode* xfermode = (SkXfermode*) load_flattenable(jsonXfermode); |
+ if (xfermode != nullptr) { |
+ target->setXfermode(xfermode); |
+ xfermode->unref(); |
+ } |
+ } |
+} |
+ |
+static void apply_paint_style(Json::Value& jsonPaint, SkPaint* target) { |
if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_STYLE)) { |
const char* style = jsonPaint[SKJSONCANVAS_ATTRIBUTE_STYLE].asCString(); |
if (!strcmp(style, SKJSONCANVAS_STYLE_FILL)) { |
- result->setStyle(SkPaint::kFill_Style); |
+ target->setStyle(SkPaint::kFill_Style); |
} |
else if (!strcmp(style, SKJSONCANVAS_STYLE_STROKE)) { |
- result->setStyle(SkPaint::kStroke_Style); |
+ target->setStyle(SkPaint::kStroke_Style); |
} |
else if (!strcmp(style, SKJSONCANVAS_STYLE_STROKEANDFILL)) { |
- result->setStyle(SkPaint::kStrokeAndFill_Style); |
+ target->setStyle(SkPaint::kStrokeAndFill_Style); |
} |
} |
+} |
+ |
+static void apply_paint_strokewidth(Json::Value& jsonPaint, SkPaint* target) { |
if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_STROKEWIDTH)) { |
float strokeWidth = jsonPaint[SKJSONCANVAS_ATTRIBUTE_STROKEWIDTH].asFloat(); |
- result->setStrokeWidth(strokeWidth); |
+ target->setStrokeWidth(strokeWidth); |
+ } |
+} |
+ |
+static void apply_paint_strokemiter(Json::Value& jsonPaint, SkPaint* target) { |
+ if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_STROKEMITER)) { |
+ float strokeMiter = jsonPaint[SKJSONCANVAS_ATTRIBUTE_STROKEMITER].asFloat(); |
+ target->setStrokeMiter(strokeMiter); |
+ } |
+} |
+ |
+static void apply_paint_cap(Json::Value& jsonPaint, SkPaint* target) { |
+ if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_CAP)) { |
+ const char* cap = jsonPaint[SKJSONCANVAS_ATTRIBUTE_CAP].asCString(); |
+ if (!strcmp(cap, SKJSONCANVAS_CAP_BUTT)) { |
+ target->setStrokeCap(SkPaint::kButt_Cap); |
+ } |
+ else if (!strcmp(cap, SKJSONCANVAS_CAP_ROUND)) { |
+ target->setStrokeCap(SkPaint::kRound_Cap); |
+ } |
+ else if (!strcmp(cap, SKJSONCANVAS_CAP_SQUARE)) { |
+ target->setStrokeCap(SkPaint::kSquare_Cap); |
+ } |
} |
+} |
+ |
+static void apply_paint_antialias(Json::Value& jsonPaint, SkPaint* target) { |
if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_ANTIALIAS)) { |
- result->setAntiAlias(jsonPaint[SKJSONCANVAS_ATTRIBUTE_ANTIALIAS].asBool()); |
+ target->setAntiAlias(jsonPaint[SKJSONCANVAS_ATTRIBUTE_ANTIALIAS].asBool()); |
} |
+} |
+ |
+static void apply_paint_blur(Json::Value& jsonPaint, SkPaint* target) { |
if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_BLUR)) { |
Json::Value blur = jsonPaint[SKJSONCANVAS_ATTRIBUTE_BLUR]; |
SkScalar sigma = blur[SKJSONCANVAS_ATTRIBUTE_SIGMA].asFloat(); |
@@ -167,8 +332,11 @@ void Renderer::getPaint(Json::Value& command, SkPaint* result) { |
SkASSERT(false); |
flags = SkBlurMaskFilter::BlurFlags::kNone_BlurFlag; |
} |
- result->setMaskFilter(SkBlurMaskFilter::Create(style, sigma, flags)); |
+ target->setMaskFilter(SkBlurMaskFilter::Create(style, sigma, flags)); |
} |
+} |
+ |
+static void apply_paint_dashing(Json::Value& jsonPaint, SkPaint* target) { |
if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_DASHING)) { |
Json::Value dash = jsonPaint[SKJSONCANVAS_ATTRIBUTE_DASHING]; |
Json::Value jsonIntervals = dash[SKJSONCANVAS_ATTRIBUTE_INTERVALS]; |
@@ -178,9 +346,12 @@ void Renderer::getPaint(Json::Value& command, SkPaint* result) { |
intervals[i] = jsonIntervals[i].asFloat(); |
} |
SkScalar phase = dash[SKJSONCANVAS_ATTRIBUTE_PHASE].asFloat(); |
- result->setPathEffect(SkDashPathEffect::Create(intervals, count, phase)); |
+ target->setPathEffect(SkDashPathEffect::Create(intervals, count, phase)); |
free(intervals); |
} |
+} |
+ |
+static void apply_paint_textalign(Json::Value& jsonPaint, SkPaint* target) { |
if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_TEXTALIGN)) { |
SkPaint::Align textAlign; |
const char* jsonAlign = jsonPaint[SKJSONCANVAS_ATTRIBUTE_TEXTALIGN].asCString(); |
@@ -197,22 +368,51 @@ void Renderer::getPaint(Json::Value& command, SkPaint* result) { |
SkASSERT(false); |
textAlign = SkPaint::kLeft_Align; |
} |
- result->setTextAlign(textAlign); |
+ target->setTextAlign(textAlign); |
} |
+} |
+ |
+static void apply_paint_textsize(Json::Value& jsonPaint, SkPaint* target) { |
if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_TEXTSIZE)) { |
float textSize = jsonPaint[SKJSONCANVAS_ATTRIBUTE_TEXTSIZE].asFloat(); |
- result->setTextSize(textSize); |
+ target->setTextSize(textSize); |
} |
+} |
+ |
+static void apply_paint_textscalex(Json::Value& jsonPaint, SkPaint* target) { |
if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_TEXTSCALEX)) { |
float textScaleX = jsonPaint[SKJSONCANVAS_ATTRIBUTE_TEXTSCALEX].asFloat(); |
- result->setTextScaleX(textScaleX); |
+ target->setTextScaleX(textScaleX); |
} |
+} |
+ |
+static void apply_paint_textskewx(Json::Value& jsonPaint, SkPaint* target) { |
if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_TEXTSKEWX)) { |
float textSkewX = jsonPaint[SKJSONCANVAS_ATTRIBUTE_TEXTSKEWX].asFloat(); |
- result->setTextSkewX(textSkewX); |
+ target->setTextSkewX(textSkewX); |
} |
} |
+void Renderer::getPaint(Json::Value& command, SkPaint* result) { |
+ Json::Value jsonPaint = command[SKJSONCANVAS_ATTRIBUTE_PAINT]; |
+ apply_paint_color(jsonPaint, result); |
+ apply_paint_shader(jsonPaint, result); |
+ apply_paint_patheffect(jsonPaint, result); |
+ apply_paint_maskfilter(jsonPaint, result); |
+ apply_paint_xfermode(jsonPaint, result); |
+ apply_paint_style(jsonPaint, result); |
+ apply_paint_strokewidth(jsonPaint, result); |
+ apply_paint_strokemiter(jsonPaint, result); |
+ apply_paint_cap(jsonPaint, result); |
+ apply_paint_antialias(jsonPaint, result); |
+ apply_paint_blur(jsonPaint, result); |
+ apply_paint_dashing(jsonPaint, result); |
+ apply_paint_textalign(jsonPaint, result); |
+ apply_paint_textsize(jsonPaint, result); |
+ apply_paint_textscalex(jsonPaint, result); |
+ apply_paint_textskewx(jsonPaint, result); |
+} |
+ |
void Renderer::getRect(Json::Value& command, const char* name, SkRect* result) { |
Json::Value rect = command[name]; |
result->set(rect[0].asFloat(), rect[1].asFloat(), rect[2].asFloat(), rect[3].asFloat()); |
@@ -330,6 +530,27 @@ void Renderer::processRestore(Json::Value& command, SkCanvas* target) { |
target->restore(); |
} |
+void Renderer::processSaveLayer(Json::Value& command, SkCanvas* target) { |
+ SkCanvas::SaveLayerRec rec; |
+ SkRect bounds; |
+ if (command.isMember(SKJSONCANVAS_ATTRIBUTE_BOUNDS)) { |
+ this->getRect(command, SKJSONCANVAS_ATTRIBUTE_BOUNDS, &bounds); |
+ rec.fBounds = &bounds; |
+ } |
+ SkPaint paint; |
+ if (command.isMember(SKJSONCANVAS_ATTRIBUTE_PAINT)) { |
+ this->getPaint(command, &paint); |
+ rec.fPaint = &paint; |
+ } |
+ if (command.isMember(SKJSONCANVAS_ATTRIBUTE_BACKDROP)) { |
+ rec.fBackdrop = (SkImageFilter*) load_flattenable(command[SKJSONCANVAS_ATTRIBUTE_BACKDROP]); |
+ } |
+ target->saveLayer(rec); |
+ if (rec.fBackdrop != nullptr) { |
+ rec.fBackdrop->unref(); |
+ } |
+} |
+ |
void Renderer::processPaint(Json::Value& command, SkCanvas* target) { |
SkPaint paint; |
this->getPaint(command, &paint); |
@@ -440,6 +661,114 @@ void Renderer::processClipPath(Json::Value& command, SkCanvas* target) { |
command[SKJSONCANVAS_ATTRIBUTE_ANTIALIAS].asBool()); |
} |
+void Renderer::processImage(Json::Value& command, SkCanvas* target) { |
+ SkImage* image = load_image(command[SKJSONCANVAS_ATTRIBUTE_IMAGE]); |
+ if (image == nullptr) { |
+ return; |
+ } |
+ Json::Value point = command[SKJSONCANVAS_ATTRIBUTE_COORDS]; |
+ SkPaint* paintPtr; |
+ SkPaint paint; |
+ if (command.isMember(SKJSONCANVAS_ATTRIBUTE_PAINT)) { |
+ this->getPaint(command, &paint); |
+ paintPtr = &paint; |
+ } |
+ else { |
+ paintPtr = nullptr; |
+ } |
+ target->drawImage(image, point[0].asFloat(), point[1].asFloat(), paintPtr); |
+ image->unref(); |
+} |
+ |
+void Renderer::processImageRect(Json::Value& command, SkCanvas* target) { |
+ SkImage* image = load_image(command[SKJSONCANVAS_ATTRIBUTE_IMAGE]); |
+ if (image == nullptr) { |
+ return; |
+ } |
+ SkRect dst; |
+ this->getRect(command, SKJSONCANVAS_ATTRIBUTE_DST, &dst); |
+ SkPaint* paintPtr; |
+ SkPaint paint; |
+ if (command.isMember(SKJSONCANVAS_ATTRIBUTE_PAINT)) { |
+ this->getPaint(command, &paint); |
+ paintPtr = &paint; |
+ } |
+ else { |
+ paintPtr = nullptr; |
+ } |
+ SkCanvas::SrcRectConstraint constraint; |
+ if (command.isMember(SKJSONCANVAS_ATTRIBUTE_STRICT) && |
+ command[SKJSONCANVAS_ATTRIBUTE_STRICT].asBool()) { |
+ constraint = SkCanvas::kStrict_SrcRectConstraint; |
+ } |
+ else { |
+ constraint = SkCanvas::kFast_SrcRectConstraint; |
+ } |
+ if (command.isMember(SKJSONCANVAS_ATTRIBUTE_SRC)) { |
+ SkRect src; |
+ this->getRect(command, SKJSONCANVAS_ATTRIBUTE_SRC, &src); |
+ target->drawImageRect(image, src, dst, paintPtr, constraint); |
+ } |
+ else { |
+ target->drawImageRect(image, dst, paintPtr, constraint); |
+ } |
+ image->unref(); |
+} |
+ |
+void Renderer::processBitmap(Json::Value& command, SkCanvas* target) { |
+ SkImage* image = load_image(command[SKJSONCANVAS_ATTRIBUTE_BITMAP]); |
+ if (image == nullptr) { |
+ return; |
+ } |
+ Json::Value point = command[SKJSONCANVAS_ATTRIBUTE_COORDS]; |
+ SkPaint* paintPtr; |
+ SkPaint paint; |
+ if (command.isMember(SKJSONCANVAS_ATTRIBUTE_PAINT)) { |
+ this->getPaint(command, &paint); |
+ paintPtr = &paint; |
+ } |
+ else { |
+ paintPtr = nullptr; |
+ } |
+ target->drawImage(image, point[0].asFloat(), point[1].asFloat(), paintPtr); |
+ image->unref(); |
+} |
+ |
+void Renderer::processBitmapRect(Json::Value& command, SkCanvas* target) { |
+ SkBitmap* bitmap = load_bitmap(command[SKJSONCANVAS_ATTRIBUTE_BITMAP]); |
+ if (bitmap == nullptr) { |
+ return; |
+ } |
+ SkRect dst; |
+ this->getRect(command, SKJSONCANVAS_ATTRIBUTE_DST, &dst); |
+ SkPaint* paintPtr; |
+ SkPaint paint; |
+ if (command.isMember(SKJSONCANVAS_ATTRIBUTE_PAINT)) { |
+ this->getPaint(command, &paint); |
+ paintPtr = &paint; |
+ } |
+ else { |
+ paintPtr = nullptr; |
+ } |
+ SkCanvas::SrcRectConstraint constraint; |
+ if (command.isMember(SKJSONCANVAS_ATTRIBUTE_STRICT) && |
+ command[SKJSONCANVAS_ATTRIBUTE_STRICT].asBool()) { |
+ constraint = SkCanvas::kStrict_SrcRectConstraint; |
+ } |
+ else { |
+ constraint = SkCanvas::kFast_SrcRectConstraint; |
+ } |
+ if (command.isMember(SKJSONCANVAS_ATTRIBUTE_SRC)) { |
+ SkRect src; |
+ this->getRect(command, SKJSONCANVAS_ATTRIBUTE_SRC, &src); |
+ target->drawBitmapRect(*bitmap, src, dst, paintPtr, constraint); |
+ } |
+ else { |
+ target->drawBitmapRect(*bitmap, dst, paintPtr, constraint); |
+ } |
+ free(bitmap); |
+} |
+ |
void render(const char* json, SkCanvas* target) { |
Renderer renderer; |
Json::Reader reader; |