Make fPathData private and add API for paths
The new API eliminates all need to access the path inner workings. There are some uses of the cast (SkGlyph*) these are to facilitate the larger change this is a part of. The will be eliminated when all is done. Some of the code has been changed to use strike->glyph(id) and SkGlyph* to help with the flow of the code. Change-Id: Id8dc84076f56e1e39450367a0440d15954dbdc71 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/220523 Commit-Queue: Herb Derby <herb@google.com> Reviewed-by: Mike Klein <mtklein@google.com>
This commit is contained in:
parent
1127c0b273
commit
f0e7581d94
@ -460,6 +460,12 @@ public:
|
||||
*/
|
||||
int getVerbs(uint8_t verbs[], int max) const;
|
||||
|
||||
/** Returns the approximate byte size of the SkPath in memory.
|
||||
|
||||
@return approximate size
|
||||
*/
|
||||
size_t approximateBytesUsed() const;
|
||||
|
||||
/** Exchanges the verb array, SkPoint array, weights, and SkPath::FillType with other.
|
||||
Cached state is also exchanged. swap() internally exchanges pointers, so
|
||||
it is lightweight and does not allocate memory.
|
||||
|
@ -355,14 +355,14 @@ void SkFont::getPaths(const SkGlyphID glyphs[], int count,
|
||||
void (*proc)(const SkPath*, const SkMatrix&, void*), void* ctx) const {
|
||||
SkFont font(*this);
|
||||
SkScalar scale = font.setupForAsPaths(nullptr);
|
||||
const SkMatrix mx = SkMatrix::MakeScale(scale, scale);
|
||||
const SkMatrix mx = SkMatrix::MakeScale(scale);
|
||||
|
||||
SkStrikeSpec strikeSpec = SkStrikeSpec::MakeCanonicalized(font);
|
||||
auto exclusive = strikeSpec.findOrCreateExclusiveStrike();
|
||||
auto cache = exclusive.get();
|
||||
|
||||
for (int i = 0; i < count; ++i) {
|
||||
proc(cache->findPath(cache->getGlyphIDMetrics(glyphs[i])), mx, ctx);
|
||||
proc(cache->preparePath(cache->glyph(glyphs[i])), mx, ctx);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,18 +117,47 @@ size_t SkGlyph::copyImageData(const SkGlyph& from, SkArenaAlloc* alloc) {
|
||||
return 0u;
|
||||
}
|
||||
|
||||
SkPath* SkGlyph::addPath(SkScalerContext* scalerContext, SkArenaAlloc* alloc) {
|
||||
if (!this->isEmpty()) {
|
||||
if (fPathData == nullptr) {
|
||||
void SkGlyph::installPath(SkArenaAlloc* alloc, const SkPath* path) {
|
||||
SkASSERT(fPathData == nullptr);
|
||||
SkASSERT(!this->setPathHasBeenCalled());
|
||||
fPathData = alloc->make<SkGlyph::PathData>();
|
||||
if (scalerContext->getPath(this->getPackedID(), &fPathData->fPath)) {
|
||||
if (path != nullptr) {
|
||||
fPathData->fPath = *path;
|
||||
fPathData->fPath.updateBoundsCache();
|
||||
fPathData->fPath.getGenerationID();
|
||||
fPathData->fHasPath = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool SkGlyph::setPath(SkArenaAlloc* alloc, SkScalerContext* scalerContext) {
|
||||
if (!this->setPathHasBeenCalled()) {
|
||||
SkPath path;
|
||||
if (scalerContext->getPath(this->getPackedID(), &path)) {
|
||||
this->installPath(alloc, &path);
|
||||
} else {
|
||||
this->installPath(alloc, nullptr);
|
||||
}
|
||||
return this->path() != nullptr;
|
||||
}
|
||||
return this->path();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SkGlyph::setPath(SkArenaAlloc* alloc, const SkPath* path) {
|
||||
if (!this->setPathHasBeenCalled()) {
|
||||
this->installPath(alloc, path);
|
||||
return this->path() != nullptr;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const SkPath* SkGlyph::path() const {
|
||||
// setPath must have been called previously.
|
||||
SkASSERT(this->setPathHasBeenCalled());
|
||||
if (fPathData->fHasPath) {
|
||||
return &fPathData->fPath;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static std::tuple<SkScalar, SkScalar> calculate_path_gap(
|
||||
|
@ -153,21 +153,26 @@ public:
|
||||
|
||||
SkMask mask(SkPoint position) const;
|
||||
|
||||
SkPath* addPath(SkScalerContext*, SkArenaAlloc*);
|
||||
// If we haven't already tried to associate a path to this glyph
|
||||
// (i.e. setPathHasBeenCalled() returns false), then use the
|
||||
// SkScalerContext or SkPath argument to try to do so. N.B. this
|
||||
// may still result in no path being associated with this glyph,
|
||||
// e.g. if you pass a null SkPath or the typeface is bitmap-only.
|
||||
//
|
||||
// This setPath() call is sticky... once you call it, the glyph
|
||||
// stays in its state permanently, ignoring any future calls.
|
||||
//
|
||||
// Returns true if this is the first time you called setPath()
|
||||
// and there actually is a path; call path() to get it.
|
||||
bool setPath(SkArenaAlloc* alloc, SkScalerContext* scalerContext);
|
||||
bool setPath(SkArenaAlloc* alloc, const SkPath* path);
|
||||
|
||||
SkPath* path() const {
|
||||
return fPathData != nullptr && fPathData->fHasPath ? &fPathData->fPath : nullptr;
|
||||
}
|
||||
// Returns true if that path has been set.
|
||||
bool setPathHasBeenCalled() const { return fPathData != nullptr; }
|
||||
|
||||
bool hasPath() const {
|
||||
// Need to have called getMetrics before calling findPath.
|
||||
SkASSERT(fMaskFormat != MASK_FORMAT_UNKNOWN);
|
||||
|
||||
// Find path must have been called to use this call.
|
||||
SkASSERT(fPathData != nullptr);
|
||||
|
||||
return fPathData != nullptr && fPathData->fHasPath;
|
||||
}
|
||||
// Return a pointer to the path if it exists, otherwise return nullptr. Only works if the
|
||||
// path was previously set.
|
||||
const SkPath* path() const;
|
||||
|
||||
int maxDimension() const {
|
||||
// width and height are only defined if a metrics call was made.
|
||||
@ -190,11 +195,6 @@ public:
|
||||
|
||||
void* fImage = nullptr;
|
||||
|
||||
// Path data has tricky state. If the glyph isEmpty, then fPathData should always be nullptr,
|
||||
// else if fPathData is not null, then a path has been requested. The fPath field of fPathData
|
||||
// may still be null after the request meaning that there is no path for this glyph.
|
||||
PathData* fPathData = nullptr;
|
||||
|
||||
// The width and height of the glyph mask.
|
||||
uint16_t fWidth = 0,
|
||||
fHeight = 0;
|
||||
@ -239,6 +239,14 @@ private:
|
||||
bool fHasPath{false};
|
||||
};
|
||||
|
||||
// path == nullptr indicates there is no path.
|
||||
void installPath(SkArenaAlloc* alloc, const SkPath* path);
|
||||
|
||||
// Path data has tricky state. If the glyph isEmpty, then fPathData should always be nullptr,
|
||||
// else if fPathData is not null, then a path has been requested. The fPath field of fPathData
|
||||
// may still be null after the request meaning that there is no path for this glyph.
|
||||
PathData* fPathData = nullptr;
|
||||
|
||||
// The advance for this glyph.
|
||||
float fAdvanceX = 0,
|
||||
fAdvanceY = 0;
|
||||
|
@ -167,16 +167,16 @@ void SkGlyphRunListPainter::drawForBitmapDevice(
|
||||
if (check_glyph_position(position)
|
||||
&& !glyph.isEmpty()
|
||||
&& glyph.fMaskFormat != SkMask::kARGB32_Format
|
||||
&& glyph.hasPath())
|
||||
&& glyph.path() != nullptr)
|
||||
{
|
||||
// Only draw a path if it exists, and this is not a color glyph.
|
||||
pathsAndPositions.push_back(SkPathPos{glyph.path(), position});
|
||||
} else {
|
||||
// TODO: this is here to have chrome layout tests pass. Remove this when
|
||||
// fallback for CPU works.
|
||||
strike->generatePath(glyph);
|
||||
if (check_glyph_position(position) && !glyph.isEmpty() && glyph.hasPath()) {
|
||||
pathsAndPositions.push_back(SkPathPos{glyph.path(), position});
|
||||
const SkPath* path = strike->preparePath((SkGlyph*) &glyph);
|
||||
if (check_glyph_position(position) && !glyph.isEmpty() && path != nullptr) {
|
||||
pathsAndPositions.push_back(SkPathPos{path, position});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -394,7 +394,8 @@ void SkGlyphRunListPainter::processGlyphRunList(const SkGlyphRunList& glyphRunLi
|
||||
&& glyph.maxDimension() <= SkStrikeCommon::kSkSideTooBigForAtlas) {
|
||||
// SDF mask will work.
|
||||
fGlyphPos[glyphsWithMaskCount++] = glyphPos;
|
||||
} else if (glyph.fMaskFormat != SkMask::kARGB32_Format && glyph.hasPath()) {
|
||||
} else if (glyph.fMaskFormat != SkMask::kARGB32_Format
|
||||
&& glyph.path() != nullptr) {
|
||||
// If not color but too big, use a path.
|
||||
fPaths.push_back(glyphPos);
|
||||
} else {
|
||||
@ -455,7 +456,8 @@ void SkGlyphRunListPainter::processGlyphRunList(const SkGlyphRunList& glyphRunLi
|
||||
SkPoint position = glyphPos.position;
|
||||
if (glyph.isEmpty()) {
|
||||
// do nothing
|
||||
} else if (glyph.fMaskFormat != SkMask::kARGB32_Format && glyph.hasPath()) {
|
||||
} else if (glyph.fMaskFormat != SkMask::kARGB32_Format
|
||||
&& glyph.path() != nullptr) {
|
||||
// Place paths in fGlyphPos
|
||||
fGlyphPos[glyphsWithPathCount++] = glyphPos;
|
||||
} else {
|
||||
@ -512,7 +514,8 @@ void SkGlyphRunListPainter::processGlyphRunList(const SkGlyphRunList& glyphRunLi
|
||||
|
||||
if (glyph.maxDimension() <= SkStrikeCommon::kSkSideTooBigForAtlas) {
|
||||
fGlyphPos[glyphsWithMaskCount++] = glyphPos;
|
||||
} else if (glyph.fMaskFormat != SkMask::kARGB32_Format && glyph.hasPath()) {
|
||||
} else if (glyph.fMaskFormat != SkMask::kARGB32_Format
|
||||
&& glyph.path() != nullptr) {
|
||||
fPaths.push_back(glyphPos);
|
||||
} else {
|
||||
addFallback(glyph, origin + glyphRun.positions()[glyphPos.index]);
|
||||
|
@ -700,6 +700,17 @@ int SkPath::getVerbs(uint8_t dst[], int max) const {
|
||||
return fPathRef->countVerbs();
|
||||
}
|
||||
|
||||
size_t SkPath::approximateBytesUsed() const {
|
||||
size_t size = sizeof (SkPath);
|
||||
if (fPathRef != nullptr) {
|
||||
size += fPathRef->countPoints() * sizeof(SkPoint)
|
||||
+ fPathRef->countVerbs()
|
||||
+ fPathRef->countWeights() * sizeof(SkScalar);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
bool SkPath::getLastPt(SkPoint* lastPt) const {
|
||||
SkDEBUGCODE(this->validate();)
|
||||
|
||||
|
@ -165,25 +165,6 @@ private:
|
||||
// Paths use a SkWriter32 which requires 4 byte alignment.
|
||||
static const size_t kPathAlignment = 4u;
|
||||
|
||||
bool read_path(Deserializer* deserializer, SkGlyph* glyph, SkStrike* cache) {
|
||||
uint64_t pathSize = 0u;
|
||||
if (!deserializer->read<uint64_t>(&pathSize)) return false;
|
||||
|
||||
if (pathSize == 0u) {
|
||||
cache->initializePath(glyph, nullptr, 0u);
|
||||
return true;
|
||||
}
|
||||
|
||||
auto* path = deserializer->read(pathSize, kPathAlignment);
|
||||
if (!path) return false;
|
||||
|
||||
// Don't overwrite the path if we already have one. We could have used a fallback if the
|
||||
// glyph was missing earlier.
|
||||
if (glyph->fPathData != nullptr) return true;
|
||||
|
||||
return cache->initializePath(glyph, path, pathSize);
|
||||
}
|
||||
|
||||
size_t SkDescriptorMapOperators::operator()(const SkDescriptor* key) const {
|
||||
return key->getChecksum();
|
||||
}
|
||||
@ -579,20 +560,15 @@ const SkGlyph& SkStrikeServer::SkGlyphCacheState::getGlyphMetrics(
|
||||
//
|
||||
// A key reason for no path is the fact that the glyph is a color image or is a bitmap only
|
||||
// font.
|
||||
void SkStrikeServer::SkGlyphCacheState::generatePath(const SkGlyph& glyph) {
|
||||
const SkPath* SkStrikeServer::SkGlyphCacheState::preparePath(SkGlyph* glyph) {
|
||||
|
||||
// Check to see if we have processed this glyph for a path before.
|
||||
if (glyph.fPathData == nullptr) {
|
||||
|
||||
// Never checked for a path before. Add the path now.
|
||||
auto path = const_cast<SkGlyph&>(glyph).addPath(fContext.get(), &fAlloc);
|
||||
if (path != nullptr) {
|
||||
|
||||
if (glyph->setPath(&fAlloc, fContext.get())) {
|
||||
// A path was added make sure to send it to the GPU.
|
||||
fCachedGlyphPaths.add(glyph.getPackedID());
|
||||
fPendingGlyphPaths.push_back(glyph.getPackedID());
|
||||
}
|
||||
fCachedGlyphPaths.add(glyph->getPackedID());
|
||||
fPendingGlyphPaths.push_back(glyph->getPackedID());
|
||||
}
|
||||
return glyph->path();
|
||||
}
|
||||
|
||||
void SkStrikeServer::SkGlyphCacheState::writeGlyphPath(const SkPackedGlyphID& glyphID,
|
||||
@ -644,18 +620,13 @@ SkSpan<const SkGlyphPos> SkStrikeServer::SkGlyphCacheState::prepareForDrawing(
|
||||
|
||||
// The glyph is too big for the atlas, but it is not color, so it is handled with a
|
||||
// path.
|
||||
if (glyphPtr->fPathData == nullptr) {
|
||||
|
||||
// Never checked for a path before. Add the path now.
|
||||
const_cast<SkGlyph&>(*glyphPtr).addPath(fContext.get(), &fAlloc);
|
||||
|
||||
if (glyphPtr->setPath(&fAlloc, fContext.get())) {
|
||||
// Always send the path data, even if its not available, to make sure empty
|
||||
// paths are not incorrectly assumed to be cache misses.
|
||||
fCachedGlyphPaths.add(glyphPtr->getPackedID());
|
||||
fPendingGlyphPaths.push_back(glyphPtr->getPackedID());
|
||||
}
|
||||
} else {
|
||||
|
||||
// This will be handled by the fallback strike.
|
||||
SkASSERT(glyphPtr->maxDimension() > maxDimension
|
||||
&& glyphPtr->fMaskFormat == SkMask::kARGB32_Format);
|
||||
@ -821,15 +792,19 @@ bool SkStrikeClient::readStrikeData(const volatile void* memory, size_t memorySi
|
||||
|
||||
SkGlyph* allocatedGlyph = strike->getRawGlyphByID(glyph->getPackedID());
|
||||
|
||||
// Update the glyph unless it's already got a path (from fallback),
|
||||
// preserving any image that might be present.
|
||||
if (allocatedGlyph->fPathData == nullptr) {
|
||||
auto* glyphImage = allocatedGlyph->fImage;
|
||||
*allocatedGlyph = *glyph;
|
||||
allocatedGlyph->fImage = glyphImage;
|
||||
SkPath* pathPtr = nullptr;
|
||||
SkPath path;
|
||||
uint64_t pathSize = 0u;
|
||||
if (!deserializer.read<uint64_t>(&pathSize)) READ_FAILURE
|
||||
|
||||
if (pathSize > 0) {
|
||||
auto* pathData = deserializer.read(pathSize, kPathAlignment);
|
||||
if (!pathData) READ_FAILURE
|
||||
if (!path.readFromMemory(const_cast<const void*>(pathData), pathSize)) READ_FAILURE
|
||||
pathPtr = &path;
|
||||
}
|
||||
|
||||
if (!read_path(&deserializer, allocatedGlyph, strike.get())) READ_FAILURE
|
||||
strike->preparePath(allocatedGlyph, pathPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,7 @@ public:
|
||||
PreparationDetail detail,
|
||||
SkGlyphPos results[]) override;
|
||||
|
||||
void generatePath(const SkGlyph& glyph) override;
|
||||
const SkPath* preparePath(SkGlyph* glyph) override;
|
||||
|
||||
void onAboutToExitScope() override {}
|
||||
|
||||
|
@ -16,12 +16,6 @@
|
||||
#include "src/core/SkMakeUnique.h"
|
||||
#include <cctype>
|
||||
|
||||
namespace {
|
||||
size_t compute_path_size(const SkPath& path) {
|
||||
return sizeof(SkPath) + path.countPoints() * sizeof(SkPoint);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
SkStrike::SkStrike(
|
||||
const SkDescriptor& desc,
|
||||
std::unique_ptr<SkScalerContext> scaler,
|
||||
@ -71,6 +65,10 @@ SkGlyph* SkStrike::glyph(SkGlyphID glyphID) {
|
||||
return this->glyph(SkPackedGlyphID{glyphID});
|
||||
}
|
||||
|
||||
SkGlyph* SkStrike::glyphOrNull(SkPackedGlyphID id) const {
|
||||
return fGlyphMap.findOrNull(id);
|
||||
}
|
||||
|
||||
SkGlyph* SkStrike::getRawGlyphByID(SkPackedGlyphID id) {
|
||||
return this->uninitializedGlyph(id);
|
||||
}
|
||||
@ -90,6 +88,20 @@ const SkGlyph& SkStrike::getGlyphIDMetrics(SkGlyphID glyphID, SkFixed x, SkFixed
|
||||
return *this->glyph(packedGlyphID);
|
||||
}
|
||||
|
||||
const SkPath* SkStrike::preparePath(SkGlyph* glyph) {
|
||||
if (glyph->setPath(&fAlloc, fScalerContext.get())) {
|
||||
fMemoryUsed += glyph->path()->approximateBytesUsed();
|
||||
}
|
||||
return glyph->path();
|
||||
}
|
||||
|
||||
const SkPath* SkStrike::preparePath(SkGlyph* glyph, const SkPath* path) {
|
||||
if (glyph->setPath(&fAlloc, path)) {
|
||||
fMemoryUsed += glyph->path()->approximateBytesUsed();
|
||||
}
|
||||
return glyph->path();
|
||||
}
|
||||
|
||||
const SkDescriptor& SkStrike::getDescriptor() const {
|
||||
return *fDesc.getDesc();
|
||||
}
|
||||
@ -148,46 +160,6 @@ void SkStrike::initializeImage(const volatile void* data, size_t size, SkGlyph*
|
||||
}
|
||||
}
|
||||
|
||||
const SkPath* SkStrike::findPath(const SkGlyph& glyph) {
|
||||
|
||||
if (!glyph.isEmpty()) {
|
||||
// If the path already exists, return it.
|
||||
if (glyph.fPathData != nullptr) {
|
||||
if (glyph.fPathData->fHasPath) {
|
||||
return &glyph.fPathData->fPath;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const_cast<SkGlyph&>(glyph).addPath(fScalerContext.get(), &fAlloc);
|
||||
if (glyph.fPathData != nullptr) {
|
||||
fMemoryUsed += compute_path_size(glyph.fPathData->fPath);
|
||||
}
|
||||
|
||||
return glyph.path();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool SkStrike::initializePath(SkGlyph* glyph, const volatile void* data, size_t size) {
|
||||
SkASSERT(!glyph->fPathData);
|
||||
|
||||
if (glyph->fWidth) {
|
||||
SkGlyph::PathData* pathData = fAlloc.make<SkGlyph::PathData>();
|
||||
glyph->fPathData = pathData;
|
||||
if (size == 0u) return true;
|
||||
|
||||
auto path = skstd::make_unique<SkPath>();
|
||||
if (!pathData->fPath.readFromMemory(const_cast<const void*>(data), size)) {
|
||||
return false;
|
||||
}
|
||||
fMemoryUsed += compute_path_size(glyph->fPathData->fPath);
|
||||
pathData->fHasPath = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SkStrike::belongsToCache(const SkGlyph* glyph) const {
|
||||
return glyph && fGlyphMap.findOrNull(glyph->getPackedID()) == glyph;
|
||||
@ -250,7 +222,7 @@ SkSpan<const SkGlyphPos> SkStrike::prepareForDrawing(const SkGlyphID glyphIDs[],
|
||||
}
|
||||
} else if (glyph.fMaskFormat != SkMask::kARGB32_Format) {
|
||||
// The out of atlas glyph is not color so we can draw it using paths.
|
||||
this->findPath(glyph);
|
||||
this->preparePath(const_cast<SkGlyph*>(&glyph));
|
||||
} else {
|
||||
// This will be handled by the fallback strike.
|
||||
SkASSERT(glyph.maxDimension() > maxDimension
|
||||
@ -285,10 +257,6 @@ void SkStrike::dump() const {
|
||||
SkDebugf("%s\n", msg.c_str());
|
||||
}
|
||||
|
||||
void SkStrike::generatePath(const SkGlyph& glyph) {
|
||||
if (!glyph.isEmpty()) { this->findPath(glyph); }
|
||||
}
|
||||
|
||||
void SkStrike::onAboutToExitScope() { }
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
@ -299,8 +267,8 @@ void SkStrike::forceValidate() const {
|
||||
if (glyphPtr->fImage) {
|
||||
memoryUsed += glyphPtr->computeImageSize();
|
||||
}
|
||||
if (glyphPtr->fPathData) {
|
||||
memoryUsed += compute_path_size(glyphPtr->fPathData->fPath);
|
||||
if (glyphPtr->setPathHasBeenCalled() && glyphPtr->path() != nullptr) {
|
||||
memoryUsed += glyphPtr->path()->approximateBytesUsed();
|
||||
}
|
||||
});
|
||||
SkASSERT(fMemoryUsed == memoryUsed);
|
||||
|
@ -66,9 +66,18 @@ public:
|
||||
SkGlyph* glyph(SkPackedGlyphID id);
|
||||
SkGlyph* glyph(SkGlyphID);
|
||||
|
||||
// Return a glyph or nullptr if it does not exits in the strike.
|
||||
SkGlyph* glyphOrNull(SkPackedGlyphID id) const;
|
||||
|
||||
// Return a glyph. Create it if it doesn't exist, but zero the data.
|
||||
SkGlyph* uninitializedGlyph(SkPackedGlyphID id);
|
||||
|
||||
// If the path has never been set, then use the scaler context to add the glyph.
|
||||
const SkPath* preparePath(SkGlyph*) override;
|
||||
|
||||
// If the path has never been set, then add a path to glyph.
|
||||
const SkPath* preparePath(SkGlyph* glyph, const SkPath* path);
|
||||
|
||||
void getAdvances(SkSpan<const SkGlyphID>, SkPoint[]);
|
||||
|
||||
/** Returns the number of glyphs for this strike.
|
||||
@ -93,16 +102,6 @@ public:
|
||||
void findIntercepts(const SkScalar bounds[2], SkScalar scale, SkScalar xPos,
|
||||
SkGlyph* , SkScalar* array, int* count);
|
||||
|
||||
/** Return the Path associated with the glyph. If it has not been generated this will trigger
|
||||
that.
|
||||
*/
|
||||
const SkPath* findPath(const SkGlyph&);
|
||||
|
||||
/** Initializes the path associated with the glyph with |data|. Returns false if
|
||||
* data is invalid.
|
||||
*/
|
||||
bool initializePath(SkGlyph*, const volatile void* data, size_t size);
|
||||
|
||||
/** Fallback glyphs used during font remoting if the original glyph can't be found.
|
||||
*/
|
||||
bool belongsToCache(const SkGlyph* glyph) const;
|
||||
@ -131,8 +130,6 @@ public:
|
||||
|
||||
const SkGlyph& getGlyphMetrics(SkGlyphID glyphID, SkPoint position) override;
|
||||
|
||||
void generatePath(const SkGlyph& glyph) override;
|
||||
|
||||
const SkDescriptor& getDescriptor() const override;
|
||||
|
||||
SkSpan<const SkGlyphPos> prepareForDrawing(const SkGlyphID glyphIDs[],
|
||||
|
@ -46,8 +46,8 @@ public:
|
||||
glyphIDs, positions, n, maxDimension, detail, results);
|
||||
}
|
||||
|
||||
void generatePath(const SkGlyph& glyph) override {
|
||||
fStrike.generatePath(glyph);
|
||||
const SkPath* preparePath(SkGlyph* glyph) override {
|
||||
return fStrike.preparePath(glyph);
|
||||
}
|
||||
|
||||
const SkDescriptor& getDescriptor() const override {
|
||||
@ -349,12 +349,11 @@ bool SkStrikeCache::desperationSearchForPath(
|
||||
// There is also a problem with accounting for cache size with shared path data.
|
||||
for (Node* node = internalGetHead(); node != nullptr; node = node->fNext) {
|
||||
if (loose_compare(node->fStrike.getDescriptor(), desc)) {
|
||||
if (node->fStrike.isGlyphCached(glyphID, 0, 0)) {
|
||||
SkGlyph* from = node->fStrike.getRawGlyphByID(SkPackedGlyphID(glyphID));
|
||||
if (from->fPathData != nullptr) {
|
||||
if (SkGlyph *from = node->fStrike.glyphOrNull(SkPackedGlyphID{glyphID})) {
|
||||
if (from->setPathHasBeenCalled() && from->path() != nullptr) {
|
||||
// We can just copy the path out by value here, so no need to worry
|
||||
// about the lifetime of this desperate-match node.
|
||||
*path = from->fPathData->fPath;
|
||||
*path = *from->path();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -70,8 +70,9 @@ public:
|
||||
SkGlyphPos results[]) = 0;
|
||||
|
||||
virtual const SkGlyph& getGlyphMetrics(SkGlyphID glyphID, SkPoint position) = 0;
|
||||
// TODO: Deprecated. Do not use. Remove when ARGB fallback for bitmap device paths is working.
|
||||
virtual void generatePath(const SkGlyph& glyph) = 0;
|
||||
|
||||
// If glyph does not have an existing path, then add a path to glyph using a scaler context.
|
||||
virtual const SkPath* preparePath(SkGlyph* glyph) = 0;
|
||||
virtual void onAboutToExitScope() = 0;
|
||||
|
||||
struct Deleter {
|
||||
|
@ -941,11 +941,11 @@ TextInterceptsIter::TextInterceptsIter(const SkGlyphID glyphs[],
|
||||
|
||||
bool TextInterceptsIter::next(SkScalar* array, int* count) {
|
||||
SkASSERT(fGlyphs < fStop);
|
||||
const SkGlyph& glyph = fCache->getGlyphIDMetrics(*fGlyphs++);
|
||||
SkGlyph* glyph = fCache->glyph(*fGlyphs++);
|
||||
fXPos += fPrevAdvance * fScale;
|
||||
fPrevAdvance = SkFloatToScalar(glyph.advanceX());
|
||||
if (fCache->findPath(glyph)) {
|
||||
fCache->findIntercepts(fBounds, fScale, fXPos, const_cast<SkGlyph*>(&glyph), array, count);
|
||||
fPrevAdvance = glyph->advanceX();
|
||||
if (fCache->preparePath(glyph) != nullptr) {
|
||||
fCache->findIntercepts(fBounds, fScale, fXPos, glyph, array, count);
|
||||
}
|
||||
return fGlyphs < fStop;
|
||||
}
|
||||
|
@ -778,12 +778,12 @@ static bool needs_new_font(SkPDFFont* font, SkGlyphID gid, SkStrike* cache,
|
||||
if (fontType == SkAdvancedTypefaceMetrics::kOther_Font) {
|
||||
return false;
|
||||
}
|
||||
const SkGlyph& glyph = cache->getGlyphIDMetrics(gid);
|
||||
if (glyph.isEmpty()) {
|
||||
SkGlyph* glyph = cache->glyph(gid);
|
||||
if (glyph->isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool bitmapOnly = nullptr == cache->findPath(glyph);
|
||||
bool bitmapOnly = nullptr == cache->preparePath(glyph);
|
||||
bool convertedToType3 = (font->getType() == SkAdvancedTypefaceMetrics::kOther_Font);
|
||||
return convertedToType3 != bitmapOnly;
|
||||
}
|
||||
|
@ -181,8 +181,8 @@ static SkGlyphID first_nonzero_glyph_for_single_byte_encoding(SkGlyphID gid) {
|
||||
}
|
||||
|
||||
static bool has_outline_glyph(SkGlyphID gid, SkStrike* cache) {
|
||||
const SkGlyph& glyph = cache->getGlyphIDMetrics(gid);
|
||||
return glyph.isEmpty() || cache->findPath(glyph);
|
||||
SkGlyph* glyph = cache->glyph(gid);
|
||||
return glyph->isEmpty() || cache->preparePath(glyph);
|
||||
}
|
||||
|
||||
SkPDFFont* SkPDFFont::GetFontResource(SkPDFDocument* doc,
|
||||
@ -569,25 +569,24 @@ static void emit_subset_type3(const SkPDFFont& pdfFont, SkPDFDocument* doc) {
|
||||
characterName.set("g0");
|
||||
} else {
|
||||
characterName.printf("g%X", gID);
|
||||
const SkGlyph& glyph = cache->getGlyphIDMetrics(gID);
|
||||
advance = SkFloatToScalar(glyph.advanceX());
|
||||
glyphBBox = SkIRect::MakeXYWH(glyph.fLeft, glyph.fTop,
|
||||
glyph.fWidth, glyph.fHeight);
|
||||
SkGlyph* glyph = cache->glyph(gID);
|
||||
advance = glyph->advanceX();
|
||||
glyphBBox = SkIRect::MakeXYWH(glyph->fLeft, glyph->fTop,
|
||||
glyph->fWidth, glyph->fHeight);
|
||||
bbox.join(glyphBBox);
|
||||
const SkPath* path = cache->findPath(glyph);
|
||||
const SkPath* path = cache->preparePath(glyph);
|
||||
SkDynamicMemoryWStream content;
|
||||
if (path && !path->isEmpty()) {
|
||||
setGlyphWidthAndBoundingBox(SkFloatToScalar(glyph.advanceX()), glyphBBox, &content);
|
||||
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, cache.get());
|
||||
if (!pimg.fImage) {
|
||||
setGlyphWidthAndBoundingBox(SkFloatToScalar(glyph.advanceX()), glyphBBox,
|
||||
&content);
|
||||
setGlyphWidthAndBoundingBox(glyph->advanceX(), glyphBBox, &content);
|
||||
} else {
|
||||
imageGlyphs.emplace_back(gID, SkPDFSerializeImage(pimg.fImage.get(), doc));
|
||||
SkPDFUtils::AppendScalar(SkFloatToScalar(glyph.advanceX()), &content);
|
||||
SkPDFUtils::AppendScalar(glyph->advanceX(), &content);
|
||||
content.writeText(" 0 d0\n");
|
||||
content.writeDecAsText(pimg.fImage->width());
|
||||
content.writeText(" 0 0 ");
|
||||
|
Loading…
Reference in New Issue
Block a user