Convert GrGlyph::PackedID to SkPackedGlyphID

This changes ripples through many areas of the code like the
hash map.

This will simplify making SkGlyphCache and GrTextStrike work
together in future CLs.

* Convert ctor to take an SkGlyph
* Remove many unused functions

Change-Id: I43ea414f03dfbb683ba7b46bf48a93c7a78895c6
Reviewed-on: https://skia-review.googlesource.com/c/179641
Commit-Queue: Herb Derby <herb@google.com>
Reviewed-by: Jim Van Verth <jvanverth@google.com>
This commit is contained in:
Herb Derby 2018-12-20 14:47:03 -05:00 committed by Skia Commit-Bot
parent edce0aa152
commit 5a3fdeecdc
4 changed files with 53 additions and 107 deletions

View File

@ -16,34 +16,52 @@
#include "SkFixed.h"
#include "SkPath.h"
/* Need this to be quad-state:
- complete w/ image
- just metrics
- failed to get image, but has metrics
- failed to get metrics
*/
struct GrGlyph {
enum MaskStyle {
kCoverage_MaskStyle,
kDistance_MaskStyle
};
typedef uint32_t PackedID;
static GrIRect16 SkIRectToGrIRect16(const SkIRect& rect) {
return GrIRect16::MakeXYWH(SkTo<int16_t>(rect.x()),
SkTo<int16_t>(rect.y()),
SkTo<uint16_t>(rect.width()),
SkTo<uint16_t>(rect.height()));
static GrMaskFormat FormatFromSkGlyph(const SkGlyph& glyph) {
SkMask::Format format = static_cast<SkMask::Format>(glyph.fMaskFormat);
switch (format) {
case SkMask::kBW_Format:
case SkMask::kSDF_Format:
// fall through to kA8 -- we store BW and SDF glyphs in our 8-bit cache
case SkMask::kA8_Format:
return kA8_GrMaskFormat;
case SkMask::k3D_Format:
return kA8_GrMaskFormat; // ignore the mul and add planes, just use the mask
case SkMask::kLCD16_Format:
return kA565_GrMaskFormat;
case SkMask::kARGB32_Format:
return kARGB_GrMaskFormat;
default:
SkDEBUGFAIL("unsupported SkMask::Format");
return kA8_GrMaskFormat;
}
}
GrGlyph(GrGlyph::PackedID packed, const SkIRect& bounds, GrMaskFormat format, MaskStyle style)
: fPackedID{packed}
, fMaskFormat{format}
, fMaskStyle{style}
, fBounds{SkIRectToGrIRect16(bounds)} {}
static GrIRect16 BoundsFromSkGlyph(const SkGlyph& glyph) {
return GrIRect16::MakeXYWH(glyph.fLeft,
glyph.fTop,
glyph.fWidth,
glyph.fHeight);
}
const PackedID fPackedID;
static MaskStyle MaskStyleFromSkGlyph(const SkGlyph& skGlyph) {
return (SkMask::Format)skGlyph.fMaskFormat == SkMask::kSDF_Format
? GrGlyph::MaskStyle::kDistance_MaskStyle
: GrGlyph::MaskStyle::kCoverage_MaskStyle;
}
GrGlyph(const SkGlyph& skGlyph)
: fPackedID{skGlyph.getPackedID()}
, fMaskFormat{FormatFromSkGlyph(skGlyph)}
, fMaskStyle{MaskStyleFromSkGlyph(skGlyph)}
, fBounds{BoundsFromSkGlyph(skGlyph)} {}
const SkPackedGlyphID fPackedID;
const GrMaskFormat fMaskFormat;
const MaskStyle fMaskStyle;
const GrIRect16 fBounds;
@ -52,55 +70,16 @@ struct GrGlyph {
int width() const { return fBounds.width(); }
int height() const { return fBounds.height(); }
bool isEmpty() const { return fBounds.isEmpty(); }
uint16_t glyphID() const { return UnpackID(fPackedID); }
uint32_t pageIndex() const { return GrDrawOpAtlas::GetPageIndexFromID(fID); }
MaskStyle maskStyle() const { return fMaskStyle; }
///////////////////////////////////////////////////////////////////////////
static unsigned ExtractSubPixelBitsFromFixed(SkFixed pos) {
// two most significant fraction bits from fixed-point
return (pos >> 14) & 3;
}
static PackedID FromSkGlyph(const SkGlyph& skGlyph) {
GrGlyph::MaskStyle maskStyle = (SkMask::Format)skGlyph.fMaskFormat == SkMask::kSDF_Format
? GrGlyph::MaskStyle::kDistance_MaskStyle
: GrGlyph::MaskStyle::kCoverage_MaskStyle;
SkPackedGlyphID skPackedID = skGlyph.getPackedID();
GrGlyph::PackedID packedID = GrGlyph::Pack(skPackedID.code(),
skPackedID.getSubXFixed(),
skPackedID.getSubYFixed(),
maskStyle);
return packedID;
}
static PackedID Pack(uint16_t glyphID, SkFixed x, SkFixed y, MaskStyle ms) {
x = ExtractSubPixelBitsFromFixed(x);
y = ExtractSubPixelBitsFromFixed(y);
int dfFlag = (ms == kDistance_MaskStyle) ? 0x1 : 0x0;
return (dfFlag << 20) | (x << 18) | (y << 16) | glyphID;
}
static SkFixed UnpackFixedX(PackedID packed) {
return ((packed >> 18) & 3) << 14;
}
static SkFixed UnpackFixedY(PackedID packed) {
return ((packed >> 16) & 3) << 14;
}
static uint16_t UnpackID(PackedID packed) {
return (uint16_t)packed;
}
static const GrGlyph::PackedID& GetKey(const GrGlyph& glyph) {
// GetKey and Hash for the the hash table.
static const SkPackedGlyphID& GetKey(const GrGlyph& glyph) {
return glyph.fPackedID;
}
static uint32_t Hash(GrGlyph::PackedID key) {
return SkChecksum::Mix(key);
static uint32_t Hash(SkPackedGlyphID key) {
return SkChecksum::Mix(key.hash());
}
};

View File

@ -56,26 +56,6 @@ void GrGlyphCache::HandleEviction(GrDrawOpAtlas::AtlasID id, void* ptr) {
}
}
static GrMaskFormat get_packed_glyph_mask_format(const SkGlyph& glyph) {
SkMask::Format format = static_cast<SkMask::Format>(glyph.fMaskFormat);
switch (format) {
case SkMask::kBW_Format:
case SkMask::kSDF_Format:
// fall through to kA8 -- we store BW and SDF glyphs in our 8-bit cache
case SkMask::kA8_Format:
return kA8_GrMaskFormat;
case SkMask::k3D_Format:
return kA8_GrMaskFormat; // ignore the mul and add planes, just use the mask
case SkMask::kLCD16_Format:
return kA565_GrMaskFormat;
case SkMask::kARGB32_Format:
return kARGB_GrMaskFormat;
default:
SkDEBUGFAIL("unsupported SkMask::Format");
return kA8_GrMaskFormat;
}
}
// expands each bit in a bitmask to 0 or ~0 of type INT_TYPE. Used to expand a BW glyph mask to
// A8, RGB565, or RGBA8888.
template <typename INT_TYPE>
@ -113,7 +93,7 @@ static bool get_packed_glyph_image(SkGlyphCache* cache, const SkGlyph& glyph, in
// Convert if the glyph uses a 565 mask format since it is using LCD text rendering but the
// expected format is 8888 (will happen on macOS with Metal since that combination does not
// support 565).
if (kA565_GrMaskFormat == get_packed_glyph_mask_format(glyph) &&
if (kA565_GrMaskFormat == GrGlyph::FormatFromSkGlyph(glyph) &&
kARGB_GrMaskFormat == expectedMaskFormat) {
const int a565Bpp = GrMaskFormatBytesPerPixel(kA565_GrMaskFormat);
const int argbBpp = GrMaskFormatBytesPerPixel(kARGB_GrMaskFormat);
@ -136,7 +116,7 @@ static bool get_packed_glyph_image(SkGlyphCache* cache, const SkGlyph& glyph, in
// crbug:510931
// Retrieving the image from the cache can actually change the mask format. This case is very
// uncommon so for now we just draw a clear box for these glyphs.
if (get_packed_glyph_mask_format(glyph) != expectedMaskFormat) {
if (GrGlyph::FormatFromSkGlyph(glyph) != expectedMaskFormat) {
const int bpp = GrMaskFormatBytesPerPixel(expectedMaskFormat);
for (int y = 0; y < height; y++) {
sk_bzero(dst, width * bpp);
@ -193,23 +173,13 @@ GrTextStrike::GrTextStrike(const SkDescriptor& key)
: fFontScalerKey(key) {}
GrGlyph* GrTextStrike::generateGlyph(const SkGlyph& skGlyph) {
SkIRect bounds;
bounds.setXYWH(skGlyph.fLeft, skGlyph.fTop, skGlyph.fWidth, skGlyph.fHeight);
GrMaskFormat format = get_packed_glyph_mask_format(skGlyph);
GrGlyph::MaskStyle maskStyle = (SkMask::Format)skGlyph.fMaskFormat == SkMask::kSDF_Format
? GrGlyph::MaskStyle::kDistance_MaskStyle
: GrGlyph::MaskStyle::kCoverage_MaskStyle;
GrGlyph* glyph = fAlloc.make<GrGlyph>(
GrGlyph::FromSkGlyph(skGlyph), bounds, format, maskStyle);
fCache.add(glyph);
return glyph;
GrGlyph* grGlyph = fAlloc.make<GrGlyph>(skGlyph);
fCache.add(grGlyph);
return grGlyph;
}
void GrTextStrike::removeID(GrDrawOpAtlas::AtlasID id) {
SkTDynamicHash<GrGlyph, GrGlyph::PackedID>::Iter iter(&fCache);
SkTDynamicHash<GrGlyph, SkPackedGlyphID>::Iter iter(&fCache);
while (!iter.done()) {
if (id == (*iter).fID) {
(*iter).fID = GrDrawOpAtlas::kInvalidAtlasID;

View File

@ -31,8 +31,7 @@ public:
GrTextStrike(const SkDescriptor& fontScalerKey);
GrGlyph* getGlyph(const SkGlyph& skGlyph) {
GrGlyph::PackedID packed = GrGlyph::FromSkGlyph(skGlyph);
GrGlyph* glyph = fCache.find(packed);
GrGlyph* glyph = fCache.find(skGlyph.getPackedID());
if (!glyph) {
glyph = this->generateGlyph(skGlyph);
}
@ -43,7 +42,7 @@ public:
// that the maskformat of the glyph differs from what we expect. In these cases we will just
// draw a clear square.
// skbug:4143 crbug:510931
GrGlyph* getGlyph(GrGlyph::PackedID packed,
GrGlyph* getGlyph(SkPackedGlyphID packed,
SkGlyphCache* cache) {
GrGlyph* glyph = fCache.find(packed);
if (!glyph) {
@ -82,17 +81,15 @@ public:
static uint32_t Hash(const SkDescriptor& desc) { return desc.getChecksum(); }
private:
SkTDynamicHash<GrGlyph, GrGlyph::PackedID> fCache;
SkTDynamicHash<GrGlyph, SkPackedGlyphID> fCache;
SkAutoDescriptor fFontScalerKey;
SkArenaAlloc fAlloc{512};
int fAtlasedGlyphs{0};
bool fIsAbandoned{false};
static const SkGlyph& GrToSkGlyph(SkGlyphCache* cache, GrGlyph::PackedID id) {
return cache->getGlyphIDMetrics(GrGlyph::UnpackID(id),
GrGlyph::UnpackFixedX(id),
GrGlyph::UnpackFixedY(id));
static const SkGlyph& GrToSkGlyph(SkGlyphCache* cache, SkPackedGlyphID id) {
return cache->getGlyphIDMetrics(id.code(), id.getSubXFixed(), id.getSubYFixed());
}
GrGlyph* generateGlyph(const SkGlyph&);

View File

@ -269,7 +269,7 @@ bool GrTextBlob::VertexRegenerator::doRegen(GrTextBlob::VertexRegenerator::Resul
if (regenGlyphs) {
// Get the id from the old glyph, and use the new strike to lookup
// the glyph.
GrGlyph::PackedID id = fBlob->fGlyphs[glyphOffset]->fPackedID;
SkPackedGlyphID id = fBlob->fGlyphs[glyphOffset]->fPackedID;
fBlob->fGlyphs[glyphOffset] = strike->getGlyph(id, fLazyCache->get());
SkASSERT(id == fBlob->fGlyphs[glyphOffset]->fPackedID);
}