Introduce SkGlyphCacheInterface

Change-Id: I54ee9f5a5a13eff0b7f9a07bb22314d8ea2350a4
Reviewed-on: https://skia-review.googlesource.com/148813
Commit-Queue: Herb Derby <herb@google.com>
Reviewed-by: Mike Klein <mtklein@google.com>
This commit is contained in:
Herb Derby 2018-08-22 17:26:46 -04:00 committed by Skia Commit-Bot
parent 7989dad6c3
commit 4f169ec737
4 changed files with 77 additions and 39 deletions

View File

@ -27,7 +27,9 @@ SkGlyphCache::SkGlyphCache(
const SkPaint::FontMetrics& fontMetrics)
: fDesc{desc}
, fScalerContext{std::move(scaler)}
, fFontMetrics(fontMetrics)
, fFontMetrics{fontMetrics}
, fIsSubpixel{fScalerContext->isSubpixel()}
, fAxisAlignment{fScalerContext->computeAxisAlignmentForHText()}
{
SkASSERT(fScalerContext != nullptr);
fMemoryUsed = sizeof(*this);
@ -282,6 +284,20 @@ void SkGlyphCache::initializeGlyphFromFallback(SkGlyph* glyph, const SkGlyph& fa
fMemoryUsed += glyph->copyImageData(fallback, &fAlloc);
}
SkVector SkGlyphCache::rounding() const {
return SkGlyphCacheCommon::PixelRounding(fIsSubpixel, fAxisAlignment);
}
const SkGlyph& SkGlyphCache::getGlyphMetrics(SkGlyphID glyphID, SkPoint position) {
if (!fIsSubpixel) {
return this->getGlyphIDMetrics(glyphID);
} else {
SkIPoint lookupPosition = SkGlyphCacheCommon::SubpixelLookup(fAxisAlignment, position);
return this->getGlyphIDMetrics(glyphID, lookupPosition.x(), lookupPosition.y());
}
}
#include "../pathops/SkPathOpsCubic.h"
#include "../pathops/SkPathOpsQuad.h"

View File

@ -30,12 +30,12 @@
The Find*Exclusive() method returns SkExclusiveStrikePtr, which releases exclusive ownership
when they go out of scope.
*/
class SkGlyphCache {
class SkGlyphCache : public SkGlyphCacheInterface {
public:
SkGlyphCache(const SkDescriptor& desc,
std::unique_ptr<SkScalerContext> scaler,
const SkPaint::FontMetrics&);
~SkGlyphCache();
~SkGlyphCache() override;
const SkDescriptor& getDescriptor() const;
@ -132,9 +132,13 @@ public:
}
bool isSubpixel() const {
return fScalerContext->isSubpixel();
return fIsSubpixel;
}
SkVector rounding() const override;
const SkGlyph& getGlyphMetrics(SkGlyphID glyphID, SkPoint position) override;
/** Return the approx RAM usage for this cache. */
size_t getMemoryUsed() const { return fMemoryUsed; }
@ -233,6 +237,9 @@ private:
// used to track (approx) how much ram is tied-up in this cache
size_t fMemoryUsed;
const bool fIsSubpixel;
const SkAxisAlignment fAxisAlignment;
};
#endif // SkGlyphCache_DEFINED

View File

@ -140,42 +140,16 @@ SkGlyphRunListPainter::SkGlyphRunListPainter(
SkGlyphRunListPainter::SkGlyphRunListPainter(const GrRenderTargetContext& rtc)
: SkGlyphRunListPainter{rtc.surfaceProps(), rtc.colorSpaceInfo()} {}
// TODO: all this logic should move to the glyph cache.
static const SkGlyph& lookup_glyph_by_subpixel(
SkAxisAlignment axisAlignment, SkPoint position, SkGlyphID glyphID, SkGlyphCache* cache) {
SkFixed lookupX = SkScalarToFixed(SkScalarFraction(position.x())),
lookupY = SkScalarToFixed(SkScalarFraction(position.y()));
// Snap to a given axis if alignment is requested.
if (axisAlignment == kX_SkAxisAlignment) {
lookupY = 0;
} else if (axisAlignment == kY_SkAxisAlignment) {
lookupX = 0;
}
return cache->getGlyphIDMetrics(glyphID, lookupX, lookupY);
}
// forEachMappedDrawableGlyph handles positioning for mask type glyph handling for both sub-pixel
// and full pixel positioning.
template <typename EachGlyph>
void SkGlyphRunListPainter::forEachMappedDrawableGlyph(
const SkGlyphRun& glyphRun, SkPoint origin, const SkMatrix& deviceMatrix,
SkGlyphCache* cache, EachGlyph eachGlyph) {
bool isSubpixel = cache->isSubpixel();
SkAxisAlignment axisAlignment = kNone_SkAxisAlignment;
SkGlyphCacheInterface* cache, EachGlyph eachGlyph) {
SkMatrix mapping = deviceMatrix;
mapping.preTranslate(origin.x(), origin.y());
// TODO: all this logic should move to the glyph cache.
if (isSubpixel) {
axisAlignment = cache->getScalerContext()->computeAxisAlignmentForHText();
SkPoint rounding = SkFindAndPlaceGlyph::SubpixelPositionRounding(axisAlignment);
mapping.postTranslate(rounding.x(), rounding.y());
} else {
mapping.postTranslate(SK_ScalarHalf, SK_ScalarHalf);
}
SkVector rounding = cache->rounding();
mapping.postTranslate(rounding.x(), rounding.y());
auto runSize = glyphRun.runSize();
if (this->ensureBitmapBuffers(runSize)) {
@ -186,10 +160,7 @@ void SkGlyphRunListPainter::forEachMappedDrawableGlyph(
auto mappedPt = *mappedPtCursor++;
auto pt = origin + *ptCursor++;
if (SkScalarsAreFinite(mappedPt.x(), mappedPt.y())) {
// TODO: all this logic should move to the glyph cache.
const SkGlyph& glyph =
isSubpixel ? lookup_glyph_by_subpixel(axisAlignment, mappedPt, glyphID, cache)
: cache->getGlyphIDMetrics(glyphID);
const SkGlyph& glyph = cache->getGlyphMetrics(glyphID, mappedPt);
if (!glyph.isEmpty()) {
// Prevent glyphs from being drawn outside of or straddling the edge
// of device space. Comparisons written a little weirdly so that NaN
@ -357,7 +328,6 @@ void SkGlyphRunListPainter::drawGlyphRunAsFullpixelMask(
}
}
void SkGlyphRunListPainter::drawForBitmapDevice(
const SkGlyphRunList& glyphRunList, const SkMatrix& deviceMatrix,
PerMaskCreator perMaskCreator, PerPathCreator perPathCreator) {

View File

@ -30,6 +30,51 @@ class SkBaseDevice;
class SkGlyphRunList;
class SkRasterClip;
class SkGlyphCacheInterface {
public:
virtual ~SkGlyphCacheInterface() = default;
virtual SkVector rounding() const = 0;
virtual const SkGlyph& getGlyphMetrics(SkGlyphID glyphID, SkPoint position) = 0;
};
class SkGlyphCacheCommon {
public:
static SkVector PixelRounding(bool isSubpixel, SkAxisAlignment axisAlignment) {
if (!isSubpixel) {
return {SK_ScalarHalf, SK_ScalarHalf};
} else {
static constexpr SkScalar kSubpixelRounding = SkFixedToScalar(SkGlyph::kSubpixelRound);
switch (axisAlignment) {
case kX_SkAxisAlignment:
return {kSubpixelRounding, SK_ScalarHalf};
case kY_SkAxisAlignment:
return {SK_ScalarHalf, kSubpixelRounding};
case kNone_SkAxisAlignment:
return {kSubpixelRounding, kSubpixelRounding};
}
}
// Some compilers need this.
return {0, 0};
}
// This assumes that position has the appropriate rounding term applied.
static SkIPoint SubpixelLookup(SkAxisAlignment axisAlignment, SkPoint position) {
// TODO: SkScalarFraction uses truncf to calculate the fraction. This should be floorf.
SkFixed lookupX = SkScalarToFixed(SkScalarFraction(position.x())),
lookupY = SkScalarToFixed(SkScalarFraction(position.y()));
// Snap to a given axis if alignment is requested.
if (axisAlignment == kX_SkAxisAlignment) {
lookupY = 0;
} else if (axisAlignment == kY_SkAxisAlignment) {
lookupX = 0;
}
return {lookupX, lookupY};
}
};
class SkGlyphRun {
public:
SkGlyphRun() = default;
@ -128,7 +173,7 @@ private:
template <typename EachGlyph>
void forEachMappedDrawableGlyph(
const SkGlyphRun& glyphRun, SkPoint origin, const SkMatrix& deviceMatrix,
SkGlyphCache* cache, EachGlyph eachGlyph);
SkGlyphCacheInterface* cache, EachGlyph eachGlyph);
void drawGlyphRunAsSubpixelMask(
SkGlyphCache* cache, const SkGlyphRun& glyphRun,