Updates to GlyphRuns[]

1. Fold "origin" into the positions (simplification)
2. Extend positions and offset arrays by 1, to include 1-past last glyph
3. Add flags field to run (with just WS flag for now)

Change-Id: I93e38df808a5e9e4e5bcedbc62bc5a7aa433ef2e
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/399876
Commit-Queue: Mike Reed <reed@google.com>
Reviewed-by: Julia Lavrova <jlavrova@google.com>
Reviewed-by: Yegor Jbanov <yjbanov@google.com>
This commit is contained in:
Mike Reed 2021-04-27 17:46:41 -04:00 committed by Skia Commit-Bot
parent 3386533c20
commit ae33954b49
7 changed files with 44 additions and 48 deletions

View File

@ -51,6 +51,7 @@
#include "include/private/SkShadowFlags.h"
#include "include/utils/SkParsePath.h"
#include "include/utils/SkShadowUtils.h"
#include "modules/skparagraph/include/Paragraph.h"
#include "modules/skshaper/include/SkShaper.h"
#include "src/core/SkFontMgrPriv.h"
#include "src/core/SkImagePriv.h"
@ -2045,4 +2046,6 @@ EMSCRIPTEN_BINDINGS(Skia) {
constant("ShadowTransparentOccluder", (int)SkShadowFlags::kTransparentOccluder_ShadowFlag);
constant("ShadowGeometricOnly", (int)SkShadowFlags::kGeometricOnly_ShadowFlag);
constant("ShadowDirectionalLight", (int)SkShadowFlags::kDirectionalLight_ShadowFlag);
constant("WhiteSpace_GlyphRunFlag", (int)skia::textlayout::Paragraph::kWhiteSpace_VisitorFlag);
}

View File

@ -583,8 +583,8 @@ CanvasKit.onRuntimeInitialized = function() {
};
CanvasKit.Canvas.prototype.drawGlyphs = function(glyphs, positions, x, y, font, paint) {
if (!(glyphs.length*2 == positions.length)) {
throw 'Need glyphs and positions array to agree on the length';
if (!(glyphs.length*2 <= positions.length)) {
throw 'Not enough positions for the array of gyphs';
}
const glyphs_ptr = copy1dArray(glyphs, 'HEAPU16');

View File

@ -258,13 +258,6 @@
canvas.drawLine(wrapTo, 0, wrapTo, 400, fontPaint);
const offset = function(array, dx, dy) {
array[0] += dx;
array[1] += dy;
array[2] += dx;
array[3] += dy;
}
{
const p = new CanvasKit.Paint();
let runs = paragraph.getShapedRuns();
@ -278,17 +271,16 @@
let bounds = [
r.positions[0],
r.positions[1] + fm.ascent,
r.positions[r.positions.length-2] + font.getGlyphWidths(r.glyphs.slice(-1))[0],
r.positions[r.positions.length-2],
r.positions[r.positions.length-1] + fm.descent
];
offset(bounds, r.origin_x, r.origin_y);
canvas.drawRect(bounds, p);
}
p.delete();
fontPaint.setColor(CanvasKit.BLUE);
for (let r of runs) {
canvas.drawGlyphs(r.glyphs, r.positions, r.origin_x, r.origin_y, font, fontPaint);
canvas.drawGlyphs(r.glyphs, r.positions, 0, 0, font, fontPaint);
}
fontPaint.setColor(CanvasKit.BLACK);
}

View File

@ -649,12 +649,23 @@ export interface LineMetrics {
lineNumber: number;
}
readonly WhiteSpace_GlyphRunFlag: number; // the entire run is made up of whitespace(s)
/**
* Information for a run of shaped text. See Paragraph.getShapedRuns()
*
* Notes:
* positions is documented as Float32, but it holds twice as many as you expect, and they
* are treated logically as pairs of floats: {x0, y0}, {x1, y1}, ... for each glyph.
*
* positions and offsets arrays have 1 extra slot (actually 2 for positions)
* to describe the location "after" the last glyph in the glyphs array.
*/
export interface GlyphRun {
glyphs: Uint16Array;
positions: Float32Array; // alternating x0, y0, x1, y1, ...
offsets: Uint32Array;
origin_x: number;
origin_y: number;
flags: number; // see ..._GlyphRunFlag values
}
/**

View File

@ -314,49 +314,34 @@ JSArray GetLineMetrics(para::Paragraph& self) {
/*
* Returns Runs[K]
*
* Run --> { font: ???, glyphs[N], positions[N*2], offsets[N], origin: x,y }
* Run --> { font: ???, glyphs[N], positions[N*2], offsets[N], flags }
*
* K = number of runs
* N = number of glyphs in a given run
*/
JSArray GetShapedRuns(para::Paragraph& self) {
struct Run {
SkFont font;
SkPoint origin;
int index;
int count;
};
std::vector<Run> runs;
std::vector<uint16_t> glyphs;
std::vector<SkPoint> positions;
std::vector<uint32_t> offsets;
self.visit([&](const para::Paragraph::VisitorInfo& info) {
// add 1 Run
runs.push_back({info.font, info.origin, (int)glyphs.size(), info.count});
// append the arrays
glyphs.insert(glyphs.end(), info.glyphs, info.glyphs + info.count);
positions.insert(positions.end(), info.positions, info.positions + info.count);
offsets.insert(offsets.end(), info.utf8Starts, info.utf8Starts + info.count);
});
// where we accumulate our js output
JSArray jruns = emscripten::val::array();
for (const auto& crun : runs) {
const int N = crun.count;
const int I = crun.index;
self.visit([&](const para::Paragraph::VisitorInfo& info) {
const int N = info.count; // glyphs
const int N1 = N + 1; // positions, offsets have 1 extra (trailing) slot
JSObject jrun = emscripten::val::object();
jrun.set("glyphs" , MakeTypedArray(N, &glyphs[I], "Uint16Array"));
jrun.set("positions", MakeTypedArray(N*2, &positions[I].fX, "Float32Array"));
jrun.set("offsets" , MakeTypedArray(N, &offsets[I], "Uint32Array"));
jrun.set("origin_x" , crun.origin.fX);
jrun.set("origin_y" , crun.origin.fY);
jrun.set("flags", info.flags);
jrun.set("glyphs", MakeTypedArray(N, info.glyphs, "Uint16Array"));
jrun.set("offsets", MakeTypedArray(N1, info.utf8Starts, "Uint32Array"));
// we need to modify the positions, so make a temp copy
SkAutoSTMalloc<32, SkPoint> positions(N);
for (int i = 0; i < N; ++i) {
positions.get()[i] = info.positions[i] + info.origin;
}
jrun.set("positions", MakeTypedArray(N1*2, (const float*)positions.get(), "Float32Array"));
jruns.call<void>("push", jrun);
}
});
return jruns;
}

View File

@ -73,13 +73,17 @@ public:
virtual void updateForegroundPaint(size_t from, size_t to, SkPaint paint) = 0;
virtual void updateBackgroundPaint(size_t from, size_t to, SkPaint paint) = 0;
enum VisitorFlags {
kWhiteSpace_VisitorFlag = 1 << 0,
};
struct VisitorInfo {
const SkFont& font;
SkPoint origin;
int count;
const uint16_t* glyphs;
const SkPoint* positions;
const uint32_t* utf8Starts;
const uint16_t* glyphs; // count values
const SkPoint* positions; // count+1 values
const uint32_t* utf8Starts; // count+1 values
unsigned flags;
};
using Visitor = std::function<void(const VisitorInfo&)>;
virtual void visit(const Visitor&) = 0;

View File

@ -1075,6 +1075,7 @@ void ParagraphImpl::visit(const Visitor& visitor) {
run.glyphs,
run.positions,
clusterPtr,
0, // flags
});
clusterPtr += run.count;
}