diff options
-rw-r--r-- | include/core/SkTypeface.h | 5 | ||||
-rw-r--r-- | src/core/SkAdvancedTypefaceMetrics.h | 10 | ||||
-rw-r--r-- | src/core/SkTypeface.cpp | 4 | ||||
-rw-r--r-- | src/core/SkTypeface_remote.h | 4 | ||||
-rw-r--r-- | src/pdf/SkPDFCanon.h | 1 | ||||
-rw-r--r-- | src/pdf/SkPDFDevice.cpp | 8 | ||||
-rw-r--r-- | src/pdf/SkPDFFont.cpp | 47 | ||||
-rw-r--r-- | src/pdf/SkPDFFont.h | 3 | ||||
-rw-r--r-- | src/pdf/SkPDFMakeToUnicodeCmap.cpp | 10 | ||||
-rw-r--r-- | src/pdf/SkPDFMakeToUnicodeCmap.h | 4 | ||||
-rw-r--r-- | src/ports/SkFontHost_FreeType.cpp | 42 | ||||
-rw-r--r-- | src/ports/SkFontHost_FreeType_common.h | 1 | ||||
-rw-r--r-- | src/ports/SkFontHost_mac.cpp | 26 | ||||
-rw-r--r-- | src/ports/SkFontHost_win.cpp | 30 | ||||
-rw-r--r-- | src/ports/SkTypeface_win_dw.cpp | 30 | ||||
-rw-r--r-- | src/ports/SkTypeface_win_dw.h | 1 | ||||
-rw-r--r-- | tests/PDFGlyphsToUnicodeTest.cpp | 18 | ||||
-rw-r--r-- | tests/TypefaceTest.cpp | 10 | ||||
-rw-r--r-- | tools/fonts/SkRandomScalerContext.cpp | 4 | ||||
-rw-r--r-- | tools/fonts/SkRandomScalerContext.h | 1 | ||||
-rw-r--r-- | tools/fonts/SkTestSVGTypeface.cpp | 16 | ||||
-rw-r--r-- | tools/fonts/SkTestSVGTypeface.h | 1 | ||||
-rw-r--r-- | tools/fonts/SkTestTypeface.cpp | 15 | ||||
-rw-r--r-- | tools/fonts/SkTestTypeface.h | 1 |
24 files changed, 162 insertions, 130 deletions
diff --git a/include/core/SkTypeface.h b/include/core/SkTypeface.h index 37878cc390..665491c3db 100644 --- a/include/core/SkTypeface.h +++ b/include/core/SkTypeface.h @@ -318,6 +318,11 @@ protected: // Backends that do not suport type1 fonts should not override. virtual void getPostScriptGlyphNames(SkString*) const {} + // The mapping from glyph to Unicode; array indices are glyph ids. + // For each glyph, give the default Unicode value, if it exists. + // dstArray is non-null, and points to an array of size this->countGlyphs(). + virtual void getGlyphToUnicodeMap(SkUnichar* dstArray) const; + virtual SkStreamAsset* onOpenStream(int* ttcIndex) const = 0; // TODO: make pure virtual. virtual std::unique_ptr<SkFontData> onMakeFontData() const; diff --git a/src/core/SkAdvancedTypefaceMetrics.h b/src/core/SkAdvancedTypefaceMetrics.h index 6be3d443bf..e9af831422 100644 --- a/src/core/SkAdvancedTypefaceMetrics.h +++ b/src/core/SkAdvancedTypefaceMetrics.h @@ -10,9 +10,7 @@ #include "SkBitmaskEnum.h" #include "SkRect.h" -#include "SkRefCnt.h" #include "SkString.h" -#include "SkTDArray.h" /** \class SkAdvancedTypefaceMetrics @@ -21,11 +19,6 @@ SkTypeface::getAdvancedMetrics. */ struct SkAdvancedTypefaceMetrics { - SkAdvancedTypefaceMetrics() {} - SkAdvancedTypefaceMetrics(const SkAdvancedTypefaceMetrics&) = delete; - SkAdvancedTypefaceMetrics& operator=(const SkAdvancedTypefaceMetrics&) = delete; - ~SkAdvancedTypefaceMetrics() {} - // The PostScript name of the font. See `FontName` and `BaseFont` in PDF standard. SkString fPostScriptName; SkString fFontName; @@ -70,9 +63,6 @@ struct SkAdvancedTypefaceMetrics { int16_t fCapHeight = 0; // Height (from baseline) of top of flat capitals. SkIRect fBBox = {0, 0, 0, 0}; // The bounding box of all glyphs (in font units). - - // The mapping from glyph to Unicode; array indices are glyph ids. - SkTDArray<SkUnichar> fGlyphToUnicode; }; namespace skstd { diff --git a/src/core/SkTypeface.cpp b/src/core/SkTypeface.cpp index c6337d7852..92c8c09e33 100644 --- a/src/core/SkTypeface.cpp +++ b/src/core/SkTypeface.cpp @@ -291,6 +291,10 @@ void SkTypeface::getFamilyName(SkString* name) const { this->onGetFamilyName(name); } +void SkTypeface::getGlyphToUnicodeMap(SkUnichar* dst) const { + sk_bzero(dst, sizeof(SkUnichar) * this->countGlyphs()); +} + std::unique_ptr<SkAdvancedTypefaceMetrics> SkTypeface::getAdvancedMetrics() const { std::unique_ptr<SkAdvancedTypefaceMetrics> result = this->onGetAdvancedMetrics(); if (result && result->fPostScriptName.isEmpty()) { diff --git a/src/core/SkTypeface_remote.h b/src/core/SkTypeface_remote.h index 691b124049..ad729aded3 100644 --- a/src/core/SkTypeface_remote.h +++ b/src/core/SkTypeface_remote.h @@ -111,6 +111,10 @@ protected: void onGetFontDescriptor(SkFontDescriptor*, bool*) const override { SK_ABORT("Should never be called."); } + void getGlyphToUnicodeMap(SkUnichar*) const override { + SK_ABORT("Should never be called."); + } + std::unique_ptr<SkAdvancedTypefaceMetrics> onGetAdvancedMetrics() const override { SK_ABORT("Should never be called."); return nullptr; diff --git a/src/pdf/SkPDFCanon.h b/src/pdf/SkPDFCanon.h index 8d0e8f8fed..8e97db05f5 100644 --- a/src/pdf/SkPDFCanon.h +++ b/src/pdf/SkPDFCanon.h @@ -42,6 +42,7 @@ public: SkTHashMap<uint32_t, std::unique_ptr<SkAdvancedTypefaceMetrics>> fTypefaceMetrics; SkTHashMap<uint32_t, std::vector<SkString>> fType1GlyphNames; + SkTHashMap<uint32_t, std::vector<SkUnichar>> fToUnicodeMap; SkTHashMap<uint32_t, sk_sp<SkPDFDict>> fFontDescriptors; SkTHashMap<uint64_t, sk_sp<SkPDFFont>> fFontMap; diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp index 6e36fb3d82..c18219ab0d 100644 --- a/src/pdf/SkPDFDevice.cpp +++ b/src/pdf/SkPDFDevice.cpp @@ -1052,8 +1052,8 @@ private: }; } // namespace -static SkUnichar map_glyph(const SkTDArray<SkUnichar>& glyphToUnicode, SkGlyphID glyph) { - return SkToInt(glyph) < glyphToUnicode.count() ? glyphToUnicode[SkToInt(glyph)] : -1; +static SkUnichar map_glyph(const std::vector<SkUnichar>& glyphToUnicode, SkGlyphID glyph) { + return glyph < glyphToUnicode.size() ? glyphToUnicode[SkToInt(glyph)] : -1; } static void update_font(SkWStream* wStream, int fontIndex, SkScalar textSize) { @@ -1200,6 +1200,9 @@ void SkPDFDevice::internalDrawText( if (!metrics) { return; } + const std::vector<SkUnichar>& glyphToUnicode = SkPDFFont::GetUnicodeMap( + typeface, fDocument->canon()); + SkClusterator clusterator(sourceText, sourceByteCount, paint, clusters, textByteLength, utf8Text); const SkGlyphID* glyphs = clusterator.glyphs(); @@ -1244,7 +1247,6 @@ void SkPDFDevice::internalDrawText( return; } SkDynamicMemoryWStream* out = content.stream(); - const SkTDArray<SkUnichar>& glyphToUnicode = metrics->fGlyphToUnicode; out->writeText("BT\n"); SK_AT_SCOPE_EXIT(out->writeText("ET\n")); diff --git a/src/pdf/SkPDFFont.cpp b/src/pdf/SkPDFFont.cpp index 9ba411495a..3b89f62cbe 100644 --- a/src/pdf/SkPDFFont.cpp +++ b/src/pdf/SkPDFFont.cpp @@ -186,6 +186,19 @@ const SkAdvancedTypefaceMetrics* SkPDFFont::GetMetrics(SkTypeface* typeface, return canon->fTypefaceMetrics.set(id, std::move(metrics))->get(); } +const std::vector<SkUnichar>& SkPDFFont::GetUnicodeMap(const SkTypeface* typeface, + SkPDFCanon* canon) { + SkASSERT(typeface); + SkASSERT(canon); + SkFontID id = typeface->uniqueID(); + if (std::vector<SkUnichar>* ptr = canon->fToUnicodeMap.find(id)) { + return *ptr; + } + std::vector<SkUnichar> buffer(typeface->countGlyphs()); + typeface->getGlyphToUnicodeMap(buffer.data()); + return *canon->fToUnicodeMap.set(id, std::move(buffer)); +} + SkAdvancedTypefaceMetrics::FontType SkPDFFont::FontType(const SkAdvancedTypefaceMetrics& metrics) { if (SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kMultiMaster_FontFlag) || SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag)) { @@ -477,14 +490,15 @@ void SkPDFType0Font::getFontSubset(SkPDFCanon* canon) { descendantFonts->appendObjRef(std::move(newCIDFont)); this->insertObject("DescendantFonts", std::move(descendantFonts)); - if (metrics.fGlyphToUnicode.count() > 0) { - this->insertObjRef("ToUnicode", - SkPDFMakeToUnicodeCmap(metrics.fGlyphToUnicode, - &this->glyphUsage(), - multiByteGlyphs(), - firstGlyphID(), - lastGlyphID())); - } + const std::vector<SkUnichar>& glyphToUnicode = + SkPDFFont::GetUnicodeMap(this->typeface(), canon); + SkASSERT(SkToSizeT(this->typeface()->countGlyphs()) == glyphToUnicode.size()); + this->insertObjRef("ToUnicode", + SkPDFMakeToUnicodeCmap(glyphToUnicode.data(), + &this->glyphUsage(), + this->multiByteGlyphs(), + this->firstGlyphID(), + this->lastGlyphID())); SkDEBUGCODE(fPopulated = true); return; } @@ -722,14 +736,15 @@ static void add_type3_font_info(SkPDFCanon* canon, fontBBox->appendInt(bbox.top()); font->insertObject("FontBBox", std::move(fontBBox)); font->insertName("CIDToGIDMap", "Identity"); - if (metrics && metrics->fGlyphToUnicode.count() > 0) { - font->insertObjRef("ToUnicode", - SkPDFMakeToUnicodeCmap(metrics->fGlyphToUnicode, - &subset, - false, - firstGlyphID, - lastGlyphID)); - } + + const std::vector<SkUnichar>& glyphToUnicode = SkPDFFont::GetUnicodeMap(typeface, canon); + SkASSERT(glyphToUnicode.size() == SkToSizeT(typeface->countGlyphs())); + font->insertObjRef("ToUnicode", + SkPDFMakeToUnicodeCmap(glyphToUnicode.data(), + &subset, + false, + firstGlyphID, + lastGlyphID)); auto descriptor = sk_make_sp<SkPDFDict>("FontDescriptor"); int32_t fontDescriptorFlags = kPdfSymbolic; if (metrics) { diff --git a/src/pdf/SkPDFFont.h b/src/pdf/SkPDFFont.h index 9dc4655501..1441eedad9 100644 --- a/src/pdf/SkPDFFont.h +++ b/src/pdf/SkPDFFont.h @@ -95,6 +95,9 @@ public: static const SkAdvancedTypefaceMetrics* GetMetrics(SkTypeface* typeface, SkPDFCanon* canon); + static const std::vector<SkUnichar>& GetUnicodeMap(const SkTypeface* typeface, + SkPDFCanon* canon); + /** Subset the font based on current usage. * Must be called before emitObject(). */ diff --git a/src/pdf/SkPDFMakeToUnicodeCmap.cpp b/src/pdf/SkPDFMakeToUnicodeCmap.cpp index afe773207d..c93aa6f2c5 100644 --- a/src/pdf/SkPDFMakeToUnicodeCmap.cpp +++ b/src/pdf/SkPDFMakeToUnicodeCmap.cpp @@ -147,15 +147,12 @@ static void append_bfrange_section(const SkTDArray<BFRange>& bfrange, // For the worst case (having 65536 continuous unicode and we use every other // one of them), the possible savings by aggressive optimization is 416KB // pre-compressed and does not provide enough motivation for implementation. -void SkPDFAppendCmapSections(const SkTDArray<SkUnichar>& glyphToUnicode, +void SkPDFAppendCmapSections(const SkUnichar* glyphToUnicode, const SkBitSet* subset, SkDynamicMemoryWStream* cmap, bool multiByteGlyphs, SkGlyphID firstGlyphID, SkGlyphID lastGlyphID) { - if (glyphToUnicode.isEmpty()) { - return; - } int glyphOffset = 0; if (!multiByteGlyphs) { glyphOffset = firstGlyphID - 1; @@ -166,8 +163,7 @@ void SkPDFAppendCmapSections(const SkTDArray<SkUnichar>& glyphToUnicode, BFRange currentRangeEntry = {0, 0, 0}; bool rangeEmpty = true; - const int limit = - SkMin32(lastGlyphID + 1, glyphToUnicode.count()) - glyphOffset; + const int limit = (int)lastGlyphID + 1 - glyphOffset; for (int i = firstGlyphID - glyphOffset; i < limit + 1; ++i) { bool inSubset = i < limit && @@ -210,7 +206,7 @@ void SkPDFAppendCmapSections(const SkTDArray<SkUnichar>& glyphToUnicode, } sk_sp<SkPDFStream> SkPDFMakeToUnicodeCmap( - const SkTDArray<SkUnichar>& glyphToUnicode, + const SkUnichar* glyphToUnicode, const SkBitSet* subset, bool multiByteGlyphs, SkGlyphID firstGlyphID, diff --git a/src/pdf/SkPDFMakeToUnicodeCmap.h b/src/pdf/SkPDFMakeToUnicodeCmap.h index 0c4d1c37dd..656af913d0 100644 --- a/src/pdf/SkPDFMakeToUnicodeCmap.h +++ b/src/pdf/SkPDFMakeToUnicodeCmap.h @@ -12,14 +12,14 @@ #include "SkStream.h" sk_sp<SkPDFStream> SkPDFMakeToUnicodeCmap( - const SkTDArray<SkUnichar>& glyphToUnicode, + const SkUnichar* glyphToUnicode, const SkBitSet* subset, bool multiByteGlyphs, SkGlyphID firstGlyphID, SkGlyphID lastGlyphID); // Exposed for unit testing. -void SkPDFAppendCmapSections(const SkTDArray<SkUnichar>& glyphToUnicode, +void SkPDFAppendCmapSections(const SkUnichar* glyphToUnicode, const SkBitSet* subset, SkDynamicMemoryWStream* cmap, bool multiByteGlyphs, diff --git a/src/ports/SkFontHost_FreeType.cpp b/src/ports/SkFontHost_FreeType.cpp index f1c1b555f2..3e8e9576dd 100644 --- a/src/ports/SkFontHost_FreeType.cpp +++ b/src/ports/SkFontHost_FreeType.cpp @@ -511,23 +511,6 @@ static bool canSubset(FT_Face face) { return (fsType & FT_FSTYPE_NO_SUBSETTING) == 0; } -static void populate_glyph_to_unicode(FT_Face& face, SkTDArray<SkUnichar>* glyphToUnicode) { - FT_Long numGlyphs = face->num_glyphs; - glyphToUnicode->setCount(SkToInt(numGlyphs)); - sk_bzero(glyphToUnicode->begin(), sizeof((*glyphToUnicode)[0]) * numGlyphs); - - FT_UInt glyphIndex; - SkUnichar charCode = FT_Get_First_Char(face, &glyphIndex); - while (glyphIndex) { - SkASSERT(glyphIndex < SkToUInt(numGlyphs)); - // Use the first character that maps to this glyphID. https://crbug.com/359065 - if (0 == (*glyphToUnicode)[glyphIndex]) { - (*glyphToUnicode)[glyphIndex] = charCode; - } - charCode = FT_Get_Next_Char(face, charCode, &glyphIndex); - } -} - static SkAdvancedTypefaceMetrics::FontType get_font_type(FT_Face face) { const char* fontType = FT_Get_X11_Font_Format(face); static struct { const char* s; SkAdvancedTypefaceMetrics::FontType t; } values[] = { @@ -602,17 +585,26 @@ std::unique_ptr<SkAdvancedTypefaceMetrics> SkTypeface_FreeType::onGetAdvancedMet } info->fBBox = SkIRect::MakeLTRB(face->bbox.xMin, face->bbox.yMax, face->bbox.xMax, face->bbox.yMin); + return info; +} - bool perGlyphInfo = FT_IS_SCALABLE(face); +void SkTypeface_FreeType::getGlyphToUnicodeMap(SkUnichar* dstArray) const { + SkASSERT(dstArray); + AutoFTAccess fta(this); + FT_Face face = fta.face(); + FT_Long numGlyphs = face->num_glyphs; + sk_bzero(dstArray, sizeof(SkUnichar) * numGlyphs); - if (perGlyphInfo && - info->fType != SkAdvancedTypefaceMetrics::kType1_Font && - face->num_charmaps) - { - populate_glyph_to_unicode(face, &(info->fGlyphToUnicode)); + FT_UInt glyphIndex; + SkUnichar charCode = FT_Get_First_Char(face, &glyphIndex); + while (glyphIndex) { + SkASSERT(glyphIndex < SkToUInt(numGlyphs)); + // Use the first character that maps to this glyphID. https://crbug.com/359065 + if (0 == dstArray[glyphIndex]) { + dstArray[glyphIndex] = charCode; + } + charCode = FT_Get_Next_Char(face, charCode, &glyphIndex); } - - return info; } void SkTypeface_FreeType::getPostScriptGlyphNames(SkString* dstArray) const { diff --git a/src/ports/SkFontHost_FreeType_common.h b/src/ports/SkFontHost_FreeType_common.h index 3aabdde250..eacce04ca1 100644 --- a/src/ports/SkFontHost_FreeType_common.h +++ b/src/ports/SkFontHost_FreeType_common.h @@ -91,6 +91,7 @@ protected: virtual SkScalerContext* onCreateScalerContext(const SkScalerContextEffects&, const SkDescriptor*) const override; void onFilterRec(SkScalerContextRec*) const override; + void getGlyphToUnicodeMap(SkUnichar*) const override; std::unique_ptr<SkAdvancedTypefaceMetrics> onGetAdvancedMetrics() const override; void getPostScriptGlyphNames(SkString* dstArray) const override; int onGetUPEM() const override; diff --git a/src/ports/SkFontHost_mac.cpp b/src/ports/SkFontHost_mac.cpp index 8047c4352f..3cc51d43f6 100644 --- a/src/ports/SkFontHost_mac.cpp +++ b/src/ports/SkFontHost_mac.cpp @@ -719,6 +719,7 @@ protected: const SkDescriptor*) const override; void onFilterRec(SkScalerContextRec*) const override; void onGetFontDescriptor(SkFontDescriptor*, bool*) const override; + void getGlyphToUnicodeMap(SkUnichar*) const override; std::unique_ptr<SkAdvancedTypefaceMetrics> onGetAdvancedMetrics() const override; int onCharsToGlyphs(const void* chars, Encoding, uint16_t glyphs[], int glyphCount) const override; @@ -1605,9 +1606,7 @@ static sk_sp<SkTypeface> create_from_dataProvider(UniqueCFRef<CGDataProviderRef> // Iterate through the font in this case. The existing caller caches the result, // so the performance impact isn't too bad. static void populate_glyph_to_unicode_slow(CTFontRef ctFont, CFIndex glyphCount, - SkTDArray<SkUnichar>* glyphToUnicode) { - glyphToUnicode->setCount(SkToInt(glyphCount)); - SkUnichar* out = glyphToUnicode->begin(); + SkUnichar* out) { sk_bzero(out, glyphCount * sizeof(SkUnichar)); UniChar unichar = 0; while (glyphCount > 0) { @@ -1628,7 +1627,8 @@ static void populate_glyph_to_unicode_slow(CTFontRef ctFont, CFIndex glyphCount, // Unicode code points that require conjugate pairs in utf16 are not // supported. static void populate_glyph_to_unicode(CTFontRef ctFont, CFIndex glyphCount, - SkTDArray<SkUnichar>* glyphToUnicode) { + SkUnichar* glyphToUnicode) { + sk_bzero(glyphToUnicode, sizeof(SkUnichar) * glyphCount); UniqueCFRef<CFCharacterSetRef> charSet(CTFontCopyCharacterSet(ctFont)); if (!charSet) { populate_glyph_to_unicode_slow(ctFont, glyphCount, glyphToUnicode); @@ -1651,9 +1651,7 @@ static void populate_glyph_to_unicode(CTFontRef ctFont, CFIndex glyphCount, length = 8192; } const UInt8* bits = CFDataGetBytePtr(bitmap.get()); - glyphToUnicode->setCount(SkToInt(glyphCount)); - SkUnichar* out = glyphToUnicode->begin(); - sk_bzero(out, glyphCount * sizeof(SkUnichar)); + sk_bzero(glyphToUnicode, glyphCount * sizeof(SkUnichar)); for (int i = 0; i < length; i++) { int mask = bits[i]; if (!mask) { @@ -1663,7 +1661,7 @@ static void populate_glyph_to_unicode(CTFontRef ctFont, CFIndex glyphCount, CGGlyph glyph; UniChar unichar = static_cast<UniChar>((i << 3) + j); if (mask & (1 << j) && CTFontGetGlyphsForCharacters(ctFont, &unichar, &glyph, 1)) { - out[glyph] = unichar; + glyphToUnicode[glyph] = unichar; } } } @@ -1681,6 +1679,14 @@ static void CFStringToSkString(CFStringRef src, SkString* dst) { dst->resize(strlen(dst->c_str())); } +void SkTypeface_Mac::getGlyphToUnicodeMap(SkUnichar* dstArray) const { + AUTO_CG_LOCK(); + UniqueCFRef<CTFontRef> ctFont = + ctfont_create_exact_copy(fFontRef.get(), CTFontGetUnitsPerEm(fFontRef.get()), nullptr); + CFIndex glyphCount = CTFontGetGlyphCount(ctFont.get()); + populate_glyph_to_unicode(ctFont.get(), glyphCount, dstArray); +} + std::unique_ptr<SkAdvancedTypefaceMetrics> SkTypeface_Mac::onGetAdvancedMetrics() const { AUTO_CG_LOCK(); @@ -1710,10 +1716,6 @@ std::unique_ptr<SkAdvancedTypefaceMetrics> SkTypeface_Mac::onGetAdvancedMetrics( } } - CFIndex glyphCount = CTFontGetGlyphCount(ctFont.get()); - - populate_glyph_to_unicode(ctFont.get(), glyphCount, &info->fGlyphToUnicode); - SkOTTableOS2_V4::Type fsType; if (sizeof(fsType) == this->getTableData(SkTEndian_SwapBE32(SkOTTableOS2::TAG), offsetof(SkOTTableOS2_V4, fsType), diff --git a/src/ports/SkFontHost_win.cpp b/src/ports/SkFontHost_win.cpp index 35a0a74b22..f1da8053f2 100644 --- a/src/ports/SkFontHost_win.cpp +++ b/src/ports/SkFontHost_win.cpp @@ -261,6 +261,7 @@ protected: SkScalerContext* onCreateScalerContext(const SkScalerContextEffects&, const SkDescriptor*) const override; void onFilterRec(SkScalerContextRec*) const override; + void getGlyphToUnicodeMap(SkUnichar*) const override; std::unique_ptr<SkAdvancedTypefaceMetrics> onGetAdvancedMetrics() const override; void onGetFontDescriptor(SkFontDescriptor*, bool*) const override; int onCharsToGlyphs(const void* chars, Encoding encoding, @@ -362,7 +363,8 @@ void SkLOGFONTFromTypeface(const SkTypeface* face, LOGFONT* lf) { // require parsing the TTF cmap table (platform 4, encoding 12) directly instead // of calling GetFontUnicodeRange(). static void populate_glyph_to_unicode(HDC fontHdc, const unsigned glyphCount, - SkTDArray<SkUnichar>* glyphToUnicode) { + SkUnichar* glyphToUnicode) { + sk_bzero(glyphToUnicode, sizeof(SkUnichar) * glyphCount); DWORD glyphSetBufferSize = GetFontUnicodeRanges(fontHdc, nullptr); if (!glyphSetBufferSize) { return; @@ -375,8 +377,6 @@ static void populate_glyph_to_unicode(HDC fontHdc, const unsigned glyphCount, return; } - glyphToUnicode->setCount(glyphCount); - memset(glyphToUnicode->begin(), 0, glyphCount * sizeof(SkUnichar)); for (DWORD i = 0; i < glyphSet->cRanges; ++i) { // There is no guarantee that within a Unicode range, the corresponding // glyph id in a font file are continuous. So, even if we have ranges, @@ -399,9 +399,8 @@ static void populate_glyph_to_unicode(HDC fontHdc, const unsigned glyphCount, // unlikely to have collisions since glyph reuse happens mostly for // different Unicode pages. for (USHORT j = 0; j < count; ++j) { - if (glyph[j] != 0xffff && glyph[j] < glyphCount && - (*glyphToUnicode)[glyph[j]] == 0) { - (*glyphToUnicode)[glyph[j]] = chars[j]; + if (glyph[j] != 0xFFFF && glyph[j] < glyphCount && glyphToUnicode[glyph[j]] == 0) { + glyphToUnicode[glyph[j]] = chars[j]; } } } @@ -1707,6 +1706,23 @@ void LogFontTypeface::onGetFontDescriptor(SkFontDescriptor* desc, *isLocalStream = this->fSerializeAsStream; } +void LogFontTypeface::getGlyphToUnicodeMap(SkUnichar* dstArray) const { + HDC hdc = ::CreateCompatibleDC(nullptr); + HFONT font = CreateFontIndirect(&fLogFont); + HFONT savefont = (HFONT)SelectObject(hdc, font); + LOGFONT lf = fLogFont; + HFONT designFont = CreateFontIndirect(&lf); + SelectObject(hdc, designFont); + + unsigned int glyphCount = calculateGlyphCount(hdc, fLogFont); + populate_glyph_to_unicode(hdc, glyphCount, dstArray); + + SelectObject(hdc, savefont); + DeleteObject(designFont); + DeleteObject(font); + DeleteDC(hdc); +} + std::unique_ptr<SkAdvancedTypefaceMetrics> LogFontTypeface::onGetAdvancedMetrics() const { LOGFONT lf = fLogFont; std::unique_ptr<SkAdvancedTypefaceMetrics> info(nullptr); @@ -1757,8 +1773,6 @@ std::unique_ptr<SkAdvancedTypefaceMetrics> LogFontTypeface::onGetAdvancedMetrics } } - populate_glyph_to_unicode(hdc, glyphCount, &(info->fGlyphToUnicode)); - if (glyphCount > 0 && (otm.otmTextMetrics.tmPitchAndFamily & TMPF_TRUETYPE)) { info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font; diff --git a/src/ports/SkTypeface_win_dw.cpp b/src/ports/SkTypeface_win_dw.cpp index 69bf7ff034..38e68dccca 100644 --- a/src/ports/SkTypeface_win_dw.cpp +++ b/src/ports/SkTypeface_win_dw.cpp @@ -288,42 +288,31 @@ void DWriteFontTypeface::onFilterRec(SkScalerContextRec* rec) const { /////////////////////////////////////////////////////////////////////////////// //PDF Support -// Construct Glyph to Unicode table. -// Unicode code points that require conjugate pairs in utf16 are not -// supported. -// TODO(bungeman): This never does what anyone wants. -// What is really wanted is the text to glyphs mapping -static void populate_glyph_to_unicode(IDWriteFontFace* fontFace, - const unsigned glyphCount, - SkTDArray<SkUnichar>* glyphToUnicode) { - //Do this like free type instead - SkAutoTMalloc<SkUnichar> glyphToUni( - (SkUnichar*)sk_calloc_throw(sizeof(SkUnichar) * glyphCount)); +void DWriteFontTypeface::getGlyphToUnicodeMap(SkUnichar* glyphToUnicode) const { + unsigned glyphCount = fDWriteFontFace->GetGlyphCount(); + sk_bzero(glyphToUnicode, sizeof(SkUnichar) * glyphCount); + IDWriteFontFace* fontFace = fDWriteFontFace.get(); int maxGlyph = -1; unsigned remainingGlyphCount = glyphCount; for (UINT32 c = 0; c < 0x10FFFF && remainingGlyphCount != 0; ++c) { UINT16 glyph = 0; - HRVM(fontFace->GetGlyphIndices(&c, 1, &glyph), - "Failed to get glyph index."); + HRVM(fontFace->GetGlyphIndices(&c, 1, &glyph), "Failed to get glyph index."); // Intermittent DW bug on Windows 10. See crbug.com/470146. if (glyph >= glyphCount) { - return; + return; } - if (0 < glyph && glyphToUni[glyph] == 0) { + if (0 < glyph && glyphToUnicode[glyph] == 0) { maxGlyph = SkTMax(static_cast<int>(glyph), maxGlyph); - glyphToUni[glyph] = c; // Always use lowest-index unichar. + glyphToUnicode[glyph] = c; // Always use lowest-index unichar. --remainingGlyphCount; } } - SkTDArray<SkUnichar>(glyphToUni, maxGlyph + 1).swap(*glyphToUnicode); } std::unique_ptr<SkAdvancedTypefaceMetrics> DWriteFontTypeface::onGetAdvancedMetrics() const { std::unique_ptr<SkAdvancedTypefaceMetrics> info(nullptr); - const unsigned glyphCount = fDWriteFontFace->GetGlyphCount(); - DWRITE_FONT_METRICS dwfm; fDWriteFontFace->GetMetrics(&dwfm); @@ -358,9 +347,6 @@ std::unique_ptr<SkAdvancedTypefaceMetrics> DWriteFontTypeface::onGetAdvancedMetr info->fPostScriptName = info->fFontName; } - - populate_glyph_to_unicode(fDWriteFontFace.get(), glyphCount, &(info->fGlyphToUnicode)); - DWRITE_FONT_FACE_TYPE fontType = fDWriteFontFace->GetType(); if (fontType != DWRITE_FONT_FACE_TYPE_TRUETYPE && fontType != DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION) diff --git a/src/ports/SkTypeface_win_dw.h b/src/ports/SkTypeface_win_dw.h index 7abbde55aa..75be040fd4 100644 --- a/src/ports/SkTypeface_win_dw.h +++ b/src/ports/SkTypeface_win_dw.h @@ -104,6 +104,7 @@ protected: SkScalerContext* onCreateScalerContext(const SkScalerContextEffects&, const SkDescriptor*) const override; void onFilterRec(SkScalerContextRec*) const override; + void getGlyphToUnicodeMap(SkUnichar* glyphToUnicode) const override; std::unique_ptr<SkAdvancedTypefaceMetrics> onGetAdvancedMetrics() const override; void onGetFontDescriptor(SkFontDescriptor*, bool*) const override; int onCharsToGlyphs(const void* chars, Encoding encoding, diff --git a/tests/PDFGlyphsToUnicodeTest.cpp b/tests/PDFGlyphsToUnicodeTest.cpp index 332520bfb0..2aeedf0330 100644 --- a/tests/PDFGlyphsToUnicodeTest.cpp +++ b/tests/PDFGlyphsToUnicodeTest.cpp @@ -74,9 +74,12 @@ DEF_TEST(SkPDF_ToUnicode, reporter) { glyphsInSubset.push(0x101); glyphToUnicode.push(0x1013); + SkGlyphID lastGlyphID = SkToU16(glyphToUnicode.count() - 1); + SkDynamicMemoryWStream buffer; subset.setAll(glyphsInSubset.begin(), glyphsInSubset.count()); - SkPDFAppendCmapSections(glyphToUnicode, &subset, &buffer, true, 0, 0xFFFF); + SkPDFAppendCmapSections(&glyphToUnicode[0], &subset, &buffer, true, 0, + SkTMin<SkGlyphID>(0xFFFF, lastGlyphID)); char expectedResult[] = "4 beginbfchar\n\ @@ -98,7 +101,8 @@ endbfrange\n"; // Remove characters and ranges. buffer.reset(); - SkPDFAppendCmapSections(glyphToUnicode, &subset, &buffer, true, 8, 0x00FF); + SkPDFAppendCmapSections(&glyphToUnicode[0], &subset, &buffer, true, 8, + SkTMin<SkGlyphID>(0x00FF, lastGlyphID)); char expectedResultChop1[] = "2 beginbfchar\n\ @@ -116,7 +120,8 @@ endbfrange\n"; // Remove characters from range to downdrade it to one char. buffer.reset(); - SkPDFAppendCmapSections(glyphToUnicode, &subset, &buffer, true, 0x00D, 0x00FE); + SkPDFAppendCmapSections(&glyphToUnicode[0], &subset, &buffer, true, 0x00D, + SkTMin<SkGlyphID>(0x00FE, lastGlyphID)); char expectedResultChop2[] = "2 beginbfchar\n\ @@ -129,7 +134,8 @@ endbfchar\n"; buffer.reset(); - SkPDFAppendCmapSections(glyphToUnicode, nullptr, &buffer, false, 0xFC, 0x110); + SkPDFAppendCmapSections(&glyphToUnicode[0], nullptr, &buffer, false, 0xFC, + SkTMin<SkGlyphID>(0x110, lastGlyphID)); char expectedResultSingleBytes[] = "2 beginbfchar\n\ @@ -155,6 +161,7 @@ endbfrange\n"; for (SkUnichar i = 0; i < 100; ++i) { glyphToUnicode.push(i + 29); } + lastGlyphID = SkToU16(glyphToUnicode.count() - 1); glyphsInSubset.push(0x2C); glyphsInSubset.push(0x44); @@ -165,7 +172,8 @@ endbfrange\n"; SkDynamicMemoryWStream buffer2; subset2.setAll(glyphsInSubset.begin(), glyphsInSubset.count()); - SkPDFAppendCmapSections(glyphToUnicode, &subset2, &buffer2, true, 0, 0xffff); + SkPDFAppendCmapSections(&glyphToUnicode[0], &subset2, &buffer2, true, 0, + SkTMin<SkGlyphID>(0xFFFF, lastGlyphID)); char expectedResult2[] = "4 beginbfchar\n\ diff --git a/tests/TypefaceTest.cpp b/tests/TypefaceTest.cpp index b6b71aeb8c..34fa3575f1 100644 --- a/tests/TypefaceTest.cpp +++ b/tests/TypefaceTest.cpp @@ -203,11 +203,11 @@ DEF_TEST(Typeface, reporter) { namespace { -class SkEmptyTypeface : public SkTypeface { +class EmptyTypeface : public SkTypeface { public: - static sk_sp<SkTypeface> Create() { return sk_sp<SkTypeface>(new SkEmptyTypeface()); } + static sk_sp<SkTypeface> Create() { return sk_sp<SkTypeface>(new EmptyTypeface()); } protected: - SkEmptyTypeface() : SkTypeface(SkFontStyle(), true) { } + EmptyTypeface() : SkTypeface(SkFontStyle(), true) { } SkStreamAsset* onOpenStream(int* ttcIndex) const override { return nullptr; } SkScalerContext* onCreateScalerContext(const SkScalerContextEffects&, @@ -255,12 +255,12 @@ static int count(skiatest::Reporter* reporter, const SkTypefaceCache& cache) { } DEF_TEST(TypefaceCache, reporter) { - sk_sp<SkTypeface> t1(SkEmptyTypeface::Create()); + sk_sp<SkTypeface> t1(EmptyTypeface::Create()); { SkTypefaceCache cache; REPORTER_ASSERT(reporter, count(reporter, cache) == 0); { - sk_sp<SkTypeface> t0(SkEmptyTypeface::Create()); + sk_sp<SkTypeface> t0(EmptyTypeface::Create()); cache.add(t0.get()); REPORTER_ASSERT(reporter, count(reporter, cache) == 1); cache.add(t1.get()); diff --git a/tools/fonts/SkRandomScalerContext.cpp b/tools/fonts/SkRandomScalerContext.cpp index 2d472129a1..9379759ff0 100644 --- a/tools/fonts/SkRandomScalerContext.cpp +++ b/tools/fonts/SkRandomScalerContext.cpp @@ -164,6 +164,10 @@ void SkRandomTypeface::onFilterRec(SkScalerContextRec* rec) const { rec->fMaskFormat = SkMask::kARGB32_Format; } +void SkRandomTypeface::getGlyphToUnicodeMap(SkUnichar* glyphToUnicode) const { + fProxy->getGlyphToUnicodeMap(glyphToUnicode); +} + std::unique_ptr<SkAdvancedTypefaceMetrics> SkRandomTypeface::onGetAdvancedMetrics() const { return fProxy->getAdvancedMetrics(); } diff --git a/tools/fonts/SkRandomScalerContext.h b/tools/fonts/SkRandomScalerContext.h index b71689d9e2..5dbdac68b8 100644 --- a/tools/fonts/SkRandomScalerContext.h +++ b/tools/fonts/SkRandomScalerContext.h @@ -27,6 +27,7 @@ protected: SkScalerContext* onCreateScalerContext(const SkScalerContextEffects&, const SkDescriptor*) const override; void onFilterRec(SkScalerContextRec*) const override; + void getGlyphToUnicodeMap(SkUnichar*) const override; std::unique_ptr<SkAdvancedTypefaceMetrics> onGetAdvancedMetrics() const override; SkStreamAsset* onOpenStream(int* ttcIndex) const override; void onGetFontDescriptor(SkFontDescriptor*, bool* isLocal) const override; diff --git a/tools/fonts/SkTestSVGTypeface.cpp b/tools/fonts/SkTestSVGTypeface.cpp index ceb523aa72..199c3b5df6 100644 --- a/tools/fonts/SkTestSVGTypeface.cpp +++ b/tools/fonts/SkTestSVGTypeface.cpp @@ -100,15 +100,17 @@ void SkTestSVGTypeface::onFilterRec(SkScalerContextRec* rec) const { rec->setHinting(SkPaint::kNo_Hinting); } +void SkTestSVGTypeface::getGlyphToUnicodeMap(SkUnichar* glyphToUnicode) const { + SkDEBUGCODE(unsigned glyphCount = this->countGlyphs()); + fCMap.foreach([=](const SkUnichar& c, const SkGlyphID& g) { + SkASSERT(g < glyphCount); + glyphToUnicode[g] = c; + }); +} + std::unique_ptr<SkAdvancedTypefaceMetrics> SkTestSVGTypeface::onGetAdvancedMetrics() const { std::unique_ptr<SkAdvancedTypefaceMetrics> info(new SkAdvancedTypefaceMetrics); - info->fFontName.set(fName); - - SkTDArray<SkUnichar>& toUnicode = info->fGlyphToUnicode; - toUnicode.setCount(fGlyphCount); - fCMap.foreach([&toUnicode](const SkUnichar& c, const SkGlyphID& g) { - toUnicode[g] = c; - }); + info->fFontName = fName; return info; } diff --git a/tools/fonts/SkTestSVGTypeface.h b/tools/fonts/SkTestSVGTypeface.h index 0b53245b70..249cd8bfc1 100644 --- a/tools/fonts/SkTestSVGTypeface.h +++ b/tools/fonts/SkTestSVGTypeface.h @@ -77,6 +77,7 @@ protected: SkScalerContext* onCreateScalerContext(const SkScalerContextEffects&, const SkDescriptor* desc) const override; void onFilterRec(SkScalerContextRec* rec) const override; + void getGlyphToUnicodeMap(SkUnichar*) const override; std::unique_ptr<SkAdvancedTypefaceMetrics> onGetAdvancedMetrics() const override; SkStreamAsset* onOpenStream(int* ttcIndex) const override { diff --git a/tools/fonts/SkTestTypeface.cpp b/tools/fonts/SkTestTypeface.cpp index d7caa5a392..bf3a1a3e9e 100644 --- a/tools/fonts/SkTestTypeface.cpp +++ b/tools/fonts/SkTestTypeface.cpp @@ -119,17 +119,16 @@ void SkTestTypeface::onFilterRec(SkScalerContextRec* rec) const { rec->setHinting(SkPaint::kNo_Hinting); } +void SkTestTypeface::getGlyphToUnicodeMap(SkUnichar* glyphToUnicode) const { + unsigned glyphCount = fTestFont->fCharCodesCount; + for (unsigned gid = 0; gid < glyphCount; ++gid) { + glyphToUnicode[gid] = SkTo<SkUnichar>(fTestFont->fCharCodes[gid]); + } +} + std::unique_ptr<SkAdvancedTypefaceMetrics> SkTestTypeface::onGetAdvancedMetrics() const { // pdf only std::unique_ptr<SkAdvancedTypefaceMetrics> info(new SkAdvancedTypefaceMetrics); info->fFontName.set(fTestFont->fName); - int glyphCount = this->onCountGlyphs(); - - SkTDArray<SkUnichar>& toUnicode = info->fGlyphToUnicode; - toUnicode.setCount(glyphCount); - SkASSERT(glyphCount == SkToInt(fTestFont->fCharCodesCount)); - for (int gid = 0; gid < glyphCount; ++gid) { - toUnicode[gid] = SkToS32(fTestFont->fCharCodes[gid]); - } return info; } diff --git a/tools/fonts/SkTestTypeface.h b/tools/fonts/SkTestTypeface.h index d3365f972a..205d82c30f 100644 --- a/tools/fonts/SkTestTypeface.h +++ b/tools/fonts/SkTestTypeface.h @@ -71,6 +71,7 @@ protected: SkScalerContext* onCreateScalerContext(const SkScalerContextEffects&, const SkDescriptor* desc) const override; void onFilterRec(SkScalerContextRec* rec) const override; + void getGlyphToUnicodeMap(SkUnichar* glyphToUnicode) const override; std::unique_ptr<SkAdvancedTypefaceMetrics> onGetAdvancedMetrics() const override; SkStreamAsset* onOpenStream(int* ttcIndex) const override { |