Distinguish between glyphs with empty path and no path.

BUG=skia:4904

Change-Id: I065e3b4d8596b415ddaf094d7f9a4b65da64d4d4
Reviewed-on: https://skia-review.googlesource.com/117280
Commit-Queue: Ben Wagner <bungeman@google.com>
Reviewed-by: Herb Derby <herb@google.com>
This commit is contained in:
Ben Wagner 2018-03-29 11:18:06 -04:00 committed by Skia Commit-Bot
parent b45aac961d
commit 5ddb308625
20 changed files with 86 additions and 72 deletions

View File

@ -48,8 +48,8 @@ private:
SkPaint defaultPaint;
auto cache = SkGlyphCache::FindOrCreateStrikeExclusive(defaultPaint);
for (int i = 0; i < kNumGlyphs; ++i) {
SkGlyphID id = cache->unicharToGlyph(kGlyphs[i]);
cache->getScalerContext()->getPath(SkPackedGlyphID(id), &fGlyphs[i]);
SkPackedGlyphID id(cache->unicharToGlyph(kGlyphs[i]));
sk_ignore_unused_variable(cache->getScalerContext()->getPath(id, &fGlyphs[i]));
fGlyphs[i].setIsVolatile(fUncached);
}

View File

@ -29,8 +29,8 @@ public:
for (int i = 0; i < 52; ++i) {
// I and l are rects on OS X ...
char c = "aQCDEFGH7JKLMNOPBRZTUVWXYSAbcdefghijk1mnopqrstuvwxyz"[i];
SkGlyphID id = cache->unicharToGlyph(c);
cache->getScalerContext()->getPath(SkPackedGlyphID(id), &glyphPaths[i]);
SkPackedGlyphID id(cache->unicharToGlyph(c));
sk_ignore_unused_variable(cache->getScalerContext()->getPath(id, &glyphPaths[i]));
}
for (int i = 0; i < kNumPaths; ++i) {

View File

@ -214,9 +214,14 @@ const SkPath* SkGlyphCache::findPath(const SkGlyph& glyph) {
SkGlyph::PathData* pathData = fAlloc.make<SkGlyph::PathData>();
const_cast<SkGlyph&>(glyph).fPathData = pathData;
pathData->fIntercept = nullptr;
SkPath* path = pathData->fPath = new SkPath;
fScalerContext->getPath(glyph.getPackedID(), path);
fMemoryUsed += sizeof(SkPath) + path->countPoints() * sizeof(SkPoint);
SkPath* path = new SkPath;
if (fScalerContext->getPath(glyph.getPackedID(), path)) {
pathData->fPath = path;
fMemoryUsed += sizeof(SkPath) + path->countPoints() * sizeof(SkPoint);
} else {
pathData->fPath = nullptr;
delete path;
}
}
}
return glyph.fPathData ? glyph.fPathData->fPath : nullptr;

View File

@ -616,11 +616,12 @@ int SkStrikeServer::serve() {
auto sc = this->generateScalerContext(op->descriptor, op->typefaceId);
// TODO: check for buffer overflow.
SkPath path;
sc->getPath(op->glyphID, &path);
size_t pathSize = path.writeToMemory(nullptr);
serializer.push_back<size_t>(pathSize);
auto pathData = serializer.allocateArray<uint8_t>(pathSize);
path.writeToMemory(pathData);
if (sc->getPath(op->glyphID, &path)) {
size_t pathSize = path.writeToMemory(nullptr);
serializer.push_back<size_t>(pathSize);
auto pathData = serializer.allocateArray<uint8_t>(pathSize);
path.writeToMemory(pathData);
}
break;
}
case OpCode::kGlyphMetricsAndImage : {
@ -760,7 +761,7 @@ void SkStrikeClient::generateMetricsAndImage(
}
}
void SkStrikeClient::generatePath(
bool SkStrikeClient::generatePath(
const SkTypefaceProxy& typefaceProxy,
const SkScalerContextRec& rec,
SkGlyphID glyphID,
@ -779,9 +780,13 @@ void SkStrikeClient::generatePath(
fTransport->readVector(&fBuffer);
Deserializer deserializer{fBuffer};
size_t pathSize = *deserializer.read<size_t>();
if (pathSize == 0) {
return false;
}
auto rawPath = deserializer.readArray<uint8_t>(pathSize);
path->readFromMemory(rawPath.data(), rawPath.size());
}
return true;
}
void SkStrikeClient::primeStrikeCache(const SkStrikeCacheDifferenceSpec& strikeDifferences) {

View File

@ -203,7 +203,7 @@ public:
const SkTypefaceProxy&, const SkScalerContextRec&, SkPaint::FontMetrics*);
void generateMetricsAndImage(
const SkTypefaceProxy&, const SkScalerContextRec&, SkArenaAlloc*, SkGlyph*);
void generatePath(
bool generatePath(
const SkTypefaceProxy&, const SkScalerContextRec&, SkGlyphID glyph, SkPath* path);
SkTypeface* lookupTypeface(SkFontID id);

View File

@ -158,10 +158,12 @@ void SkScalerContext::getMetrics(SkGlyph* glyph) {
SK_ERROR:
// draw nothing 'cause we failed
glyph->fLeft = 0;
glyph->fTop = 0;
glyph->fWidth = 0;
glyph->fHeight = 0;
glyph->fLeft = 0;
glyph->fTop = 0;
glyph->fWidth = 0;
glyph->fHeight = 0;
glyph->fLsbDelta = 0;
glyph->fRsbDelta = 0;
// put a valid value here, in case it was earlier set to
// MASK_FORMAT_JUST_ADVANCE
glyph->fMaskFormat = fRec.fMaskFormat;
@ -500,8 +502,8 @@ void SkScalerContext::getImage(const SkGlyph& origGlyph) {
}
}
void SkScalerContext::getPath(SkPackedGlyphID glyphID, SkPath* path) {
this->internalGetPath(glyphID, nullptr, path, nullptr);
bool SkScalerContext::getPath(SkPackedGlyphID glyphID, SkPath* path) {
return this->internalGetPath(glyphID, nullptr, path, nullptr);
}
void SkScalerContext::getFontMetrics(SkPaint::FontMetrics* fm) {
@ -518,8 +520,7 @@ SkUnichar SkScalerContext::generateGlyphToChar(uint16_t glyph) {
bool SkScalerContext::internalGetPath(SkPackedGlyphID glyphID, SkPath* fillPath,
SkPath* devPath, SkMatrix* fillToDevMatrix) {
SkPath path;
generatePath(glyphID.code(), &path);
if (path.isEmpty()) {
if (!generatePath(glyphID.code(), &path)) {
return false;
}
@ -790,7 +791,10 @@ protected:
glyph->zeroMetrics();
}
void generateImage(const SkGlyph& glyph) override {}
void generatePath(SkGlyphID glyph, SkPath* path) override {}
bool generatePath(SkGlyphID glyph, SkPath* path) override {
path->reset();
return false;
}
void generateFontMetrics(SkPaint::FontMetrics* metrics) override {
if (metrics) {
sk_bzero(metrics, sizeof(*metrics));

View File

@ -289,7 +289,7 @@ public:
void getAdvance(SkGlyph*);
void getMetrics(SkGlyph*);
void getImage(const SkGlyph&);
void getPath(SkPackedGlyphID, SkPath*);
bool SK_WARN_UNUSED_RESULT getPath(SkPackedGlyphID, SkPath*);
void getFontMetrics(SkPaint::FontMetrics*);
/** Return the size in bytes of the associated gamma lookup table
@ -377,9 +377,9 @@ protected:
/** Sets the passed path to the glyph outline.
* If this cannot be done the path is set to empty;
* this is indistinguishable from a glyph with an empty path.
* @return false if this glyph does not have any path.
*/
virtual void generatePath(SkGlyphID glyphId, SkPath* path) = 0;
virtual bool SK_WARN_UNUSED_RESULT generatePath(SkGlyphID glyphId, SkPath* path) = 0;
/** Retrieves font metrics. */
virtual void generateFontMetrics(SkPaint::FontMetrics*) = 0;

View File

@ -39,8 +39,8 @@ void SkScalerContextProxy::generateMetrics(SkGlyph* glyph) {
void SkScalerContextProxy::generateImage(const SkGlyph& glyph) {
}
void SkScalerContextProxy::generatePath(SkGlyphID glyphID, SkPath* path) {
fClient->generatePath(*this->typefaceProxy(), this->getRec(), glyphID, path);
bool SkScalerContextProxy::generatePath(SkGlyphID glyphID, SkPath* path) {
return fClient->generatePath(*this->typefaceProxy(), this->getRec(), glyphID, path);
}
void SkScalerContextProxy::generateFontMetrics(SkPaint::FontMetrics* metrics) {

View File

@ -33,7 +33,7 @@ protected:
void generateAdvance(SkGlyph* glyph) override;
void generateMetrics(SkGlyph* glyph) override;
void generateImage(const SkGlyph& glyph) override;
void generatePath(SkGlyphID glyphID, SkPath* path) override;
bool generatePath(SkGlyphID glyphID, SkPath* path) override;
void generateFontMetrics(SkPaint::FontMetrics* metrics) override;
private:

View File

@ -460,7 +460,7 @@ protected:
void generateAdvance(SkGlyph* glyph) override;
void generateMetrics(SkGlyph* glyph) override;
void generateImage(const SkGlyph& glyph) override;
void generatePath(SkGlyphID glyphID, SkPath* path) override;
bool generatePath(SkGlyphID glyphID, SkPath* path) override;
void generateFontMetrics(SkPaint::FontMetrics*) override;
SkUnichar generateGlyphToChar(uint16_t glyph) override;
@ -1232,14 +1232,14 @@ void SkScalerContext_FreeType::generateImage(const SkGlyph& glyph) {
}
void SkScalerContext_FreeType::generatePath(SkGlyphID glyphID, SkPath* path) {
SkAutoMutexAcquire ac(gFTMutex);
bool SkScalerContext_FreeType::generatePath(SkGlyphID glyphID, SkPath* path) {
SkASSERT(path);
SkAutoMutexAcquire ac(gFTMutex);
if (this->setupSize()) {
path->reset();
return;
return false;
}
uint32_t flags = fLoadGlyphFlags;
@ -1247,16 +1247,16 @@ void SkScalerContext_FreeType::generatePath(SkGlyphID glyphID, SkPath* path) {
flags &= ~FT_LOAD_RENDER; // don't scan convert (we just want the outline)
FT_Error err = FT_Load_Glyph(fFace, glyphID, flags);
if (err != 0) {
SK_TRACEFTR(err, "SkScalerContext_FreeType::generatePath: FT_Load_Glyph(glyph:%d "
"flags:%d) failed.", glyphID, flags);
path->reset();
return;
return false;
}
emboldenIfNeeded(fFace, fFace->glyph, glyphID);
generateGlyphPath(fFace, path);
if (!generateGlyphPath(fFace, path)) {
path->reset();
return false;
}
// The path's origin from FreeType is always the horizontal layout origin.
// Offset the path so that it is relative to the vertical origin if needed.
@ -1267,6 +1267,7 @@ void SkScalerContext_FreeType::generatePath(SkGlyphID glyphID, SkPath* path) {
FT_Vector_Transform(&vector, &fMatrix22);
path->offset(SkFDot6ToScalar(vector.x), -SkFDot6ToScalar(vector.y));
}
return true;
}
void SkScalerContext_FreeType::generateFontMetrics(SkPaint::FontMetrics* metrics) {

View File

@ -637,16 +637,14 @@ int line_proc(const FT_Vector* pt, void* ctx) {
return 0;
}
int quad_proc(const FT_Vector* pt0, const FT_Vector* pt1,
void* ctx) {
int quad_proc(const FT_Vector* pt0, const FT_Vector* pt1, void* ctx) {
SkPath* path = (SkPath*)ctx;
path->quadTo(SkFDot6ToScalar(pt0->x), -SkFDot6ToScalar(pt0->y),
SkFDot6ToScalar(pt1->x), -SkFDot6ToScalar(pt1->y));
return 0;
}
int cubic_proc(const FT_Vector* pt0, const FT_Vector* pt1,
const FT_Vector* pt2, void* ctx) {
int cubic_proc(const FT_Vector* pt0, const FT_Vector* pt1, const FT_Vector* pt2, void* ctx) {
SkPath* path = (SkPath*)ctx;
path->cubicTo(SkFDot6ToScalar(pt0->x), -SkFDot6ToScalar(pt0->y),
SkFDot6ToScalar(pt1->x), -SkFDot6ToScalar(pt1->y),
@ -656,7 +654,7 @@ int cubic_proc(const FT_Vector* pt0, const FT_Vector* pt1,
} // namespace
void SkScalerContext_FreeType_Base::generateGlyphPath(FT_Face face, SkPath* path) {
bool SkScalerContext_FreeType_Base::generateGlyphPath(FT_Face face, SkPath* path) {
FT_Outline_Funcs funcs;
funcs.move_to = move_proc;
@ -670,8 +668,9 @@ void SkScalerContext_FreeType_Base::generateGlyphPath(FT_Face face, SkPath* path
if (err != 0) {
path->reset();
return;
return false;
}
path->close();
return true;
}

View File

@ -46,7 +46,7 @@ protected:
{}
void generateGlyphImage(FT_Face face, const SkGlyph& glyph, const SkMatrix& bitmapTransform);
void generateGlyphPath(FT_Face face, SkPath* path);
bool generateGlyphPath(FT_Face face, SkPath* path);
private:
typedef SkScalerContext INHERITED;
};

View File

@ -894,7 +894,7 @@ protected:
void generateAdvance(SkGlyph* glyph) override;
void generateMetrics(SkGlyph* glyph) override;
void generateImage(const SkGlyph& glyph) override;
void generatePath(SkGlyphID glyph, SkPath* path) override;
bool generatePath(SkGlyphID glyph, SkPath* path) override;
void generateFontMetrics(SkPaint::FontMetrics*) override;
private:
@ -1434,7 +1434,7 @@ void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) {
*/
#define kScaleForSubPixelPositionHinting (4.0f)
void SkScalerContext_Mac::generatePath(SkGlyphID glyph, SkPath* path) {
bool SkScalerContext_Mac::generatePath(SkGlyphID glyph, SkPath* path) {
AUTO_CG_LOCK();
SkScalar scaleX = SK_Scalar1;
@ -1473,10 +1473,11 @@ void SkScalerContext_Mac::generatePath(SkGlyphID glyph, SkPath* path) {
UniqueCFRef<CGPathRef> cgPath(CTFontCreatePathForGlyph(fCTFont.get(), cgGlyph, &xform));
path->reset();
if (cgPath != nullptr) {
CGPathApply(cgPath.get(), path, SkScalerContext_Mac::CTPathElement);
if (!cgPath) {
return false;
}
CGPathApply(cgPath.get(), path, SkScalerContext_Mac::CTPathElement);
if (fDoSubPosition) {
SkMatrix m;
m.setScale(SkScalarInvert(scaleX), SkScalarInvert(scaleY));
@ -1487,6 +1488,7 @@ void SkScalerContext_Mac::generatePath(SkGlyphID glyph, SkPath* path) {
getVerticalOffset(cgGlyph, &offset);
path->offset(offset.fX, offset.fY);
}
return true;
}
void SkScalerContext_Mac::generateFontMetrics(SkPaint::FontMetrics* metrics) {

View File

@ -551,7 +551,7 @@ protected:
void generateAdvance(SkGlyph* glyph) override;
void generateMetrics(SkGlyph* glyph) override;
void generateImage(const SkGlyph& glyph) override;
void generatePath(SkGlyphID glyph, SkPath* path) override;
bool generatePath(SkGlyphID glyph, SkPath* path) override;
void generateFontMetrics(SkPaint::FontMetrics*) override;
private:
@ -1614,7 +1614,7 @@ DWORD SkScalerContext_GDI::getGDIGlyphPath(SkGlyphID glyph, UINT flags,
return total_size;
}
void SkScalerContext_GDI::generatePath(SkGlyphID glyph, SkPath* path) {
bool SkScalerContext_GDI::generatePath(SkGlyphID glyph, SkPath* path) {
SkASSERT(path);
SkASSERT(fDDC);
@ -1636,7 +1636,7 @@ void SkScalerContext_GDI::generatePath(SkGlyphID glyph, SkPath* path) {
SkAutoSTMalloc<BUFFERSIZE, uint8_t> glyphbuf(BUFFERSIZE);
DWORD total_size = getGDIGlyphPath(glyph, format, &glyphbuf);
if (0 == total_size) {
return;
return false;
}
if (fRec.getHinting() != SkPaint::kSlight_Hinting) {
@ -1648,7 +1648,7 @@ void SkScalerContext_GDI::generatePath(SkGlyphID glyph, SkPath* path) {
SkAutoSTMalloc<BUFFERSIZE, uint8_t> hintedGlyphbuf(BUFFERSIZE);
DWORD hinted_total_size = getGDIGlyphPath(glyph, format, &hintedGlyphbuf);
if (0 == hinted_total_size) {
return;
return false;
}
if (!sk_path_from_gdi_paths(path, glyphbuf, total_size,
@ -1658,6 +1658,7 @@ void SkScalerContext_GDI::generatePath(SkGlyphID glyph, SkPath* path) {
sk_path_from_gdi_path(path, glyphbuf, total_size);
}
}
return true;
}
static void logfont_for_name(const char* familyName, LOGFONT* lf) {

View File

@ -967,20 +967,20 @@ void SkScalerContext_DW::generateImage(const SkGlyph& glyph) {
}
}
void SkScalerContext_DW::generatePath(SkGlyphID glyph, SkPath* path) {
bool SkScalerContext_DW::generatePath(SkGlyphID glyph, SkPath* path) {
SkASSERT(path);
path->reset();
SkTScopedComPtr<IDWriteGeometrySink> geometryToPath;
HRVM(SkDWriteGeometrySink::Create(path, &geometryToPath),
HRBM(SkDWriteGeometrySink::Create(path, &geometryToPath),
"Could not create geometry to path converter.");
UINT16 glyphId = SkTo<UINT16>(glyph);
{
SkAutoExclusive l(DWriteFactoryMutex);
//TODO: convert to<->from DIUs? This would make a difference if hinting.
//It may not be needed, it appears that DirectWrite only hints at em size.
HRVM(this->getDWriteTypeface()->fDWriteFontFace->GetGlyphRunOutline(
HRBM(this->getDWriteTypeface()->fDWriteFontFace->GetGlyphRunOutline(
SkScalarToFloat(fTextSizeRender),
&glyphId,
nullptr, //advances
@ -993,6 +993,7 @@ void SkScalerContext_DW::generatePath(SkGlyphID glyph, SkPath* path) {
}
path->transform(fSkXform);
return true;
}
#endif//defined(SK_BUILD_FOR_WIN)

View File

@ -32,7 +32,7 @@ protected:
void generateAdvance(SkGlyph* glyph) override;
void generateMetrics(SkGlyph* glyph) override;
void generateImage(const SkGlyph& glyph) override;
void generatePath(SkGlyphID glyph, SkPath* path) override;
bool generatePath(SkGlyphID glyph, SkPath* path) override;
void generateFontMetrics(SkPaint::FontMetrics*) override;
private:

View File

@ -26,7 +26,7 @@ protected:
void generateAdvance(SkGlyph*) override;
void generateMetrics(SkGlyph*) override;
void generateImage(const SkGlyph&) override;
void generatePath(SkGlyphID, SkPath*) override;
bool generatePath(SkGlyphID, SkPath*) override;
void generateFontMetrics(SkPaint::FontMetrics*) override;
private:
@ -85,7 +85,7 @@ void SkRandomScalerContext::generateMetrics(SkGlyph* glyph) {
}
if (SkMask::kARGB32_Format == format) {
SkPath path;
fProxy->getPath(glyph->getPackedID(), &path);
sk_ignore_unused_variable(fProxy->getPath(glyph->getPackedID(), &path));
SkRect storage;
const SkPaint& paint = this->getRandomTypeface()->paint();
@ -155,7 +155,7 @@ void SkRandomScalerContext::generateImage(const SkGlyph& glyph) {
if (!fFakeIt) {
if (SkMask::kARGB32_Format == glyph.fMaskFormat) {
SkPath path;
fProxy->getPath(glyph.getPackedID(), &path);
sk_ignore_unused_variable(fProxy->getPath(glyph.getPackedID(), &path));
SkBitmap bm;
bm.installPixels(SkImageInfo::MakeN32Premul(glyph.fWidth, glyph.fHeight),
@ -176,8 +176,8 @@ void SkRandomScalerContext::generateImage(const SkGlyph& glyph) {
}
}
void SkRandomScalerContext::generatePath(SkGlyphID glyph, SkPath* path) {
fProxy->generatePath(glyph, path);
bool SkRandomScalerContext::generatePath(SkGlyphID glyph, SkPath* path) {
return fProxy->generatePath(glyph, path);
}
void SkRandomScalerContext::generateFontMetrics(SkPaint::FontMetrics* metrics) {

View File

@ -96,10 +96,6 @@ void SkTestSVGTypeface::getFontMetrics(SkPaint::FontMetrics* metrics) const {
*metrics = fFontMetrics;
}
void SkTestSVGTypeface::getPath(SkGlyphID glyphID, SkPath* path) const {
path->reset();
}
void SkTestSVGTypeface::onFilterRec(SkScalerContextRec* rec) const {
rec->setHinting(SkPaint::kNo_Hinting);
}
@ -244,9 +240,9 @@ protected:
}
}
void generatePath(SkGlyphID glyph, SkPath* path) override {
this->geTestSVGTypeface()->getPath(glyph, path);
path->transform(fMatrix);
bool generatePath(SkGlyphID glyph, SkPath* path) override {
path->reset();
return false;
}
void generateFontMetrics(SkPaint::FontMetrics* metrics) override {

View File

@ -53,7 +53,6 @@ public:
~SkTestSVGTypeface() override;
void getAdvance(SkGlyph* glyph) const;
void getFontMetrics(SkPaint::FontMetrics* metrics) const;
void getPath(SkGlyphID glyph, SkPath* path) const;
static sk_sp<SkTestSVGTypeface> Default();
void exportTtxCbdt(SkWStream*) const;

View File

@ -214,9 +214,10 @@ protected:
SK_ABORT("Should have generated from path.");
}
void generatePath(SkGlyphID glyph, SkPath* path) override {
bool generatePath(SkGlyphID glyph, SkPath* path) override {
this->getTestTypeface()->getPath(glyph, path);
path->transform(fMatrix);
return true;
}
void generateFontMetrics(SkPaint::FontMetrics* metrics) override {