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
This commit is contained in:
parent
9c7a8a4648
commit
f6a84bdb47
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user