impl intercepts with fonts
Bug: skia:
Change-Id: Ib3958c61822716846e12647afdfef4ecd979b474
Reviewed-on: https://skia-review.googlesource.com/c/176581
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Mike Reed <reed@google.com>
diff --git a/include/core/SkPaint.h b/include/core/SkPaint.h
index c98e2b0..cd87eb0 100644
--- a/include/core/SkPaint.h
+++ b/include/core/SkPaint.h
@@ -1238,11 +1238,11 @@
SkScalar measure_text(SkGlyphCache*, const char* text, size_t length,
int* count, SkRect* bounds) const;
- int getTextIntercepts(const void* text, size_t length, SkScalar x, SkScalar y,
+ int getTextIntercepts(const SkFont&, const SkGlyphID[], int count, SkScalar x, SkScalar y,
const SkScalar bounds[2], SkScalar* intervals) const;
- int getPosTextIntercepts(const void* text, size_t length, const SkPoint pos[],
+ int getPosTextIntercepts(const SkFont&, const SkGlyphID[], int count, const SkPoint pos[],
const SkScalar bounds[2], SkScalar* intervals) const;
- int getPosTextHIntercepts(const void* text, size_t length, const SkScalar xpos[],
+ int getPosTextHIntercepts(const SkFont&, const SkGlyphID[], int count, const SkScalar xpos[],
SkScalar constY, const SkScalar bounds[2], SkScalar* intervals) const;
/*
diff --git a/src/core/SkPaint_text.cpp b/src/core/SkPaint_text.cpp
index 4f42764..1d45b85 100644
--- a/src/core/SkPaint_text.cpp
+++ b/src/core/SkPaint_text.cpp
@@ -392,16 +392,12 @@
}
template <SkTextInterceptsIter::TextType TextType, typename Func>
-int GetTextIntercepts(const SkPaint& paint, const void* text, size_t length,
- const SkScalar bounds[2], SkScalar* array, Func posMaker) {
- SkASSERT(length == 0 || text != nullptr);
- if (!length) {
- return 0;
- }
+int GetTextIntercepts(const SkFont& font, const SkPaint& paint, const SkGlyphID glyphs[],
+ int glyphCount, const SkScalar bounds[2], SkScalar* array, Func posMaker) {
+ SkASSERT(glyphCount == 0 || glyphs != nullptr);
const SkPoint pos0 = posMaker(0);
- SkTextInterceptsIter iter(static_cast<const char*>(text), length, paint, bounds,
- pos0.x(), pos0.y(), TextType);
+ SkTextInterceptsIter iter(glyphs, glyphCount, font, paint, bounds, pos0.x(), pos0.y(), TextType);
int i = 0;
int count = 0;
@@ -415,31 +411,32 @@
return count;
}
-int SkPaint::getTextIntercepts(const void* textData, size_t length,
+int SkPaint::getTextIntercepts(const SkFont& font, const SkGlyphID glyphs[], int count,
SkScalar x, SkScalar y, const SkScalar bounds[2],
SkScalar* array) const {
return GetTextIntercepts<SkTextInterceptsIter::TextType::kText>(
- *this, textData, length, bounds, array, [&x, &y] (int) -> SkPoint {
+ font, *this, glyphs, count, bounds, array, [&x, &y] (int) -> SkPoint {
return SkPoint::Make(x, y);
});
}
-int SkPaint::getPosTextIntercepts(const void* textData, size_t length, const SkPoint pos[],
- const SkScalar bounds[2], SkScalar* array) const {
+int SkPaint::getPosTextIntercepts(const SkFont& font, const SkGlyphID glyphs[], int count,
+ const SkPoint pos[], const SkScalar bounds[2],
+ SkScalar* array) const {
return GetTextIntercepts<SkTextInterceptsIter::TextType::kPosText>(
- *this, textData, length, bounds, array, [&pos] (int i) -> SkPoint {
+ font, *this, glyphs, count, bounds, array, [&pos] (int i) -> SkPoint {
return pos[i];
});
}
-int SkPaint::getPosTextHIntercepts(const void* textData, size_t length, const SkScalar xpos[],
- SkScalar constY, const SkScalar bounds[2],
+int SkPaint::getPosTextHIntercepts(const SkFont& font, const SkGlyphID glyphs[], int count,
+ const SkScalar xpos[], SkScalar constY, const SkScalar bounds[2],
SkScalar* array) const {
return GetTextIntercepts<SkTextInterceptsIter::TextType::kPosText>(
- *this, textData, length, bounds, array, [&xpos, &constY] (int i) -> SkPoint {
+ font, *this, glyphs, count, bounds, array, [&xpos, &constY] (int i) -> SkPoint {
return SkPoint::Make(xpos[i], constY);
});
}
@@ -447,27 +444,23 @@
int SkPaint::getTextBlobIntercepts(const SkTextBlob* blob, const SkScalar bounds[2],
SkScalar* intervals) const {
int count = 0;
- SkPaint runPaint(*this);
-
SkTextBlobRunIterator it(blob);
+
while (!it.done()) {
- it.applyFontToPaint(&runPaint);
- const size_t runByteCount = it.glyphCount() * sizeof(SkGlyphID);
SkScalar* runIntervals = intervals ? intervals + count : nullptr;
switch (it.positioning()) {
case SkTextBlobRunIterator::kDefault_Positioning:
- count += runPaint.getTextIntercepts(it.glyphs(), runByteCount, it.offset().x(),
- it.offset().y(), bounds, runIntervals);
+ count += this->getTextIntercepts(it.font(), it.glyphs(), it.glyphCount(), it.offset().x(),
+ it.offset().y(), bounds, runIntervals);
break;
case SkTextBlobRunIterator::kHorizontal_Positioning:
- count += runPaint.getPosTextHIntercepts(it.glyphs(), runByteCount, it.pos(),
- it.offset().y(), bounds, runIntervals);
+ count += this->getPosTextHIntercepts(it.font(), it.glyphs(), it.glyphCount(), it.pos(),
+ it.offset().y(), bounds, runIntervals);
break;
case SkTextBlobRunIterator::kFull_Positioning:
- count += runPaint.getPosTextIntercepts(it.glyphs(), runByteCount,
- reinterpret_cast<const SkPoint*>(it.pos()),
- bounds, runIntervals);
+ count += this->getPosTextIntercepts(it.font(), it.glyphs(), it.glyphCount(),
+ reinterpret_cast<const SkPoint*>(it.pos()), bounds, runIntervals);
break;
}
@@ -510,23 +503,19 @@
paint.getStyle() != SkPaint::kFill_Style;
}
-SkTextBaseIter::SkTextBaseIter(const char text[], size_t length,
- const SkPaint& paint,
- bool applyStrokeAndPathEffects)
- : fPaint(paint) {
- fGlyphCacheProc = SkFontPriv::GetGlyphCacheProc(paint.getTextEncoding(), true);
+SkTextBaseIter::SkTextBaseIter(const SkGlyphID glyphs[], int count, const SkFont& font,
+ const SkPaint& paint)
+ : fFont(font), fPaint(paint)
+{
+ SkAssertResult(count >= 0);
- fPaint.setLinearText(true);
+ fFont.setLinearMetrics(true);
fPaint.setMaskFilter(nullptr); // don't want this affecting our path-cache lookup
- if (fPaint.getPathEffect() == nullptr && !has_thick_frame(fPaint)) {
- applyStrokeAndPathEffects = false;
- }
-
// can't use our canonical size if we need to apply patheffects
if (fPaint.getPathEffect() == nullptr) {
- fPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths));
- fScale = paint.getTextSize() / SkPaint::kCanonicalTextSizeForPaths;
+ fScale = fFont.getSize() / SkPaint::kCanonicalTextSizeForPaths;
+ fFont.setSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths));
// Note: fScale can be zero here (even if it wasn't before the divide). It can also
// be very very small. We call sk_ieee_float_divide below to ensure IEEE divide behavior,
// since downstream we will check for the resulting coordinates being non-finite anyway.
@@ -538,24 +527,13 @@
fScale = SK_Scalar1;
}
- if (!applyStrokeAndPathEffects) {
- fPaint.setStyle(SkPaint::kFill_Style);
- fPaint.setPathEffect(nullptr);
- }
+ fPaint.setStyle(SkPaint::kFill_Style);
+ fPaint.setPathEffect(nullptr);
- // SRGBTODO: Is this correct?
- const SkFont font = SkFont::LEGACY_ExtractFromPaint(fPaint);
- fCache = SkStrikeCache::FindOrCreateStrikeWithNoDeviceExclusive(font, fPaint);
+ fCache = SkStrikeCache::FindOrCreateStrikeWithNoDeviceExclusive(fFont, fPaint);
- SkPaint::Style style = SkPaint::kFill_Style;
- sk_sp<SkPathEffect> pe;
-
- if (!applyStrokeAndPathEffects) {
- style = paint.getStyle(); // restore
- pe = paint.refPathEffect(); // restore
- }
- fPaint.setStyle(style);
- fPaint.setPathEffect(pe);
+ fPaint.setStyle(paint.getStyle());
+ fPaint.setPathEffect(paint.refPathEffect());
fPaint.setMaskFilter(paint.refMaskFilter()); // restore
// now compute fXOffset if needed
@@ -564,41 +542,18 @@
fXPos = xOffset;
fPrevAdvance = 0;
- fText = text;
- fStop = text + length;
-}
-
-bool SkTextToPathIter::next(const SkPath** path, SkScalar* xpos) {
- if (fText < fStop) {
- const SkGlyph& glyph = fGlyphCacheProc(fCache.get(), &fText, fStop);
-
- fXPos += fPrevAdvance * fScale;
- fPrevAdvance = advance(glyph); // + fPaint.getTextTracking();
-
- if (glyph.fWidth) {
- if (path) {
- *path = fCache->findPath(glyph);
- }
- } else {
- if (path) {
- *path = nullptr;
- }
- }
- if (xpos) {
- *xpos = fXPos;
- }
- return true;
- }
- return false;
+ fGlyphs = glyphs;
+ fStop = glyphs + count;
}
bool SkTextInterceptsIter::next(SkScalar* array, int* count) {
- const SkGlyph& glyph = fGlyphCacheProc(fCache.get(), &fText, fStop);
+ SkASSERT(fGlyphs < fStop);
+ const SkGlyph& glyph = fCache->getGlyphIDMetrics(*fGlyphs++);
fXPos += fPrevAdvance * fScale;
fPrevAdvance = advance(glyph); // + fPaint.getTextTracking();
if (fCache->findPath(glyph)) {
fCache->findIntercepts(fBounds, fScale, fXPos, false,
const_cast<SkGlyph*>(&glyph), array, count);
}
- return fText < fStop;
+ return fGlyphs < fStop;
}
diff --git a/src/core/SkTextToPathIter.h b/src/core/SkTextToPathIter.h
index 92ddff2..6543543 100644
--- a/src/core/SkTextToPathIter.h
+++ b/src/core/SkTextToPathIter.h
@@ -13,35 +13,23 @@
#include "SkStrikeCache.h"
class SkTextBaseIter {
-protected:
- SkTextBaseIter(const char text[], size_t length, const SkPaint& paint,
- bool applyStrokeAndPathEffects);
-
- SkExclusiveStrikePtr fCache;
- SkPaint fPaint;
- SkScalar fScale;
- SkScalar fPrevAdvance;
- const char* fText;
- const char* fStop;
- SkFontPriv::GlyphCacheProc fGlyphCacheProc;
-
- SkScalar fXPos; // accumulated xpos, returned in next
-};
-
-class SkTextToPathIter : SkTextBaseIter {
public:
- SkTextToPathIter(const char text[], size_t length, const SkPaint& paint,
- bool applyStrokeAndPathEffects)
- : SkTextBaseIter(text, length, paint, applyStrokeAndPathEffects) {
- }
-
+ const SkFont& getFont() const { return fFont; }
const SkPaint& getPaint() const { return fPaint; }
SkScalar getPathScale() const { return fScale; }
- /**
- * Returns false when all of the text has been consumed
- */
- bool next(const SkPath** path, SkScalar* xpos);
+protected:
+ SkTextBaseIter(const SkGlyphID glyphs[], int count, const SkFont&, const SkPaint& paint);
+
+ SkExclusiveStrikePtr fCache;
+ SkFont fFont;
+ SkPaint fPaint;
+ SkScalar fScale;
+ SkScalar fPrevAdvance;
+ const SkGlyphID* fGlyphs;
+ const SkGlyphID* fStop;
+
+ SkScalar fXPos; // accumulated xpos, returned in next
};
class SkTextInterceptsIter : SkTextBaseIter {
@@ -51,9 +39,10 @@
kPosText
};
- SkTextInterceptsIter(const char text[], size_t length, const SkPaint& paint,
- const SkScalar bounds[2], SkScalar x, SkScalar y, TextType textType)
- : SkTextBaseIter(text, length, paint, false)
+ SkTextInterceptsIter(const SkGlyphID glyphs[], int count, const SkFont& font,
+ const SkPaint& paint, const SkScalar bounds[2], SkScalar x, SkScalar y,
+ TextType textType)
+ : SkTextBaseIter(glyphs, count, font, paint)
{
fBoundsBase[0] = bounds[0];
fBoundsBase[1] = bounds[1];