Force single glyph calls through bulk interface
Enance SkBulkGlyphMetrics, SkBulkGlyphMetricsAndPaths, and SkBulkGlyphMetricsAndImages with single glyph calls. In addtion, add calls needed to have the rest of the system work with these interfaces. As a resulte move the glyph, prepareImage, and preparePath calls to private. Change-Id: I8d383b649390e45f621dcb9d62fb8367a55cee02 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/254056 Reviewed-by: Ben Wagner <bungeman@google.com> Commit-Queue: Herb Derby <herb@google.com>
This commit is contained in:
parent
a9b348f66c
commit
cb443a5928
@ -218,7 +218,6 @@ void GrAtlasTextOp::finalizeForTextTarget(uint32_t color, const GrCaps& caps) {
|
||||
|
||||
void GrAtlasTextOp::executeForTextTarget(SkAtlasTextTarget* target) {
|
||||
FlushInfo flushInfo;
|
||||
SkExclusiveStrikePtr autoGlyphCache;
|
||||
auto& context = target->context()->internal();
|
||||
auto glyphCache = context.grContext()->priv().getGrStrikeCache();
|
||||
auto atlasManager = context.grContext()->priv().getAtlasManager();
|
||||
@ -234,8 +233,7 @@ void GrAtlasTextOp::executeForTextTarget(SkAtlasTextTarget* target) {
|
||||
GrTextBlob::VertexRegenerator regenerator(
|
||||
resourceProvider, fGeoData[i].fBlob, fGeoData[i].fRun, fGeoData[i].fSubRun,
|
||||
fGeoData[i].fViewMatrix, fGeoData[i].fX, fGeoData[i].fY,
|
||||
fGeoData[i].fColor.toBytes_RGBA(), &context, glyphCache, atlasManager,
|
||||
&autoGlyphCache);
|
||||
fGeoData[i].fColor.toBytes_RGBA(), &context, glyphCache, atlasManager);
|
||||
bool done = false;
|
||||
while (!done) {
|
||||
GrTextBlob::VertexRegenerator::Result result;
|
||||
|
@ -39,27 +39,18 @@ public:
|
||||
std::unique_ptr<SkScalerContext> scaler,
|
||||
const SkFontMetrics&);
|
||||
|
||||
// Return a glyph. Create it if it doesn't exist, and initialize the glyph with metrics and
|
||||
// advances using a scaler.
|
||||
SkGlyph* glyph(SkPackedGlyphID packedID);
|
||||
|
||||
// Return a glyph. Create it if it doesn't exist, and initialize with the prototype.
|
||||
SkGlyph* glyphFromPrototype(const SkGlyphPrototype& p, void* image = nullptr);
|
||||
|
||||
// Return a glyph or nullptr if it does not exits in the strike.
|
||||
SkGlyph* glyphOrNull(SkPackedGlyphID id) const;
|
||||
|
||||
const void* prepareImage(SkGlyph* glyph);
|
||||
|
||||
// Lookup (or create if needed) the toGlyph using toID. If that glyph is not initialized with
|
||||
// an image, then use the information in from to initialize the width, height top, left,
|
||||
// format and image of the toGlyph. This is mainly used preserving the glyph if it was
|
||||
// created by a search of desperation.
|
||||
SkGlyph* mergeGlyphAndImage(SkPackedGlyphID toID, const SkGlyph& from);
|
||||
|
||||
// If the path has never been set, then use the scaler context to add the glyph.
|
||||
const SkPath* preparePath(SkGlyph*);
|
||||
|
||||
// If the path has never been set, then add a path to glyph.
|
||||
const SkPath* preparePath(SkGlyph* glyph, const SkPath* path);
|
||||
|
||||
@ -163,11 +154,19 @@ private:
|
||||
template <typename Fn>
|
||||
void commonFilterLoop(SkDrawableGlyphBuffer* drawables, Fn&& fn);
|
||||
|
||||
// Return a glyph. Create it if it doesn't exist, and initialize the glyph with metrics and
|
||||
// advances using a scaler.
|
||||
SkGlyph* glyph(SkPackedGlyphID packedID);
|
||||
|
||||
const void* prepareImage(SkGlyph* glyph);
|
||||
|
||||
// If the path has never been set, then use the scaler context to add the glyph.
|
||||
const SkPath* preparePath(SkGlyph*);
|
||||
|
||||
enum PathDetail {
|
||||
kMetricsOnly,
|
||||
kMetricsAndPath
|
||||
};
|
||||
|
||||
// internalPrepare will only be called with a mutex already held.
|
||||
SkSpan<const SkGlyph*> internalPrepare(
|
||||
SkSpan<const SkGlyphID> glyphIDs,
|
||||
|
@ -13,6 +13,11 @@
|
||||
#include "src/core/SkStrikeCache.h"
|
||||
#include "src/core/SkTLazy.h"
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
#include "src/gpu/text/GrStrikeCache.h"
|
||||
#include "src/gpu/text/GrTextContext.h"
|
||||
#endif
|
||||
|
||||
SkStrikeSpec SkStrikeSpec::MakeMask(const SkFont& font, const SkPaint& paint,
|
||||
const SkSurfaceProps& surfaceProps,
|
||||
SkScalerContextFlags scalerContextFlags,
|
||||
@ -239,18 +244,48 @@ SkSpan<const SkGlyph*> SkBulkGlyphMetrics::glyphs(SkSpan<const SkGlyphID> glyphI
|
||||
return fStrike->metrics(glyphIDs, fGlyphs.get());
|
||||
}
|
||||
|
||||
const SkGlyph* SkBulkGlyphMetrics::glyph(SkGlyphID glyphID) {
|
||||
return this->glyphs(SkSpan<const SkGlyphID>{&glyphID, 1})[0];
|
||||
}
|
||||
|
||||
SkBulkGlyphMetricsAndPaths::SkBulkGlyphMetricsAndPaths(const SkStrikeSpec& spec)
|
||||
: fStrike{spec.findOrCreateExclusiveStrike()} { }
|
||||
|
||||
SkBulkGlyphMetricsAndPaths::SkBulkGlyphMetricsAndPaths(SkExclusiveStrikePtr&& strike)
|
||||
: fStrike{std::move(strike)} { }
|
||||
|
||||
SkSpan<const SkGlyph*> SkBulkGlyphMetricsAndPaths::glyphs(SkSpan<const SkGlyphID> glyphIDs) {
|
||||
fGlyphs.reset(glyphIDs.size());
|
||||
return fStrike->preparePaths(glyphIDs, fGlyphs.get());
|
||||
}
|
||||
|
||||
const SkGlyph* SkBulkGlyphMetricsAndPaths::glyph(SkGlyphID glyphID) {
|
||||
return this->glyphs(SkSpan<const SkGlyphID>{&glyphID, 1})[0];
|
||||
}
|
||||
|
||||
void SkBulkGlyphMetricsAndPaths::findIntercepts(
|
||||
const SkScalar* bounds, SkScalar scale, SkScalar xPos,
|
||||
const SkGlyph* glyph, SkScalar* array, int* count) {
|
||||
// TODO(herb): remove this abominable const_cast. Do the intercepts really need to be on the
|
||||
// glyph?
|
||||
fStrike->findIntercepts(bounds, scale, xPos, const_cast<SkGlyph*>(glyph), array, count);
|
||||
}
|
||||
|
||||
SkBulkGlyphMetricsAndImages::SkBulkGlyphMetricsAndImages(const SkStrikeSpec& spec)
|
||||
: fStrike{spec.findOrCreateExclusiveStrike()} { }
|
||||
|
||||
SkBulkGlyphMetricsAndImages::SkBulkGlyphMetricsAndImages(SkExclusiveStrikePtr&& strike)
|
||||
: fStrike{std::move(strike)} { }
|
||||
|
||||
SkSpan<const SkGlyph*> SkBulkGlyphMetricsAndImages::glyphs(SkSpan<const SkPackedGlyphID> glyphIDs) {
|
||||
fGlyphs.reset(glyphIDs.size());
|
||||
return fStrike->prepareImages(glyphIDs, fGlyphs.get());
|
||||
}
|
||||
|
||||
const SkGlyph* SkBulkGlyphMetricsAndImages::glyph(SkPackedGlyphID packedID) {
|
||||
return this->glyphs(SkSpan<const SkPackedGlyphID>{&packedID, 1})[0];
|
||||
}
|
||||
|
||||
const SkDescriptor& SkBulkGlyphMetricsAndImages::descriptor() const {
|
||||
return fStrike->getDescriptor();
|
||||
}
|
||||
|
@ -13,8 +13,9 @@
|
||||
#include "src/core/SkStrikeForGPU.h"
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
#include "src/gpu/text/GrStrikeCache.h"
|
||||
#include "src/gpu/text/GrTextContext.h"
|
||||
class GrStrikeCache;
|
||||
class GrTextStrike;
|
||||
#endif
|
||||
|
||||
class SkFont;
|
||||
@ -40,10 +41,10 @@ public:
|
||||
SkScalerContextFlags scalerContextFlags);
|
||||
|
||||
static SkStrikeSpec MakeSourceFallback(const SkFont& font,
|
||||
const SkPaint& paint,
|
||||
const SkSurfaceProps& surfaceProps,
|
||||
SkScalerContextFlags scalerContextFlags,
|
||||
SkScalar maxSourceGlyphDimension);
|
||||
const SkPaint& paint,
|
||||
const SkSurfaceProps& surfaceProps,
|
||||
SkScalerContextFlags scalerContextFlags,
|
||||
SkScalar maxSourceGlyphDimension);
|
||||
|
||||
// Create a canonical strike spec for device-less measurements.
|
||||
static SkStrikeSpec MakeCanonicalized(
|
||||
@ -99,6 +100,7 @@ class SkBulkGlyphMetrics {
|
||||
public:
|
||||
explicit SkBulkGlyphMetrics(const SkStrikeSpec& spec);
|
||||
SkSpan<const SkGlyph*> glyphs(SkSpan<const SkGlyphID> glyphIDs);
|
||||
const SkGlyph* glyph(SkGlyphID glyphID);
|
||||
|
||||
private:
|
||||
static constexpr int kTypicalGlyphCount = 20;
|
||||
@ -109,7 +111,11 @@ private:
|
||||
class SkBulkGlyphMetricsAndPaths {
|
||||
public:
|
||||
explicit SkBulkGlyphMetricsAndPaths(const SkStrikeSpec& spec);
|
||||
explicit SkBulkGlyphMetricsAndPaths(SkExclusiveStrikePtr&& strike);
|
||||
SkSpan<const SkGlyph*> glyphs(SkSpan<const SkGlyphID> glyphIDs);
|
||||
const SkGlyph* glyph(SkGlyphID glyphID);
|
||||
void findIntercepts(const SkScalar bounds[2], SkScalar scale, SkScalar xPos,
|
||||
const SkGlyph* glyph, SkScalar* array, int* count);
|
||||
|
||||
private:
|
||||
static constexpr int kTypicalGlyphCount = 20;
|
||||
@ -120,7 +126,11 @@ private:
|
||||
class SkBulkGlyphMetricsAndImages {
|
||||
public:
|
||||
explicit SkBulkGlyphMetricsAndImages(const SkStrikeSpec& spec);
|
||||
SkSpan<const SkGlyph*> glyphs(SkSpan<const SkPackedGlyphID> glyphIDs);
|
||||
explicit SkBulkGlyphMetricsAndImages(SkExclusiveStrikePtr&& strike);
|
||||
SkSpan<const SkGlyph*> glyphs(SkSpan<const SkPackedGlyphID> packedIDs);
|
||||
const SkGlyph* glyph(SkPackedGlyphID packedID);
|
||||
const SkDescriptor& descriptor() const;
|
||||
|
||||
|
||||
private:
|
||||
static constexpr int kTypicalGlyphCount = 64;
|
||||
|
@ -875,27 +875,27 @@ int get_glyph_run_intercepts(const SkGlyphRun& glyphRun,
|
||||
interceptPaint.setPathEffect(nullptr);
|
||||
|
||||
SkStrikeSpec strikeSpec = SkStrikeSpec::MakeWithNoDevice(interceptFont, &interceptPaint);
|
||||
auto cache = strikeSpec.findOrCreateExclusiveStrike();
|
||||
SkBulkGlyphMetricsAndPaths metricsAndPaths{strikeSpec};
|
||||
|
||||
SkScalar xOffset = 0;
|
||||
SkScalar xPos = xOffset;
|
||||
SkScalar prevAdvance = 0;
|
||||
|
||||
const SkPoint* posCursor = glyphRun.positions().begin();
|
||||
for (auto glyphID : glyphRun.glyphsIDs()) {
|
||||
for (const SkGlyph* glyph : metricsAndPaths.glyphs(glyphRun.glyphsIDs())) {
|
||||
SkPoint pos = *posCursor++;
|
||||
|
||||
SkGlyph* glyph = cache->glyph(SkPackedGlyphID{glyphID});
|
||||
xPos += prevAdvance * scale;
|
||||
prevAdvance = glyph->advanceX();
|
||||
if (cache->preparePath(glyph) != nullptr) {
|
||||
if (glyph->path() != nullptr) {
|
||||
// The typeface is scaled, so un-scale the bounds to be in the space of the typeface.
|
||||
// Also ensure the bounds are properly offset by the vertical positioning of the glyph.
|
||||
SkScalar scaledBounds[2] = {
|
||||
(bounds[0] - pos.y()) / scale,
|
||||
(bounds[1] - pos.y()) / scale
|
||||
};
|
||||
cache->findIntercepts(scaledBounds, scale, pos.x(), glyph, intervals, intervalCount);
|
||||
metricsAndPaths.findIntercepts(
|
||||
scaledBounds, scale, pos.x(), glyph, intervals, intervalCount);
|
||||
}
|
||||
}
|
||||
return *intervalCount;
|
||||
|
@ -340,7 +340,6 @@ void GrAtlasTextOp::onPrepareDraws(Target* target) {
|
||||
|
||||
char* currVertex = reinterpret_cast<char*>(vertices);
|
||||
|
||||
SkExclusiveStrikePtr autoGlyphCache;
|
||||
// each of these is a SubRun
|
||||
for (int i = 0; i < fGeoCount; i++) {
|
||||
const Geometry& args = fGeoData[i];
|
||||
@ -349,7 +348,7 @@ void GrAtlasTextOp::onPrepareDraws(Target* target) {
|
||||
GrTextBlob::VertexRegenerator regenerator(
|
||||
resourceProvider, blob, args.fRun, args.fSubRun, args.fViewMatrix, args.fX, args.fY,
|
||||
args.fColor.toBytes_RGBA(), target->deferredUploadTarget(), glyphCache,
|
||||
atlasManager, &autoGlyphCache);
|
||||
atlasManager);
|
||||
bool done = false;
|
||||
while (!done) {
|
||||
GrTextBlob::VertexRegenerator::Result result;
|
||||
|
@ -11,8 +11,10 @@
|
||||
#include "src/gpu/text/GrAtlasManager.h"
|
||||
#include "src/gpu/text/GrStrikeCache.h"
|
||||
|
||||
#include "src/core/SkArenaAlloc.h"
|
||||
#include "src/core/SkAutoMalloc.h"
|
||||
#include "src/core/SkDistanceFieldGen.h"
|
||||
#include "src/core/SkStrikeSpec.h"
|
||||
|
||||
GrStrikeCache::GrStrikeCache(const GrCaps* caps, size_t maxTextureBytes)
|
||||
: fPreserveStrike(nullptr)
|
||||
@ -80,12 +82,12 @@ static void expand_bits(INT_TYPE* dst,
|
||||
}
|
||||
}
|
||||
|
||||
static bool get_packed_glyph_image(SkStrike* cache, SkGlyph* glyph, int width,
|
||||
static bool get_packed_glyph_image(const SkGlyph* glyph, int width,
|
||||
int height, int dstRB, GrMaskFormat expectedMaskFormat,
|
||||
void* dst, const SkMasks& masks) {
|
||||
SkASSERT(glyph->width() == width);
|
||||
SkASSERT(glyph->height() == height);
|
||||
const void* src = cache->prepareImage(glyph);
|
||||
const void* src = glyph->image();
|
||||
if (src == nullptr) {
|
||||
return false;
|
||||
}
|
||||
@ -190,11 +192,11 @@ GrDrawOpAtlas::ErrorCode GrTextStrike::addGlyphToAtlas(
|
||||
GrStrikeCache* glyphCache,
|
||||
GrAtlasManager* fullAtlasManager,
|
||||
GrGlyph* glyph,
|
||||
SkStrike* skStrikeCache,
|
||||
SkBulkGlyphMetricsAndImages* metricsAndImages,
|
||||
GrMaskFormat expectedMaskFormat,
|
||||
bool isScaledGlyph) {
|
||||
SkASSERT(glyph);
|
||||
SkASSERT(skStrikeCache);
|
||||
SkASSERT(metricsAndImages);
|
||||
SkASSERT(fCache.find(glyph->fPackedID));
|
||||
|
||||
expectedMaskFormat = fullAtlasManager->resolveMaskFormat(expectedMaskFormat);
|
||||
@ -215,13 +217,13 @@ GrDrawOpAtlas::ErrorCode GrTextStrike::addGlyphToAtlas(
|
||||
}
|
||||
SkAutoSMalloc<1024> storage(size);
|
||||
|
||||
SkGlyph* skGlyph = skStrikeCache->glyph(glyph->fPackedID);
|
||||
const SkGlyph* skGlyph = metricsAndImages->glyph(glyph->fPackedID);
|
||||
void* dataPtr = storage.get();
|
||||
if (addPad) {
|
||||
sk_bzero(dataPtr, size);
|
||||
dataPtr = (char*)(dataPtr) + rowBytes + bytesPerPixel;
|
||||
}
|
||||
if (!get_packed_glyph_image(skStrikeCache, skGlyph, glyph->width(), glyph->height(),
|
||||
if (!get_packed_glyph_image(skGlyph, glyph->width(), glyph->height(),
|
||||
rowBytes, expectedMaskFormat,
|
||||
dataPtr, glyphCache->getMasks())) {
|
||||
return GrDrawOpAtlas::ErrorCode::kError;
|
||||
@ -242,3 +244,25 @@ GrDrawOpAtlas::ErrorCode GrTextStrike::addGlyphToAtlas(
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
GrGlyph* GrTextStrike::getGlyph(const SkGlyph& skGlyph) {
|
||||
GrGlyph* grGlyph = fCache.find(skGlyph.getPackedID());
|
||||
if (grGlyph == nullptr) {
|
||||
grGlyph = fAlloc.make<GrGlyph>(skGlyph);
|
||||
fCache.add(grGlyph);
|
||||
}
|
||||
return grGlyph;
|
||||
}
|
||||
|
||||
GrGlyph*
|
||||
GrTextStrike::getGlyph(SkPackedGlyphID packed, SkBulkGlyphMetricsAndImages* metricsAndImages) {
|
||||
GrGlyph* grGlyph = fCache.find(packed);
|
||||
if (grGlyph == nullptr) {
|
||||
// We could return this to the caller, but in practice it adds code complexity for
|
||||
// potentially little benefit(ie, if the glyph is not in our font cache, then its not
|
||||
// in the atlas and we're going to be doing a texture upload anyways).
|
||||
grGlyph = fAlloc.make<GrGlyph>(*metricsAndImages->glyph(packed));
|
||||
fCache.add(grGlyph);
|
||||
}
|
||||
return grGlyph;
|
||||
}
|
||||
|
@ -9,15 +9,16 @@
|
||||
#define GrStrikeCache_DEFINED
|
||||
|
||||
#include "src/codec/SkMasks.h"
|
||||
#include "src/core/SkArenaAlloc.h"
|
||||
#include "src/core/SkStrike.h"
|
||||
#include "src/core/SkDescriptor.h"
|
||||
#include "src/core/SkTDynamicHash.h"
|
||||
#include "src/gpu/GrDrawOpAtlas.h"
|
||||
#include "src/gpu/GrGlyph.h"
|
||||
|
||||
|
||||
class GrAtlasManager;
|
||||
class GrGpu;
|
||||
class GrStrikeCache;
|
||||
class SkBulkGlyphMetricsAndImages;
|
||||
|
||||
/**
|
||||
* The GrTextStrike manages a pool of CPU backing memory for GrGlyphs. This backing memory
|
||||
@ -30,30 +31,13 @@ class GrTextStrike : public SkNVRefCnt<GrTextStrike> {
|
||||
public:
|
||||
GrTextStrike(const SkDescriptor& fontScalerKey);
|
||||
|
||||
GrGlyph* getGlyph(const SkGlyph& skGlyph) {
|
||||
GrGlyph* grGlyph = fCache.find(skGlyph.getPackedID());
|
||||
if (grGlyph == nullptr) {
|
||||
grGlyph = fAlloc.make<GrGlyph>(skGlyph);
|
||||
fCache.add(grGlyph);
|
||||
}
|
||||
return grGlyph;
|
||||
}
|
||||
GrGlyph* getGlyph(const SkGlyph& skGlyph);
|
||||
|
||||
// This variant of the above function is called by GrAtlasTextOp. At this point, it is possible
|
||||
// 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(SkPackedGlyphID packed, SkStrike* skStrike) {
|
||||
GrGlyph* grGlyph = fCache.find(packed);
|
||||
if (grGlyph == nullptr) {
|
||||
// We could return this to the caller, but in practice it adds code complexity for
|
||||
// potentially little benefit(ie, if the glyph is not in our font cache, then its not
|
||||
// in the atlas and we're going to be doing a texture upload anyways).
|
||||
grGlyph = fAlloc.make<GrGlyph>(*skStrike->glyph(packed));
|
||||
fCache.add(grGlyph);
|
||||
}
|
||||
return grGlyph;
|
||||
}
|
||||
GrGlyph* getGlyph(SkPackedGlyphID packed, SkBulkGlyphMetricsAndImages* metricsAndImages);
|
||||
|
||||
// returns true if glyph successfully added to texture atlas, false otherwise. If the glyph's
|
||||
// mask format has changed, then addGlyphToAtlas will draw a clear box. This will almost never
|
||||
@ -62,7 +46,8 @@ public:
|
||||
// get the actual glyph image itself when we get the glyph metrics.
|
||||
GrDrawOpAtlas::ErrorCode addGlyphToAtlas(GrResourceProvider*, GrDeferredUploadTarget*,
|
||||
GrStrikeCache*, GrAtlasManager*, GrGlyph*,
|
||||
SkStrike*, GrMaskFormat expectedMaskFormat,
|
||||
SkBulkGlyphMetricsAndImages*,
|
||||
GrMaskFormat expectedMaskFormat,
|
||||
bool isScaledGlyph);
|
||||
|
||||
// testing
|
||||
|
@ -593,8 +593,7 @@ public:
|
||||
*/
|
||||
VertexRegenerator(GrResourceProvider*, GrTextBlob*, int runIdx, int subRunIdx,
|
||||
const SkMatrix& viewMatrix, SkScalar x, SkScalar y, GrColor color,
|
||||
GrDeferredUploadTarget*, GrStrikeCache*, GrAtlasManager*,
|
||||
SkExclusiveStrikePtr*);
|
||||
GrDeferredUploadTarget*, GrStrikeCache*, GrAtlasManager*);
|
||||
|
||||
struct Result {
|
||||
/**
|
||||
@ -626,7 +625,7 @@ private:
|
||||
GrDeferredUploadTarget* fUploadTarget;
|
||||
GrStrikeCache* fGlyphCache;
|
||||
GrAtlasManager* fFullAtlasManager;
|
||||
SkExclusiveStrikePtr* fLazyStrike;
|
||||
SkTLazy<SkBulkGlyphMetricsAndImages> fMetricsAndImages;
|
||||
SubRun* fSubRun;
|
||||
GrColor fColor;
|
||||
SkScalar fTransX;
|
||||
|
@ -122,15 +122,13 @@ GrTextBlob::VertexRegenerator::VertexRegenerator(GrResourceProvider* resourcePro
|
||||
GrColor color,
|
||||
GrDeferredUploadTarget* uploadTarget,
|
||||
GrStrikeCache* glyphCache,
|
||||
GrAtlasManager* fullAtlasManager,
|
||||
SkExclusiveStrikePtr* lazyStrike)
|
||||
GrAtlasManager* fullAtlasManager)
|
||||
: fResourceProvider(resourceProvider)
|
||||
, fViewMatrix(viewMatrix)
|
||||
, fBlob(blob)
|
||||
, fUploadTarget(uploadTarget)
|
||||
, fGlyphCache(glyphCache)
|
||||
, fFullAtlasManager(fullAtlasManager)
|
||||
, fLazyStrike(lazyStrike)
|
||||
, fSubRun(&blob->fRuns[runIdx].fSubRunInfo[subRunIdx])
|
||||
, fColor(color) {
|
||||
// Compute translation if any
|
||||
@ -166,9 +164,9 @@ bool GrTextBlob::VertexRegenerator::doRegen(GrTextBlob::VertexRegenerator::Resul
|
||||
|
||||
const SkStrikeSpec& strikeSpec = fSubRun->strikeSpec();
|
||||
|
||||
if (!*fLazyStrike || (*fLazyStrike)->getDescriptor() != strikeSpec.descriptor()) {
|
||||
*fLazyStrike =
|
||||
strikeSpec.findOrCreateExclusiveStrike(SkStrikeCache::GlobalStrikeCache());
|
||||
if (!fMetricsAndImages.isValid()
|
||||
|| fMetricsAndImages->descriptor() != strikeSpec.descriptor()) {
|
||||
fMetricsAndImages.init(strikeSpec);
|
||||
}
|
||||
|
||||
if (regenGlyphs) {
|
||||
@ -193,7 +191,7 @@ bool GrTextBlob::VertexRegenerator::doRegen(GrTextBlob::VertexRegenerator::Resul
|
||||
// Get the id from the old glyph, and use the new strike to lookup
|
||||
// the glyph.
|
||||
SkPackedGlyphID id = fBlob->fGlyphs[glyphOffset]->fPackedID;
|
||||
fBlob->fGlyphs[glyphOffset] = strike->getGlyph(id, fLazyStrike->get());
|
||||
fBlob->fGlyphs[glyphOffset] = strike->getGlyph(id, fMetricsAndImages.get());
|
||||
SkASSERT(id == fBlob->fGlyphs[glyphOffset]->fPackedID);
|
||||
}
|
||||
glyph = fBlob->fGlyphs[glyphOffset];
|
||||
@ -203,7 +201,7 @@ bool GrTextBlob::VertexRegenerator::doRegen(GrTextBlob::VertexRegenerator::Resul
|
||||
GrDrawOpAtlas::ErrorCode code;
|
||||
code = strike->addGlyphToAtlas(fResourceProvider, fUploadTarget, fGlyphCache,
|
||||
fFullAtlasManager, glyph,
|
||||
fLazyStrike->get(), fSubRun->maskFormat(),
|
||||
fMetricsAndImages.get(), fSubRun->maskFormat(),
|
||||
fSubRun->needsTransform());
|
||||
if (GrDrawOpAtlas::ErrorCode::kError == code) {
|
||||
// Something horrible has happened - drop the op
|
||||
|
@ -442,9 +442,8 @@ struct ImageAndOffset {
|
||||
sk_sp<SkImage> fImage;
|
||||
SkIPoint fOffset;
|
||||
};
|
||||
static ImageAndOffset to_image(SkGlyphID gid, SkStrike* cache) {
|
||||
SkGlyph* glyph = cache->glyph(SkPackedGlyphID{gid});
|
||||
(void)cache->prepareImage(glyph);
|
||||
static ImageAndOffset to_image(SkGlyphID gid, SkBulkGlyphMetricsAndImages* smallGlyphs) {
|
||||
const SkGlyph* glyph = smallGlyphs->glyph(SkPackedGlyphID{gid});
|
||||
SkMask mask = glyph->mask();
|
||||
if (!mask.fImage) {
|
||||
return {nullptr, {0, 0}};
|
||||
@ -485,7 +484,7 @@ static ImageAndOffset to_image(SkGlyphID gid, SkStrike* cache) {
|
||||
|
||||
static SkPDFIndirectReference type3_descriptor(SkPDFDocument* doc,
|
||||
const SkTypeface* typeface,
|
||||
SkStrike* cache) {
|
||||
SkScalar xHeight) {
|
||||
if (SkPDFIndirectReference* ptr = doc->fType3FontDescriptors.find(typeface->uniqueID())) {
|
||||
return *ptr;
|
||||
}
|
||||
@ -501,7 +500,6 @@ static SkPDFIndirectReference type3_descriptor(SkPDFDocument* doc,
|
||||
// to "greatly help our workflow downstream".
|
||||
if (metrics->fCapHeight != 0) { descriptor.insertInt("CapHeight", metrics->fCapHeight); }
|
||||
if (metrics->fStemV != 0) { descriptor.insertInt("StemV", metrics->fStemV); }
|
||||
SkScalar xHeight = cache->getFontMetrics().fXHeight;
|
||||
if (xHeight != 0) {
|
||||
descriptor.insertScalar("XHeight", xHeight);
|
||||
}
|
||||
@ -545,11 +543,13 @@ static void emit_subset_type3(const SkPDFFont& pdfFont, SkPDFDocument* doc) {
|
||||
auto cache = strikeSpec.findOrCreateExclusiveStrike();
|
||||
SkASSERT(cache);
|
||||
SkScalar emSize = (SkScalar)unitsPerEm;
|
||||
SkScalar xHeight = cache->getFontMetrics().fXHeight;
|
||||
SkBulkGlyphMetricsAndPaths metricsAndPaths(std::move(cache));
|
||||
|
||||
SkStrikeSpec strikeSpecSmall = kBitmapFontSize > 0 ? make_small_strike(*typeface)
|
||||
: strikeSpec;
|
||||
auto smallCache = strikeSpecSmall.findOrCreateExclusiveStrike();
|
||||
SkASSERT(smallCache);
|
||||
|
||||
SkBulkGlyphMetricsAndImages smallGlyphs(strikeSpecSmall);
|
||||
float bitmapScale = kBitmapFontSize > 0 ? emSize / kBitmapFontSize : 1.0f;
|
||||
|
||||
SkPDFDict font("Font");
|
||||
@ -587,18 +587,18 @@ static void emit_subset_type3(const SkPDFFont& pdfFont, SkPDFDocument* doc) {
|
||||
characterName.set("g0");
|
||||
} else {
|
||||
characterName.printf("g%X", gID);
|
||||
SkGlyph* glyph = cache->glyph(SkPackedGlyphID{gID});
|
||||
const SkGlyph* glyph = metricsAndPaths.glyph(gID);
|
||||
advance = glyph->advanceX();
|
||||
glyphBBox = glyph->iRect();
|
||||
bbox.join(glyphBBox);
|
||||
const SkPath* path = cache->preparePath(glyph);
|
||||
const SkPath* path = glyph->path();
|
||||
SkDynamicMemoryWStream content;
|
||||
if (path && !path->isEmpty()) {
|
||||
setGlyphWidthAndBoundingBox(glyph->advanceX(), glyphBBox, &content);
|
||||
SkPDFUtils::EmitPath(*path, SkPaint::kFill_Style, &content);
|
||||
SkPDFUtils::PaintPath(SkPaint::kFill_Style, path->getFillType(), &content);
|
||||
} else {
|
||||
auto pimg = to_image(gID, smallCache.get());
|
||||
auto pimg = to_image(gID, &smallGlyphs);
|
||||
if (!pimg.fImage) {
|
||||
setGlyphWidthAndBoundingBox(glyph->advanceX(), glyphBBox, &content);
|
||||
} else {
|
||||
@ -659,7 +659,7 @@ static void emit_subset_type3(const SkPDFFont& pdfFont, SkPDFDocument* doc) {
|
||||
firstGlyphID,
|
||||
lastGlyphID);
|
||||
font.insertRef("ToUnicode", SkPDFStreamOut(nullptr, std::move(toUnicodeCmap), doc));
|
||||
font.insertRef("FontDescriptor", type3_descriptor(doc, typeface, cache.get()));
|
||||
font.insertRef("FontDescriptor", type3_descriptor(doc, typeface, xHeight));
|
||||
font.insertObject("Widths", std::move(widthArray));
|
||||
font.insertObject("Encoding", std::move(encoding));
|
||||
font.insertObject("CharProcs", std::move(charProcs));
|
||||
|
@ -891,14 +891,17 @@ DEF_TEST(SkRemoteGlyphCache_SearchOfDesperation, reporter) {
|
||||
auto scalerProxy = static_cast<SkScalerContextProxy*>(testCache->getScalerContext());
|
||||
scalerProxy->initCache(testCache.get(), &strikeCache);
|
||||
|
||||
auto rounding = testCache->roundingSpec();
|
||||
SkBulkGlyphMetricsAndImages metricsAndImages{std::move(testCache)};
|
||||
|
||||
// Look for the lost glyph.
|
||||
{
|
||||
SkPoint pt{SkFixedToScalar(lostGlyphID.getSubXFixed()),
|
||||
SkFixedToScalar(lostGlyphID.getSubYFixed())};
|
||||
SkPackedGlyphID packedID{
|
||||
lostGlyphID.glyphID(), pt, testCache->roundingSpec().ignorePositionFieldMask};
|
||||
SkGlyph* lostGlyph = testCache->glyph(packedID);
|
||||
testCache->prepareImage(lostGlyph);
|
||||
lostGlyphID.glyphID(), pt, rounding.ignorePositionFieldMask};
|
||||
|
||||
const SkGlyph* lostGlyph = metricsAndImages.glyph(packedID);
|
||||
|
||||
REPORTER_ASSERT(reporter, lostGlyph->height() == 1);
|
||||
REPORTER_ASSERT(reporter, lostGlyph->width() == 2);
|
||||
@ -911,9 +914,8 @@ DEF_TEST(SkRemoteGlyphCache_SearchOfDesperation, reporter) {
|
||||
SkPoint pt{SkFixedToScalar(SK_FixedQuarter),
|
||||
SkFixedToScalar(SK_FixedQuarter)};
|
||||
SkPackedGlyphID packedID{
|
||||
lostGlyphID.glyphID(), pt, testCache->roundingSpec().ignorePositionFieldMask};
|
||||
SkGlyph* lostGlyph = testCache->glyph(packedID);
|
||||
testCache->prepareImage(lostGlyph);
|
||||
lostGlyphID.glyphID(), pt, rounding.ignorePositionFieldMask};
|
||||
const SkGlyph* lostGlyph = metricsAndImages.glyph(packedID);
|
||||
|
||||
REPORTER_ASSERT(reporter, lostGlyph->height() == 1);
|
||||
REPORTER_ASSERT(reporter, lostGlyph->width() == 2);
|
||||
|
Loading…
Reference in New Issue
Block a user