diff options
author | 2016-02-05 09:04:44 -0800 | |
---|---|---|
committer | 2016-02-05 09:04:45 -0800 | |
commit | f6a84bdb477f1430b575d9e5743d055c0c170265 (patch) | |
tree | 260ec0aec4abce33e7d25e052aae27148b942e64 /tools | |
parent | 9c7a8a464894436fc71a15b5419e818905226cdf (diff) |
Added JSON support for TextBlob et al.
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1674643002
Review URL: https://codereview.chromium.org/1674643002
Diffstat (limited to 'tools')
-rw-r--r-- | tools/json/SkJSONCanvas.cpp | 72 | ||||
-rw-r--r-- | tools/json/SkJSONCanvas.h | 6 | ||||
-rw-r--r-- | tools/json/SkJSONRenderer.cpp | 78 |
3 files changed, 155 insertions, 1 deletions
diff --git a/tools/json/SkJSONCanvas.cpp b/tools/json/SkJSONCanvas.cpp index 3a6a2697a8..de7c40cca0 100644 --- a/tools/json/SkJSONCanvas.cpp +++ b/tools/json/SkJSONCanvas.cpp @@ -6,12 +6,16 @@ */ #include "SkJSONCanvas.h" +#include "SkColorFilter.h" #include "SkImageFilter.h" #include "SkMaskFilter.h" #include "SkPaintDefaults.h" #include "SkPath.h" #include "SkPathEffect.h" #include "SkRRect.h" +#include "SkTextBlob.h" +#include "SkTextBlobRunIterator.h" +#include "SkTypeface.h" #include "SkWriteBuffer.h" SkJSONCanvas::SkJSONCanvas(int width, int height, SkWStream& out, bool sendBinaries) @@ -398,6 +402,25 @@ static void apply_paint_textalign(const SkPaint& paint, Json::Value* target) { } } +static void apply_paint_typeface(const SkPaint& paint, Json::Value* target, + bool sendBinaries) { + SkTypeface* typeface = paint.getTypeface(); + if (typeface != nullptr) { + if (sendBinaries) { + Json::Value jsonTypeface; + SkDynamicMemoryWStream buffer; + typeface->serialize(&buffer); + void* data = sk_malloc_throw(buffer.bytesWritten()); + buffer.copyTo(data); + Json::Value bytes; + encode_data(data, buffer.bytesWritten(), &bytes); + jsonTypeface[SKJSONCANVAS_ATTRIBUTE_BYTES] = bytes; + free(data); + (*target)[SKJSONCANVAS_ATTRIBUTE_TYPEFACE] = jsonTypeface; + } + } +} + static void apply_paint_shader(const SkPaint& paint, Json::Value* target, bool sendBinaries) { SkFlattenable* shader = paint.getShader(); if (shader != nullptr) { @@ -425,6 +448,15 @@ static void apply_paint_imagefilter(const SkPaint& paint, Json::Value* target, b } } +static void apply_paint_colorfilter(const SkPaint& paint, Json::Value* target, bool sendBinaries) { + SkFlattenable* colorFilter = paint.getColorFilter(); + if (colorFilter != nullptr) { + Json::Value jsonColorFilter; + flatten(colorFilter, &jsonColorFilter, sendBinaries); + (*target)[SKJSONCANVAS_ATTRIBUTE_COLORFILTER] = jsonColorFilter; + } +} + Json::Value SkJSONCanvas::makePaint(const SkPaint& paint) { Json::Value result(Json::objectValue); store_scalar(&result, SKJSONCANVAS_ATTRIBUTE_STROKEWIDTH, paint.getStrokeWidth(), 0.0f); @@ -444,6 +476,8 @@ Json::Value SkJSONCanvas::makePaint(const SkPaint& paint) { apply_paint_shader(paint, &result, fSendBinaries); apply_paint_xfermode(paint, &result, fSendBinaries); apply_paint_imagefilter(paint, &result, fSendBinaries); + apply_paint_colorfilter(paint, &result, fSendBinaries); + apply_paint_typeface(paint, &result, fSendBinaries); return result; } @@ -756,9 +790,45 @@ void SkJSONCanvas::onDrawTextOnPath(const void* text, size_t byteLength, void SkJSONCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint) { - SkDebugf("unsupported: drawTextBlob\n"); Json::Value command(Json::objectValue); command[SKJSONCANVAS_COMMAND] = Json::Value(SKJSONCANVAS_COMMAND_TEXTBLOB); + Json::Value runs(Json::arrayValue); + SkTextBlobRunIterator iter(blob); + while (!iter.done()) { + Json::Value run(Json::objectValue); + Json::Value jsonPositions(Json::arrayValue); + Json::Value jsonGlyphs(Json::arrayValue); + const SkScalar* iterPositions = iter.pos(); + const uint16_t* iterGlyphs = iter.glyphs(); + for (uint32_t i = 0; i < iter.glyphCount(); i++) { + switch (iter.positioning()) { + case SkTextBlob::kFull_Positioning: + jsonPositions.append(this->makePoint(iterPositions[i * 2], + iterPositions[i * 2 + 1])); + break; + case SkTextBlob::kHorizontal_Positioning: + jsonPositions.append(Json::Value(iterPositions[i])); + break; + case SkTextBlob::kDefault_Positioning: + break; + } + jsonGlyphs.append(Json::Value(iterGlyphs[i])); + } + if (iter.positioning() != SkTextBlob::kDefault_Positioning) { + run[SKJSONCANVAS_ATTRIBUTE_POSITIONS] = jsonPositions; + } + run[SKJSONCANVAS_ATTRIBUTE_GLYPHS] = jsonGlyphs; + SkPaint fontPaint; + iter.applyFontToPaint(&fontPaint); + run[SKJSONCANVAS_ATTRIBUTE_FONT] = this->makePaint(fontPaint); + run[SKJSONCANVAS_ATTRIBUTE_COORDS] = this->makePoint(iter.offset()); + runs.append(run); + iter.next(); + } + command[SKJSONCANVAS_ATTRIBUTE_RUNS] = runs; + command[SKJSONCANVAS_ATTRIBUTE_X] = Json::Value(x); + command[SKJSONCANVAS_ATTRIBUTE_Y] = Json::Value(y); + command[SKJSONCANVAS_ATTRIBUTE_PAINT] = this->makePaint(paint); fCommands.append(command); } diff --git a/tools/json/SkJSONCanvas.h b/tools/json/SkJSONCanvas.h index b43606447b..b0f736f48a 100644 --- a/tools/json/SkJSONCanvas.h +++ b/tools/json/SkJSONCanvas.h @@ -89,6 +89,7 @@ #define SKJSONCANVAS_ATTRIBUTE_MASKFILTER "maskFilter" #define SKJSONCANVAS_ATTRIBUTE_XFERMODE "xfermode" #define SKJSONCANVAS_ATTRIBUTE_BACKDROP "backdrop" +#define SKJSONCANVAS_ATTRIBUTE_COLORFILTER "colorfilter" #define SKJSONCANVAS_ATTRIBUTE_IMAGEFILTER "imagefilter" #define SKJSONCANVAS_ATTRIBUTE_IMAGE "image" #define SKJSONCANVAS_ATTRIBUTE_BITMAP "bitmap" @@ -98,6 +99,11 @@ #define SKJSONCANVAS_ATTRIBUTE_DESCRIPTION "description" #define SKJSONCANVAS_ATTRIBUTE_X "x" #define SKJSONCANVAS_ATTRIBUTE_Y "y" +#define SKJSONCANVAS_ATTRIBUTE_RUNS "runs" +#define SKJSONCANVAS_ATTRIBUTE_POSITIONS "positions" +#define SKJSONCANVAS_ATTRIBUTE_GLYPHS "glyphs" +#define SKJSONCANVAS_ATTRIBUTE_FONT "font" +#define SKJSONCANVAS_ATTRIBUTE_TYPEFACE "typeface" #define SKJSONCANVAS_VERB_MOVE "move" #define SKJSONCANVAS_VERB_LINE "line" diff --git a/tools/json/SkJSONRenderer.cpp b/tools/json/SkJSONRenderer.cpp index a44503af5e..6332b2ae29 100644 --- a/tools/json/SkJSONRenderer.cpp +++ b/tools/json/SkJSONRenderer.cpp @@ -12,6 +12,8 @@ #include "SkJSONCanvas.h" #include "SkJSONCPP.h" #include "SkPath.h" +#include "SkTextBlob.h" +#include "SkTypeface.h" #include "SkValidatingReadBuffer.h" namespace SkJSONRenderer { @@ -60,6 +62,8 @@ public: void processTextOnPath(Json::Value& command, SkCanvas* target); + void processTextBlob(Json::Value& command, SkCanvas* target); + void processPoints(Json::Value& command, SkCanvas* target); void processImage(Json::Value& command, SkCanvas* target); @@ -122,6 +126,9 @@ void Renderer::processCommand(Json::Value& command, SkCanvas* target) { else if (!strcmp(name, SKJSONCANVAS_COMMAND_TEXTONPATH)) { this->processTextOnPath(command, target); } + else if (!strcmp(name, SKJSONCANVAS_COMMAND_TEXTBLOB)) { + this->processTextBlob(command, target); + } else if (!strcmp(name, SKJSONCANVAS_COMMAND_POINTS)) { this->processPoints(command, target); } @@ -304,6 +311,17 @@ static void apply_paint_maskfilter(Json::Value& jsonPaint, SkPaint* target) { } } +static void apply_paint_colorfilter(Json::Value& jsonPaint, SkPaint* target) { + if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_COLORFILTER)) { + Json::Value jsonColorFilter = jsonPaint[SKJSONCANVAS_ATTRIBUTE_COLORFILTER]; + SkColorFilter* colorFilter = (SkColorFilter*) load_flattenable(jsonColorFilter); + if (colorFilter != nullptr) { + target->setColorFilter(colorFilter); + colorFilter->unref(); + } + } +} + static void apply_paint_xfermode(Json::Value& jsonPaint, SkPaint* target) { if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_XFERMODE)) { Json::Value jsonXfermode = jsonPaint[SKJSONCANVAS_ATTRIBUTE_XFERMODE]; @@ -471,11 +489,25 @@ static void apply_paint_textskewx(Json::Value& jsonPaint, SkPaint* target) { } } +static void apply_paint_typeface(Json::Value& jsonPaint, SkPaint* target) { + if (jsonPaint.isMember(SKJSONCANVAS_ATTRIBUTE_TYPEFACE)) { + Json::Value jsonTypeface = jsonPaint[SKJSONCANVAS_ATTRIBUTE_TYPEFACE]; + Json::Value bytes = jsonTypeface[SKJSONCANVAS_ATTRIBUTE_BYTES]; + void* data; + Json::ArrayIndex length = decode_data(bytes, &data); + SkMemoryStream buffer(data, length); + SkTypeface* typeface = SkTypeface::Deserialize(&buffer); + free(data); + target->setTypeface(typeface); + } +} + void Renderer::getPaint(Json::Value& paint, SkPaint* result) { apply_paint_color(paint, result); apply_paint_shader(paint, result); apply_paint_patheffect(paint, result); apply_paint_maskfilter(paint, result); + apply_paint_colorfilter(paint, result); apply_paint_xfermode(paint, result); apply_paint_imagefilter(paint, result); apply_paint_style(paint, result); @@ -489,6 +521,7 @@ void Renderer::getPaint(Json::Value& paint, SkPaint* result) { apply_paint_textsize(paint, result); apply_paint_textscalex(paint, result); apply_paint_textskewx(paint, result); + apply_paint_typeface(paint, result); } void Renderer::getRect(Json::Value& rect, SkRect* result) { @@ -717,6 +750,51 @@ void Renderer::processTextOnPath(Json::Value& command, SkCanvas* target) { target->drawTextOnPath(text, strlen(text), path, matrixPtr, paint); } +void Renderer::processTextBlob(Json::Value& command, SkCanvas* target) { + SkTextBlobBuilder builder; + Json::Value runs = command[SKJSONCANVAS_ATTRIBUTE_RUNS]; + for (Json::ArrayIndex i = 0 ; i < runs.size(); i++) { + Json::Value run = runs[i]; + SkPaint font; + font.setTextEncoding(SkPaint::kGlyphID_TextEncoding); + this->getPaint(run[SKJSONCANVAS_ATTRIBUTE_FONT], &font); + Json::Value glyphs = run[SKJSONCANVAS_ATTRIBUTE_GLYPHS]; + int count = glyphs.size(); + Json::Value coords = run[SKJSONCANVAS_ATTRIBUTE_COORDS]; + SkScalar x = coords[0].asFloat(); + SkScalar y = coords[1].asFloat(); + if (run.isMember(SKJSONCANVAS_ATTRIBUTE_POSITIONS)) { + Json::Value positions = run[SKJSONCANVAS_ATTRIBUTE_POSITIONS]; + if (positions.size() > 0 && positions[0].isNumeric()) { + SkTextBlobBuilder::RunBuffer buffer = builder.allocRunPosH(font, count, y); + for (int j = 0; j < count; j++) { + buffer.glyphs[j] = glyphs[j].asUInt(); + buffer.pos[j] = positions[j].asFloat(); + } + } + else { + SkTextBlobBuilder::RunBuffer buffer = builder.allocRunPos(font, count); + for (int j = 0; j < count; j++) { + buffer.glyphs[j] = glyphs[j].asUInt(); + buffer.pos[j * 2] = positions[j][0].asFloat(); + buffer.pos[j * 2 + 1] = positions[j][1].asFloat(); + } + } + } + else { + SkTextBlobBuilder::RunBuffer buffer = builder.allocRun(font, count, x, y); + for (int j = 0; j < count; j++) { + buffer.glyphs[j] = glyphs[j].asUInt(); + } + } + } + SkScalar x = command[SKJSONCANVAS_ATTRIBUTE_X].asFloat(); + SkScalar y = command[SKJSONCANVAS_ATTRIBUTE_Y].asFloat(); + SkPaint paint; + this->getPaint(command[SKJSONCANVAS_ATTRIBUTE_PAINT], &paint); + target->drawTextBlob(builder.build(), x, y, paint); +} + void Renderer::processPoints(Json::Value& command, SkCanvas* target) { SkCanvas::PointMode mode; const char* jsonMode = command[SKJSONCANVAS_ATTRIBUTE_MODE].asCString(); |