Expose intercepts on SkFont
Already exposed (on TextBlob), so this makes it available for clients that may use drawGlyphs directly. (including canvaskit/flutter) Change-Id: I8b4bd51e13827dc3970d5a6d06f0e0d3031af13c Reviewed-on: https://skia-review.googlesource.com/c/skia/+/408638 Reviewed-by: Julia Lavrova <jlavrova@google.com> Reviewed-by: Herb Derby <herb@google.com> Commit-Queue: Mike Reed <reed@google.com>
This commit is contained in:
parent
c650cc05f8
commit
81e2f9355b
@ -12,6 +12,8 @@
|
||||
#include "include/core/SkScalar.h"
|
||||
#include "include/core/SkTypeface.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class SkMatrix;
|
||||
class SkPaint;
|
||||
class SkPath;
|
||||
@ -432,6 +434,20 @@ public:
|
||||
*/
|
||||
void getXPos(const SkGlyphID glyphs[], int count, SkScalar xpos[], SkScalar origin = 0) const;
|
||||
|
||||
/** Returns intervals [start, end] describing lines parallel to the advance that intersect
|
||||
* with the glyphs.
|
||||
*
|
||||
* @param glyphs the glyphs to intersect
|
||||
* @param count the number of glyphs and positions
|
||||
* @param pos the position of each glyph
|
||||
* @param top the top of the line intersecting
|
||||
* @param bottom the bottom of the line intersecting
|
||||
@return array of pairs of x values [start, end]. May be empty.
|
||||
*/
|
||||
std::vector<SkScalar> getIntercepts(const SkGlyphID glyphs[], int count, const SkPoint pos[],
|
||||
SkScalar top, SkScalar bottom,
|
||||
const SkPaint* = nullptr) const;
|
||||
|
||||
/** Modifies path to be the outline of the glyph.
|
||||
If the glyph has an outline, modifies path to be the glyph's outline and returns true.
|
||||
The glyph outline may be empty. Degenerate contours in the glyph outline will be skipped.
|
||||
|
@ -99,6 +99,12 @@ protected:
|
||||
p2.setColor(0xFFFF0000);
|
||||
p2.setStrokeWidth(4);
|
||||
p2.setStrokeCap(SkPaint::kSquare_Cap);
|
||||
SkPaint underp;
|
||||
underp.setStroke(true);
|
||||
underp.setStrokeWidth(2);
|
||||
underp.setAntiAlias(true);
|
||||
underp.setColor(p.getColor());
|
||||
const SkScalar GAP = 2;
|
||||
|
||||
para->visit([&](int, const skia::textlayout::Paragraph::VisitorInfo* info) {
|
||||
if (!info) {
|
||||
@ -107,6 +113,31 @@ protected:
|
||||
canvas->drawGlyphs(info->count, info->glyphs, info->positions, info->origin,
|
||||
info->font, p);
|
||||
|
||||
if (fFlags & kUseUnderline) {
|
||||
// Need to modify positions to roll-in the orign
|
||||
std::vector<SkPoint> pos;
|
||||
for (int i = 0; i < info->count; ++i) {
|
||||
pos.push_back({info->origin.fX + info->positions[i].fX,
|
||||
info->origin.fY + info->positions[i].fY});
|
||||
}
|
||||
|
||||
const SkScalar X0 = pos[0].fX;
|
||||
const SkScalar X1 = X0 + info->advanceX;
|
||||
const SkScalar Y = pos[0].fY;
|
||||
auto sects = info->font.getIntercepts(info->glyphs, info->count, pos.data(),
|
||||
Y+1, Y+3);
|
||||
|
||||
SkScalar x0 = X0;
|
||||
for (size_t i = 0; i < sects.size(); i += 2) {
|
||||
SkScalar x1 = sects[i] - GAP;
|
||||
if (x0 < x1) {
|
||||
canvas->drawLine(x0, Y+2, x1, Y+2, underp);
|
||||
}
|
||||
x0 = sects[i+1] + GAP;
|
||||
}
|
||||
canvas->drawLine(x0, Y+2, X1, Y+2, underp);
|
||||
}
|
||||
|
||||
if (info->utf8Starts && false) {
|
||||
SkString str;
|
||||
for (int i = 0; i < info->count; ++i) {
|
||||
@ -176,3 +207,4 @@ DEF_GM(return new ParagraphGM(0);)
|
||||
DEF_GM(return new ParagraphGM(kTimeLayout);)
|
||||
DEF_GM(return new ParagraphGM(kUseUnderline);)
|
||||
DEF_GM(return new ParagraphGM(kShowVisitor);)
|
||||
DEF_GM(return new ParagraphGM(kShowVisitor | kUseUnderline);)
|
||||
|
@ -922,7 +922,6 @@ int get_glyph_run_intercepts(const SkGlyphRun& glyphRun,
|
||||
|
||||
int SkTextBlob::getIntercepts(const SkScalar bounds[2], SkScalar intervals[],
|
||||
const SkPaint* paint) const {
|
||||
|
||||
SkTLazy<SkPaint> defaultPaint;
|
||||
if (paint == nullptr) {
|
||||
defaultPaint.init();
|
||||
@ -944,6 +943,28 @@ int SkTextBlob::getIntercepts(const SkScalar bounds[2], SkScalar intervals[],
|
||||
return intervalCount;
|
||||
}
|
||||
|
||||
std::vector<SkScalar> SkFont::getIntercepts(const SkGlyphID glyphs[], int count,
|
||||
const SkPoint positions[],
|
||||
SkScalar top, SkScalar bottom,
|
||||
const SkPaint* paintPtr) const {
|
||||
if (count <= 0) {
|
||||
return std::vector<SkScalar>();
|
||||
}
|
||||
|
||||
const SkPaint paint(paintPtr ? *paintPtr : SkPaint());
|
||||
const SkScalar bounds[] = {top, bottom};
|
||||
const SkGlyphRun run(*this,
|
||||
{positions, size_t(count)}, {glyphs, size_t(count)},
|
||||
{nullptr, 0}, {nullptr, 0}, {nullptr, 0});
|
||||
|
||||
std::vector<SkScalar> result;
|
||||
result.resize(count * 2); // worst case allocation
|
||||
int intervalCount = 0;
|
||||
intervalCount = get_glyph_run_intercepts(run, paint, bounds, result.data(), &intervalCount);
|
||||
result.resize(intervalCount);
|
||||
return result;
|
||||
}
|
||||
|
||||
////////
|
||||
|
||||
SkTextBlob::Iter::Iter(const SkTextBlob& blob) {
|
||||
|
Loading…
Reference in New Issue
Block a user