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/SkScalar.h"
|
||||||
#include "include/core/SkTypeface.h"
|
#include "include/core/SkTypeface.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class SkMatrix;
|
class SkMatrix;
|
||||||
class SkPaint;
|
class SkPaint;
|
||||||
class SkPath;
|
class SkPath;
|
||||||
@ -432,6 +434,20 @@ public:
|
|||||||
*/
|
*/
|
||||||
void getXPos(const SkGlyphID glyphs[], int count, SkScalar xpos[], SkScalar origin = 0) const;
|
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.
|
/** 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.
|
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.
|
The glyph outline may be empty. Degenerate contours in the glyph outline will be skipped.
|
||||||
|
@ -99,6 +99,12 @@ protected:
|
|||||||
p2.setColor(0xFFFF0000);
|
p2.setColor(0xFFFF0000);
|
||||||
p2.setStrokeWidth(4);
|
p2.setStrokeWidth(4);
|
||||||
p2.setStrokeCap(SkPaint::kSquare_Cap);
|
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) {
|
para->visit([&](int, const skia::textlayout::Paragraph::VisitorInfo* info) {
|
||||||
if (!info) {
|
if (!info) {
|
||||||
@ -107,6 +113,31 @@ protected:
|
|||||||
canvas->drawGlyphs(info->count, info->glyphs, info->positions, info->origin,
|
canvas->drawGlyphs(info->count, info->glyphs, info->positions, info->origin,
|
||||||
info->font, p);
|
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) {
|
if (info->utf8Starts && false) {
|
||||||
SkString str;
|
SkString str;
|
||||||
for (int i = 0; i < info->count; ++i) {
|
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(kTimeLayout);)
|
||||||
DEF_GM(return new ParagraphGM(kUseUnderline);)
|
DEF_GM(return new ParagraphGM(kUseUnderline);)
|
||||||
DEF_GM(return new ParagraphGM(kShowVisitor);)
|
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[],
|
int SkTextBlob::getIntercepts(const SkScalar bounds[2], SkScalar intervals[],
|
||||||
const SkPaint* paint) const {
|
const SkPaint* paint) const {
|
||||||
|
|
||||||
SkTLazy<SkPaint> defaultPaint;
|
SkTLazy<SkPaint> defaultPaint;
|
||||||
if (paint == nullptr) {
|
if (paint == nullptr) {
|
||||||
defaultPaint.init();
|
defaultPaint.init();
|
||||||
@ -944,6 +943,28 @@ int SkTextBlob::getIntercepts(const SkScalar bounds[2], SkScalar intervals[],
|
|||||||
return intervalCount;
|
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) {
|
SkTextBlob::Iter::Iter(const SkTextBlob& blob) {
|
||||||
|
Loading…
Reference in New Issue
Block a user