From 03cd6e6dec894b3447527f84e7591d62981df433 Mon Sep 17 00:00:00 2001 From: Ben Wagner Date: Thu, 8 Mar 2018 16:02:55 -0500 Subject: Avoid serializing to 'typ1' on Mac. CoreGraphics does not provide a means to get the original font data for a CGFont, only the tables. As a result, Skia pieces the font data back together when requested. The most awkward part of this is choosing the first four bytes, and the CTFont suggestion seems to often be wrong. This change doublechecks the selection of 'typ1', prefering to use 'OTTO' if there are no 'TYP1' or 'CID ' tables. These sorts of fonts are extremely old and unlikely to be in current use. It appears that CTFont may report that it has this format if it is an 'OTTO' font with very few glyphs. If Skia serializes such a font with 'typ1' as the first four bytes, CoreGraphics will not create a CGFont from the resulting font data. BUG=chromium:809763,skia:7630 Change-Id: I9979b9f0ebdd27c4ad0903e8ee6237241e755541 Reviewed-on: https://skia-review.googlesource.com/113306 Reviewed-by: Herb Derby Commit-Queue: Ben Wagner --- resources/fonts/7630.otf | Bin 0 -> 1168 bytes src/ports/SkFontHost_mac.cpp | 17 ++++++++++++++++- tests/TypefaceTest.cpp | 15 +++++++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 resources/fonts/7630.otf diff --git a/resources/fonts/7630.otf b/resources/fonts/7630.otf new file mode 100644 index 0000000000..355d0af275 Binary files /dev/null and b/resources/fonts/7630.otf differ diff --git a/src/ports/SkFontHost_mac.cpp b/src/ports/SkFontHost_mac.cpp index ae46664ff6..5d8723b95f 100644 --- a/src/ports/SkFontHost_mac.cpp +++ b/src/ports/SkFontHost_mac.cpp @@ -1629,15 +1629,30 @@ SkStreamAsset* SkTypeface_Mac::onOpenStream(int* ttcIndex) const { tableTags.setCount(numTables); this->getTableTags(tableTags.begin()); - // calc total size for font, save sizes + // see if there are any required 'typ1' tables (see Adobe Technical Note #5180) + bool couldBeTyp1 = false; + constexpr SkFontTableTag TYPE1Tag = SkSetFourByteTag('T', 'Y', 'P', '1'); + constexpr SkFontTableTag CIDTag = SkSetFourByteTag('C', 'I', 'D', ' '); + // get the table sizes and accumulate the total size of the font SkTDArray tableSizes; size_t totalSize = sizeof(SkSFNTHeader) + sizeof(SkSFNTHeader::TableDirectoryEntry) * numTables; for (int tableIndex = 0; tableIndex < numTables; ++tableIndex) { + if (TYPE1Tag == tableTags[tableIndex] || CIDTag == tableTags[tableIndex]) { + couldBeTyp1 = true; + } + size_t tableSize = this->getTableSize(tableTags[tableIndex]); totalSize += (tableSize + 3) & ~3; *tableSizes.append() = tableSize; } + // sometimes CoreGraphics incorrectly thinks a font is kCTFontFormatPostScript + // it is exceedingly unlikely that this is the case, so double check + // see https://crbug.com/809763 + if (fontType == SkSFNTHeader::fontType_PostScript::TAG && !couldBeTyp1) { + fontType = SkSFNTHeader::fontType_OpenTypeCFF::TAG; + } + // reserve memory for stream, and zero it (tables must be zero padded) SkMemoryStream* stream = new SkMemoryStream(totalSize); char* dataStart = (char*)stream->getMemoryBase(); diff --git a/tests/TypefaceTest.cpp b/tests/TypefaceTest.cpp index fc81e84926..b6b71aeb8c 100644 --- a/tests/TypefaceTest.cpp +++ b/tests/TypefaceTest.cpp @@ -94,6 +94,21 @@ DEF_TEST(TypefaceStyle, reporter) { } } +DEF_TEST(TypefaceRoundTrip, reporter) { + sk_sp typeface(MakeResourceAsTypeface("fonts/7630.otf")); + if (!typeface) { + // Not all SkFontMgr can MakeFromStream(). + return; + } + + int fontIndex; + std::unique_ptr stream(typeface->openStream(&fontIndex)); + + sk_sp fm = SkFontMgr::RefDefault(); + sk_sp typeface2 = fm->makeFromStream(std::move(stream), fontIndex); + REPORTER_ASSERT(reporter, typeface2); +} + DEF_TEST(TypefaceAxes, reporter) { std::unique_ptr distortable(GetResourceAsStream("fonts/Distortable.ttf")); if (!distortable) { -- cgit v1.2.3