diff --git a/bench/CmapBench.cpp b/bench/CmapBench.cpp index 3b90e35c40..cc34af1587 100644 --- a/bench/CmapBench.cpp +++ b/bench/CmapBench.cpp @@ -44,7 +44,7 @@ static void charsToGlyphs_proc(const Rec& r) { SkTypeface* face = r.fFont.getTypefaceOrDefault(); for (int i = 0; i < r.fLoops; ++i) { - face->charsToGlyphs(r.fText, SkTypeface::kUTF32_Encoding, glyphs, r.fCount); + face->unicharsToGlyphs(r.fText, r.fCount, glyphs); } } diff --git a/bench/TypefaceBench.cpp b/bench/TypefaceBench.cpp index cce5cdbd44..00b19d2e26 100644 --- a/bench/TypefaceBench.cpp +++ b/bench/TypefaceBench.cpp @@ -8,7 +8,7 @@ #include #include "Benchmark.h" -#include "SkFontTypes.h" +#include "SkFont.h" #include "SkMakeUnique.h" #include "SkTypeface.h" #include "SkUTF.h" @@ -238,12 +238,12 @@ protected: } void onDraw(int loops, SkCanvas* canvas) override { + SkFont font(fTypeface); // Do more loops to reduce variance. for (int i = 0; i < loops * 3; ++i) { for (auto& line : fLines) { - fTypeface->charsToGlyphs(line->utf.data(), - (SkTypeface::Encoding)fEncoding, fGlyphIds.data(), - line->glyphCount); + font.textToGlyphs(line->utf.data(), line->utf.size(), fEncoding, + fGlyphIds.data(), line->glyphCount); } } } diff --git a/gm/atlastext.cpp b/gm/atlastext.cpp index 328f398a8b..1584ea44a5 100644 --- a/gm/atlastext.cpp +++ b/gm/atlastext.cpp @@ -33,12 +33,14 @@ static SkScalar draw_string(SkAtlasTextTarget* target, const SkString& text, SkS auto atlas_font = SkAtlasTextFont::Make(typeface, size); int cnt = SkUTF::CountUTF8(text.c_str(), text.size()); std::unique_ptr glyphs(new SkGlyphID[cnt]); - typeface->charsToGlyphs(text.c_str(), SkTypeface::Encoding::kUTF8_Encoding, glyphs.get(), cnt); // Using a paint to get the positions for each glyph. SkFont font; font.setSize(size); font.setTypeface(std::move(typeface)); + + font.textToGlyphs(text.c_str(), text.size(), SkTextEncoding::kUTF8, glyphs.get(), cnt); + std::unique_ptr widths(new SkScalar[cnt]); font.getWidths(glyphs.get(), cnt, widths.get()); diff --git a/include/core/SkFont.h b/include/core/SkFont.h index 74b7df57c7..a64c4bb750 100644 --- a/include/core/SkFont.h +++ b/include/core/SkFont.h @@ -302,6 +302,8 @@ public: */ SkGlyphID unicharToGlyph(SkUnichar uni) const; + void unicharsToGlyphs(const SkUnichar uni[], int count, SkGlyphID glyphs[]) const; + /** Returns number of glyphs represented by text. If encoding is kUTF8_SkTextEncoding, kUTF16_SkTextEncoding, or diff --git a/include/core/SkFontTypes.h b/include/core/SkFontTypes.h index bb1b03f227..67964516f5 100644 --- a/include/core/SkFontTypes.h +++ b/include/core/SkFontTypes.h @@ -9,8 +9,6 @@ #define SkFontTypes_DEFINED #include "SkTypes.h" -// remove me once google3 uses IWYU -#include "SkTypeface.h" enum class SkTextEncoding { kUTF8, //!< uses bytes to represent UTF-8 or ASCII @@ -36,4 +34,7 @@ enum class SkFontHinting { #define kNormal_SkFontHinting SkFontHinting::kNormal #define kFull_SkFontHinting SkFontHinting::kFull +// remove me once google3 uses IWYU +#include "SkTypeface.h" + #endif diff --git a/include/core/SkTypeface.h b/include/core/SkTypeface.h index 7f5af8cdb1..99c22ce336 100644 --- a/include/core/SkTypeface.h +++ b/include/core/SkTypeface.h @@ -14,6 +14,7 @@ #include "SkFontArguments.h" #include "SkFontParameters.h" #include "SkFontStyle.h" +#include "SkFontTypes.h" #include "SkRect.h" #include "SkString.h" @@ -176,36 +177,29 @@ public: */ static sk_sp MakeDeserialize(SkStream*); +#ifdef SK_SUPPORT_LEGACY_CHARSTOGLYPHS enum Encoding : uint8_t { kUTF8_Encoding, kUTF16_Encoding, kUTF32_Encoding }; - - /** - * Given an array of character codes, of the specified encoding, - * optionally return their corresponding glyph IDs (if glyphs is not NULL). - * - * @param chars pointer to the array of character codes - * @param encoding how the characters are encoded - * @param glyphs (optional) returns the corresponding glyph IDs for each - * character code, up to glyphCount values. If a character code is - * not found in the typeface, the corresponding glyph ID will be 0. - * @param glyphCount number of code points in 'chars' to process. If glyphs - * is not NULL, then it must point sufficient memory to write - * glyphCount values into it. - * @return the number of number of continuous non-zero glyph IDs computed - * from the beginning of chars. This value is valid, even if the - * glyphs parameter is NULL. - */ int charsToGlyphs(const void* chars, Encoding encoding, SkGlyphID glyphs[], int glyphCount) const; +#endif + /** + * Given an array of UTF32 character codes, return their corresponding glyph IDs. + * + * @param chars pointer to the array of UTF32 chars + * @param number of chars and glyphs + * @param glyphs returns the corresponding glyph IDs for each character. + */ + void unicharsToGlyphs(const SkUnichar uni[], int count, SkGlyphID glyphs[]) const; /** * Return the glyphID that corresponds to the specified unicode code-point * (in UTF32 encoding). If the unichar is not supported, returns 0. * - * This is a short-cut for calling charsToGlyphs() with kUTF32_Encoding for one code-point. + * This is a short-cut for calling unicharsToGlyphs(). */ SkGlyphID unicharToGlyph(SkUnichar unichar) const; @@ -393,8 +387,7 @@ protected: virtual void onGetFontDescriptor(SkFontDescriptor*, bool* isLocal) const = 0; - virtual int onCharsToGlyphs(const void* chars, Encoding, SkGlyphID glyphs[], - int glyphCount) const = 0; + virtual void onCharsToGlyphs(const SkUnichar* chars, int count, SkGlyphID glyphs[]) const = 0; virtual int onCountGlyphs() const = 0; virtual int onGetUPEM() const = 0; diff --git a/src/core/SkFont.cpp b/src/core/SkFont.cpp index 5ab8447035..29c82295c6 100644 --- a/src/core/SkFont.cpp +++ b/src/core/SkFont.cpp @@ -170,6 +170,46 @@ SkGlyphID SkFont::unicharToGlyph(SkUnichar uni) const { return this->getTypefaceOrDefault()->unicharToGlyph(uni); } +void SkFont::unicharsToGlyphs(const SkUnichar uni[], int count, SkGlyphID glyphs[]) const { + this->getTypefaceOrDefault()->unicharsToGlyphs(uni, count, glyphs); +} + +class SkConvertToUTF32 { +public: + SkConvertToUTF32() {} + + const SkUnichar* convert(const void* text, size_t byteLength, SkTextEncoding encoding) { + const SkUnichar* uni; + switch (encoding) { + case SkTextEncoding::kUTF8: { + uni = fStorage.reset(byteLength); + const char* ptr = (const char*)text; + const char* end = ptr + byteLength; + for (int i = 0; ptr < end; ++i) { + fStorage[i] = SkUTF::NextUTF8(&ptr, end); + } + } break; + case SkTextEncoding::kUTF16: { + uni = fStorage.reset(byteLength); + const uint16_t* ptr = (const uint16_t*)text; + const uint16_t* end = ptr + (byteLength >> 1); + for (int i = 0; ptr < end; ++i) { + fStorage[i] = SkUTF::NextUTF16(&ptr, end); + } + } break; + case SkTextEncoding::kUTF32: + uni = (const SkUnichar*)text; + break; + default: + SK_ABORT("unexpected enum"); + } + return uni; + } + +private: + SkAutoSTMalloc<256, SkUnichar> fStorage; +}; + int SkFont::textToGlyphs(const void* text, size_t byteLength, SkTextEncoding encoding, SkGlyphID glyphs[], int maxGlyphCount) const { if (0 == byteLength) { @@ -183,26 +223,15 @@ int SkFont::textToGlyphs(const void* text, size_t byteLength, SkTextEncoding enc return count; } - // TODO: unify/eliminate SkTypeface::Encoding with SkTextEncoding - SkTypeface::Encoding typefaceEncoding; - switch (encoding) { - case kUTF8_SkTextEncoding: - typefaceEncoding = SkTypeface::kUTF8_Encoding; - break; - case kUTF16_SkTextEncoding: - typefaceEncoding = SkTypeface::kUTF16_Encoding; - break; - case kUTF32_SkTextEncoding: - typefaceEncoding = SkTypeface::kUTF32_Encoding; - break; - default: - SkASSERT(kGlyphID_SkTextEncoding == encoding); - // we can early exit, since we already have glyphIDs - memcpy(glyphs, text, count << 1); - return count; + if (encoding == SkTextEncoding::kGlyphID) { + memcpy(glyphs, text, count << 1); + return count; } - (void) this->getTypefaceOrDefault()->charsToGlyphs(text, typefaceEncoding, glyphs,count); + SkConvertToUTF32 storage; + const SkUnichar* uni = storage.convert(text, byteLength, encoding); + + this->getTypefaceOrDefault()->unicharsToGlyphs(uni, count, glyphs); return count; } diff --git a/src/core/SkTypeface.cpp b/src/core/SkTypeface.cpp index 3950e5d571..1cb4e98f9e 100644 --- a/src/core/SkTypeface.cpp +++ b/src/core/SkTypeface.cpp @@ -57,12 +57,8 @@ protected: return nullptr; } void onGetFontDescriptor(SkFontDescriptor*, bool*) const override { } - virtual int onCharsToGlyphs(const void* chars, Encoding encoding, - uint16_t glyphs[], int glyphCount) const override { - if (glyphs && glyphCount > 0) { - sk_bzero(glyphs, glyphCount * sizeof(glyphs[0])); - } - return 0; + void onCharsToGlyphs(const SkUnichar* chars, int count, SkGlyphID glyphs[]) const override { + sk_bzero(glyphs, count * sizeof(glyphs[0])); } int onCountGlyphs() const override { return 0; } int onGetUPEM() const override { return 0; } @@ -285,25 +281,30 @@ std::unique_ptr SkTypeface::onMakeFontData() const { return skstd::make_unique(std::move(stream), index, nullptr, 0); }; -int SkTypeface::charsToGlyphs(const void* chars, Encoding encoding, - uint16_t glyphs[], int glyphCount) const { - if (glyphCount <= 0) { - return 0; +void SkTypeface::unicharsToGlyphs(const SkUnichar uni[], int count, SkGlyphID glyphs[]) const { + if (count > 0 && glyphs && uni) { + this->onCharsToGlyphs(uni, count, glyphs); } - if (nullptr == chars || (unsigned)encoding > kUTF32_Encoding) { - if (glyphs) { - sk_bzero(glyphs, glyphCount * sizeof(glyphs[0])); - } - return 0; - } - return this->onCharsToGlyphs(chars, encoding, glyphs, glyphCount); } SkGlyphID SkTypeface::unicharToGlyph(SkUnichar uni) const { - SkGlyphID glyphs[1]; - return this->onCharsToGlyphs(&uni, kUTF32_Encoding, glyphs, 1) == 1 ? glyphs[0] : 0; + SkGlyphID glyphs[1] = { 0 }; + this->onCharsToGlyphs(&uni, 1, glyphs); + return glyphs[0]; } +#ifdef SK_SUPPORT_LEGACY_CHARSTOGLYPHS +#include "SkFont.h" +int SkTypeface::charsToGlyphs(const void* chars, Encoding encoding, SkGlyphID glyphs[], + int glyphCount) const { + SkFont font(sk_ref_sp(this)); + const size_t save_length = glyphCount * 4; + int n = font.textToGlyphs(chars, save_length, (SkTextEncoding)encoding, glyphs, glyphCount); + SkASSERT(n == glyphCount); + return n; +} +#endif + int SkTypeface::countGlyphs() const { return this->onCountGlyphs(); } diff --git a/src/core/SkTypeface_remote.h b/src/core/SkTypeface_remote.h index 46908c5892..dde0ff555d 100644 --- a/src/core/SkTypeface_remote.h +++ b/src/core/SkTypeface_remote.h @@ -122,10 +122,8 @@ protected: SK_ABORT("Should never be called."); return nullptr; } - int onCharsToGlyphs(const void* chars, Encoding, - uint16_t glyphs[], int glyphCount) const override { + void onCharsToGlyphs(const SkUnichar* chars, int count, SkGlyphID glyphs[]) const override { SK_ABORT("Should never be called."); - return 0; } int onCountGlyphs() const override { return this->glyphCount(); diff --git a/src/core/SkUtils.h b/src/core/SkUtils.h index cfbdaae31b..1597c98836 100644 --- a/src/core/SkUtils.h +++ b/src/core/SkUtils.h @@ -9,7 +9,7 @@ #define SkUtils_DEFINED #include "SkOpts.h" -#include "SkTypeface.h" +#include "SkFontTypes.h" #include "../utils/SkUTF.h" /** Similar to memset(), but it assigns a 16, 32, or 64-bit value into the buffer. @@ -42,23 +42,22 @@ static inline bool SkUTF16_IsTrailingSurrogate (uint16_t c) { return ((c) & 0xFC /////////////////////////////////////////////////////////////////////////////// -static inline int SkUTFN_CountUnichars(SkTypeface::Encoding enc, const void* utfN, size_t bytes) { +static inline int SkUTFN_CountUnichars(SkTextEncoding enc, const void* utfN, size_t bytes) { switch (enc) { - case SkTypeface::kUTF8_Encoding: return SkUTF::CountUTF8((const char*)utfN, bytes); - case SkTypeface::kUTF16_Encoding: return SkUTF::CountUTF16((const uint16_t*)utfN, bytes); - case SkTypeface::kUTF32_Encoding: return SkUTF::CountUTF32((const int32_t*)utfN, bytes); + case SkTextEncoding::kUTF8: return SkUTF::CountUTF8((const char*)utfN, bytes); + case SkTextEncoding::kUTF16: return SkUTF::CountUTF16((const uint16_t*)utfN, bytes); + case SkTextEncoding::kUTF32: return SkUTF::CountUTF32((const int32_t*)utfN, bytes); default: SkDEBUGFAIL("unknown text encoding"); return -1; } } -static inline SkUnichar SkUTFN_Next(SkTypeface::Encoding enc, - const void** ptr, const void* stop) { +static inline SkUnichar SkUTFN_Next(SkTextEncoding enc, const void** ptr, const void* stop) { switch (enc) { - case SkTypeface::kUTF8_Encoding: + case SkTextEncoding::kUTF8: return SkUTF::NextUTF8((const char**)ptr, (const char*)stop); - case SkTypeface::kUTF16_Encoding: + case SkTextEncoding::kUTF16: return SkUTF::NextUTF16((const uint16_t**)ptr, (const uint16_t*)stop); - case SkTypeface::kUTF32_Encoding: + case SkTextEncoding::kUTF32: return SkUTF::NextUTF32((const int32_t**)ptr, (const int32_t*)stop); default: SkDEBUGFAIL("unknown text encoding"); return -1; } diff --git a/src/ports/SkFontHost_FreeType.cpp b/src/ports/SkFontHost_FreeType.cpp index c21f8844ed..dd0b800264 100644 --- a/src/ports/SkFontHost_FreeType.cpp +++ b/src/ports/SkFontHost_FreeType.cpp @@ -1551,62 +1551,17 @@ void SkScalerContext_FreeType::emboldenIfNeeded(FT_Face face, FT_GlyphSlot glyph #include "SkUtils.h" -static SkUnichar next_utf8(const void** chars) { - return SkUTF8_NextUnichar((const char**)chars); -} - -static SkUnichar next_utf16(const void** chars) { - return SkUTF16_NextUnichar((const uint16_t**)chars); -} - -static SkUnichar next_utf32(const void** chars) { - const SkUnichar** uniChars = (const SkUnichar**)chars; - SkUnichar uni = **uniChars; - *uniChars += 1; - return uni; -} - -typedef SkUnichar (*EncodingProc)(const void**); - -static EncodingProc find_encoding_proc(SkTypeface::Encoding enc) { - static const EncodingProc gProcs[] = { - next_utf8, next_utf16, next_utf32 - }; - SkASSERT((size_t)enc < SK_ARRAY_COUNT(gProcs)); - return gProcs[enc]; -} - -int SkTypeface_FreeType::onCharsToGlyphs(const void* chars, Encoding encoding, - uint16_t glyphs[], int glyphCount) const -{ +void SkTypeface_FreeType::onCharsToGlyphs(const SkUnichar uni[], int count, + SkGlyphID glyphs[]) const { AutoFTAccess fta(this); FT_Face face = fta.face(); if (!face) { - if (glyphs) { - sk_bzero(glyphs, glyphCount * sizeof(glyphs[0])); - } - return 0; + sk_bzero(glyphs, count * sizeof(glyphs[0])); + return; } - EncodingProc next_uni_proc = find_encoding_proc(encoding); - - if (nullptr == glyphs) { - for (int i = 0; i < glyphCount; ++i) { - if (0 == FT_Get_Char_Index(face, next_uni_proc(&chars))) { - return i; - } - } - return glyphCount; - } else { - int first = glyphCount; - for (int i = 0; i < glyphCount; ++i) { - unsigned id = FT_Get_Char_Index(face, next_uni_proc(&chars)); - glyphs[i] = SkToU16(id); - if (0 == id && i < first) { - first = i; - } - } - return first; + for (int i = 0; i < count; ++i) { + glyphs[i] = SkToU16(FT_Get_Char_Index(face, uni[i])); } } diff --git a/src/ports/SkFontHost_FreeType_common.h b/src/ports/SkFontHost_FreeType_common.h index 02cdb60156..064b1a8259 100644 --- a/src/ports/SkFontHost_FreeType_common.h +++ b/src/ports/SkFontHost_FreeType_common.h @@ -102,8 +102,7 @@ protected: int onGetUPEM() const override; bool onGetKerningPairAdjustments(const uint16_t glyphs[], int count, int32_t adjustments[]) const override; - int onCharsToGlyphs(const void* chars, Encoding, uint16_t glyphs[], - int glyphCount) const override; + void onCharsToGlyphs(const SkUnichar uni[], int count, SkGlyphID glyphs[]) const override; int onCountGlyphs() const override; LocalizedStrings* onCreateFamilyNameIterator() const override; diff --git a/src/ports/SkFontHost_mac.cpp b/src/ports/SkFontHost_mac.cpp index 5f9cbcf80a..870ee30f7d 100644 --- a/src/ports/SkFontHost_mac.cpp +++ b/src/ports/SkFontHost_mac.cpp @@ -742,8 +742,7 @@ protected: void onGetFontDescriptor(SkFontDescriptor*, bool*) const override; void getGlyphToUnicodeMap(SkUnichar*) const override; std::unique_ptr onGetAdvancedMetrics() const override; - int onCharsToGlyphs(const void* chars, Encoding, - uint16_t glyphs[], int glyphCount) const override; + void onCharsToGlyphs(const SkUnichar* chars, int count, SkGlyphID glyphs[]) const override; int onCountGlyphs() const override; void* onGetCTFontRef() const override { return (void*)fFontRef.get(); } @@ -2333,9 +2332,7 @@ void SkTypeface_Mac::onGetFontDescriptor(SkFontDescriptor* desc, *isLocalStream = fIsFromStream; } -int SkTypeface_Mac::onCharsToGlyphs(const void* chars, Encoding encoding, - uint16_t glyphs[], int glyphCount) const -{ +void SkTypeface_Mac::onCharsToGlyphs(const SkUnichar uni[], int count, SkGlyphID glyphs[]) const { // Undocumented behavior of CTFontGetGlyphsForCharacters with non-bmp code points: // When a surrogate pair is detected, the glyph index used is the index of the high surrogate. // It is documented that if a mapping is unavailable, the glyph will be set to 0. @@ -2343,81 +2340,38 @@ int SkTypeface_Mac::onCharsToGlyphs(const void* chars, Encoding encoding, SkAutoSTMalloc<1024, UniChar> charStorage; const UniChar* src; // UniChar is a UTF-16 16-bit code unit. int srcCount; - switch (encoding) { - case kUTF8_Encoding: { - const char* utf8 = reinterpret_cast(chars); - UniChar* utf16 = charStorage.reset(2 * glyphCount); - src = utf16; - for (int i = 0; i < glyphCount; ++i) { - SkUnichar uni = SkUTF8_NextUnichar(&utf8); - utf16 += SkUTF::ToUTF16(uni, utf16); - } - srcCount = SkToInt(utf16 - src); - break; - } - case kUTF16_Encoding: { - src = reinterpret_cast(chars); - int extra = 0; - for (int i = 0; i < glyphCount; ++i) { - if (SkUTF16_IsLeadingSurrogate(src[i + extra])) { - ++extra; - } - } - srcCount = glyphCount + extra; - break; - } - case kUTF32_Encoding: { - const SkUnichar* utf32 = reinterpret_cast(chars); - UniChar* utf16 = charStorage.reset(2 * glyphCount); - src = utf16; - for (int i = 0; i < glyphCount; ++i) { - utf16 += SkUTF::ToUTF16(utf32[i], utf16); - } - srcCount = SkToInt(utf16 - src); - break; - } + const SkUnichar* utf32 = reinterpret_cast(uni); + UniChar* utf16 = charStorage.reset(2 * count); + src = utf16; + for (int i = 0; i < count; ++i) { + utf16 += SkUTF::ToUTF16(utf32[i], utf16); } + srcCount = SkToInt(utf16 - src); - // If glyphs is nullptr, CT still needs glyph storage for finding the first failure. - // Also, if there are any non-bmp code points, the provided 'glyphs' storage will be inadequate. + // If there are any non-bmp code points, the provided 'glyphs' storage will be inadequate. SkAutoSTMalloc<1024, uint16_t> glyphStorage; uint16_t* macGlyphs = glyphs; - if (nullptr == macGlyphs || srcCount > glyphCount) { + if (srcCount > count) { macGlyphs = glyphStorage.reset(srcCount); } - bool allEncoded = CTFontGetGlyphsForCharacters(fFontRef.get(), src, macGlyphs, srcCount); + CTFontGetGlyphsForCharacters(fFontRef.get(), src, macGlyphs, srcCount); // If there were any non-bmp, then copy and compact. - // If 'glyphs' is nullptr, then compact glyphStorage in-place. - // If all are bmp and 'glyphs' is non-nullptr, 'glyphs' already contains the compact glyphs. - // If some are non-bmp and 'glyphs' is non-nullptr, copy and compact into 'glyphs'. - uint16_t* compactedGlyphs = glyphs; - if (nullptr == compactedGlyphs) { - compactedGlyphs = macGlyphs; - } - if (srcCount > glyphCount) { + // If all are bmp, 'glyphs' already contains the compact glyphs. + // If some are non-bmp, copy and compact into 'glyphs'. + if (srcCount > count) { + SkASSERT(glyphs != macGlyphs); int extra = 0; - for (int i = 0; i < glyphCount; ++i) { - compactedGlyphs[i] = macGlyphs[i + extra]; + for (int i = 0; i < count; ++i) { + glyphs[i] = macGlyphs[i + extra]; if (SkUTF16_IsLeadingSurrogate(src[i + extra])) { ++extra; } } + } else { + SkASSERT(glyphs == macGlyphs); } - - if (allEncoded) { - return glyphCount; - } - - // If we got false, then we need to manually look for first failure. - for (int i = 0; i < glyphCount; ++i) { - if (0 == compactedGlyphs[i]) { - return i; - } - } - // Odd to get here, as we expected CT to have returned true up front. - return glyphCount; } int SkTypeface_Mac::onCountGlyphs() const { diff --git a/src/ports/SkFontHost_win.cpp b/src/ports/SkFontHost_win.cpp index bbb37c7f92..bb76fc572f 100644 --- a/src/ports/SkFontHost_win.cpp +++ b/src/ports/SkFontHost_win.cpp @@ -267,8 +267,7 @@ protected: void getGlyphToUnicodeMap(SkUnichar*) const override; std::unique_ptr onGetAdvancedMetrics() const override; void onGetFontDescriptor(SkFontDescriptor*, bool*) const override; - int onCharsToGlyphs(const void* chars, Encoding encoding, - uint16_t glyphs[], int glyphCount) const override; + void onCharsToGlyphs(const SkUnichar* chars, int count, SkGlyphID glyphs[]) const override; int onCountGlyphs() const override; int onGetUPEM() const override; void onGetFamilyName(SkString* familyName) const override; @@ -1917,8 +1916,8 @@ private: }; #define SkAutoHDC(...) SK_REQUIRE_LOCAL_VAR(SkAutoHDC) -int LogFontTypeface::onCharsToGlyphs(const void* chars, Encoding encoding, - uint16_t userGlyphs[], int glyphCount) const +void LogFontTypeface::onCharsToGlyphs(const SkUnichar uni[], int glyphCount, + SkGlyphID glyphs[]) const { SkAutoHDC hdc(fLogFont); @@ -1931,119 +1930,35 @@ int LogFontTypeface::onCharsToGlyphs(const void* chars, Encoding encoding, } bool Ox1FHack = !(tm.tmPitchAndFamily & TMPF_VECTOR) /*&& winVer < Vista */; - SkAutoSTMalloc<256, uint16_t> scratchGlyphs; - uint16_t* glyphs; - if (userGlyphs != nullptr) { - glyphs = userGlyphs; - } else { - glyphs = scratchGlyphs.reset(glyphCount); - } - SCRIPT_CACHE sc = 0; - switch (encoding) { - case SkTypeface::kUTF8_Encoding: { - static const int scratchCount = 256; - WCHAR scratch[scratchCount]; - int glyphIndex = 0; - const char* currentUtf8 = reinterpret_cast(chars); - SkUnichar currentChar = 0; - if (glyphCount) { - currentChar = SkUTF8_NextUnichar(¤tUtf8); + static const int scratchCount = 256; + WCHAR scratch[scratchCount]; + int glyphIndex = 0; + const uint32_t* utf32 = reinterpret_cast(uni); + while (glyphIndex < glyphCount) { + // Try a run of bmp. + int glyphsLeft = SkTMin(glyphCount - glyphIndex, scratchCount); + int runLength = 0; + while (runLength < glyphsLeft && utf32[glyphIndex + runLength] <= 0xFFFF) { + scratch[runLength] = static_cast(utf32[glyphIndex + runLength]); + ++runLength; + } + if (runLength) { + bmpCharsToGlyphs(hdc, scratch, runLength, &glyphs[glyphIndex], Ox1FHack); + glyphIndex += runLength; } - while (glyphIndex < glyphCount) { - // Try a run of bmp. - int glyphsLeft = SkTMin(glyphCount - glyphIndex, scratchCount); - int runLength = 0; - while (runLength < glyphsLeft && currentChar <= 0xFFFF) { - scratch[runLength] = static_cast(currentChar); - ++runLength; - if (runLength < glyphsLeft) { - currentChar = SkUTF8_NextUnichar(¤tUtf8); - } - } - if (runLength) { - bmpCharsToGlyphs(hdc, scratch, runLength, &glyphs[glyphIndex], Ox1FHack); - glyphIndex += runLength; - } - // Try a run of non-bmp. - while (glyphIndex < glyphCount && currentChar > 0xFFFF) { - SkUTF::ToUTF16(currentChar, reinterpret_cast(scratch)); - glyphs[glyphIndex] = nonBmpCharToGlyph(hdc, &sc, scratch); - ++glyphIndex; - if (glyphIndex < glyphCount) { - currentChar = SkUTF8_NextUnichar(¤tUtf8); - } - } + // Try a run of non-bmp. + while (glyphIndex < glyphCount && utf32[glyphIndex] > 0xFFFF) { + SkUTF::ToUTF16(utf32[glyphIndex], reinterpret_cast(scratch)); + glyphs[glyphIndex] = nonBmpCharToGlyph(hdc, &sc, scratch); + ++glyphIndex; } - break; - } - case SkTypeface::kUTF16_Encoding: { - int glyphIndex = 0; - const WCHAR* currentUtf16 = reinterpret_cast(chars); - while (glyphIndex < glyphCount) { - // Try a run of bmp. - int glyphsLeft = glyphCount - glyphIndex; - int runLength = 0; - while (runLength < glyphsLeft && !SkUTF16_IsLeadingSurrogate(currentUtf16[runLength])) { - ++runLength; - } - if (runLength) { - bmpCharsToGlyphs(hdc, currentUtf16, runLength, &glyphs[glyphIndex], Ox1FHack); - glyphIndex += runLength; - currentUtf16 += runLength; - } - - // Try a run of non-bmp. - while (glyphIndex < glyphCount && SkUTF16_IsLeadingSurrogate(*currentUtf16)) { - glyphs[glyphIndex] = nonBmpCharToGlyph(hdc, &sc, currentUtf16); - ++glyphIndex; - currentUtf16 += 2; - } - } - break; - } - case SkTypeface::kUTF32_Encoding: { - static const int scratchCount = 256; - WCHAR scratch[scratchCount]; - int glyphIndex = 0; - const uint32_t* utf32 = reinterpret_cast(chars); - while (glyphIndex < glyphCount) { - // Try a run of bmp. - int glyphsLeft = SkTMin(glyphCount - glyphIndex, scratchCount); - int runLength = 0; - while (runLength < glyphsLeft && utf32[glyphIndex + runLength] <= 0xFFFF) { - scratch[runLength] = static_cast(utf32[glyphIndex + runLength]); - ++runLength; - } - if (runLength) { - bmpCharsToGlyphs(hdc, scratch, runLength, &glyphs[glyphIndex], Ox1FHack); - glyphIndex += runLength; - } - - // Try a run of non-bmp. - while (glyphIndex < glyphCount && utf32[glyphIndex] > 0xFFFF) { - SkUTF::ToUTF16(utf32[glyphIndex], reinterpret_cast(scratch)); - glyphs[glyphIndex] = nonBmpCharToGlyph(hdc, &sc, scratch); - ++glyphIndex; - } - } - break; - } - default: - SK_ABORT("Invalid Text Encoding"); } if (sc) { ::ScriptFreeCache(&sc); } - - for (int i = 0; i < glyphCount; ++i) { - if (0 == glyphs[i]) { - return i; - } - } - return glyphCount; } int LogFontTypeface::onCountGlyphs() const { diff --git a/src/ports/SkTypeface_win_dw.cpp b/src/ports/SkTypeface_win_dw.cpp index c7802aa858..bcb9d7dc60 100644 --- a/src/ports/SkTypeface_win_dw.cpp +++ b/src/ports/SkTypeface_win_dw.cpp @@ -52,78 +52,9 @@ void DWriteFontTypeface::onGetFontDescriptor(SkFontDescriptor* desc, *isLocalStream = SkToBool(fDWriteFontFileLoader.get()); } -static SkUnichar next_utf8(const void** chars) { - return SkUTF8_NextUnichar((const char**)chars); -} - -static SkUnichar next_utf16(const void** chars) { - return SkUTF16_NextUnichar((const uint16_t**)chars); -} - -static SkUnichar next_utf32(const void** chars) { - const SkUnichar** uniChars = (const SkUnichar**)chars; - SkUnichar uni = **uniChars; - *uniChars += 1; - return uni; -} - -typedef SkUnichar (*EncodingProc)(const void**); - -static EncodingProc find_encoding_proc(SkTypeface::Encoding enc) { - static const EncodingProc gProcs[] = { - next_utf8, next_utf16, next_utf32 - }; - SkASSERT((size_t)enc < SK_ARRAY_COUNT(gProcs)); - return gProcs[enc]; -} - -int DWriteFontTypeface::onCharsToGlyphs(const void* chars, Encoding encoding, - uint16_t glyphs[], int glyphCount) const -{ - if (nullptr == glyphs) { - EncodingProc next_ucs4_proc = find_encoding_proc(encoding); - for (int i = 0; i < glyphCount; ++i) { - const SkUnichar c = next_ucs4_proc(&chars); - BOOL exists; - fDWriteFont->HasCharacter(c, &exists); - if (!exists) { - return i; - } - } - return glyphCount; - } - - switch (encoding) { - case SkTypeface::kUTF8_Encoding: - case SkTypeface::kUTF16_Encoding: { - static const int scratchCount = 256; - UINT32 scratch[scratchCount]; - EncodingProc next_ucs4_proc = find_encoding_proc(encoding); - for (int baseGlyph = 0; baseGlyph < glyphCount; baseGlyph += scratchCount) { - int glyphsLeft = glyphCount - baseGlyph; - int limit = SkTMin(glyphsLeft, scratchCount); - for (int i = 0; i < limit; ++i) { - scratch[i] = next_ucs4_proc(&chars); - } - fDWriteFontFace->GetGlyphIndices(scratch, limit, &glyphs[baseGlyph]); - } - break; - } - case SkTypeface::kUTF32_Encoding: { - const UINT32* utf32 = reinterpret_cast(chars); - fDWriteFontFace->GetGlyphIndices(utf32, glyphCount, glyphs); - break; - } - default: - SK_ABORT("Invalid Text Encoding"); - } - - for (int i = 0; i < glyphCount; ++i) { - if (0 == glyphs[i]) { - return i; - } - } - return glyphCount; +void DWriteFontTypeface::onCharsToGlyphs(const SkUnichar uni[], int count, + SkGlyphID glyphs[]) const { + fDWriteFontFace->GetGlyphIndices((const UINT32*)uni, count, glyphs); } int DWriteFontTypeface::onCountGlyphs() const { diff --git a/src/ports/SkTypeface_win_dw.h b/src/ports/SkTypeface_win_dw.h index 855ef79d76..0e11333bba 100644 --- a/src/ports/SkTypeface_win_dw.h +++ b/src/ports/SkTypeface_win_dw.h @@ -116,8 +116,7 @@ protected: void getGlyphToUnicodeMap(SkUnichar* glyphToUnicode) const override; std::unique_ptr onGetAdvancedMetrics() const override; void onGetFontDescriptor(SkFontDescriptor*, bool*) const override; - int onCharsToGlyphs(const void* chars, Encoding encoding, - uint16_t glyphs[], int glyphCount) const override; + void onCharsToGlyphs(const SkUnichar* chars, int count, SkGlyphID glyphs[]) const override; int onCountGlyphs() const override; int onGetUPEM() const override; void onGetFamilyName(SkString* familyName) const override; diff --git a/tests/FontHostTest.cpp b/tests/FontHostTest.cpp index c9846a6c87..0b70ac67bc 100644 --- a/tests/FontHostTest.cpp +++ b/tests/FontHostTest.cpp @@ -69,50 +69,6 @@ static void test_countGlyphs(skiatest::Reporter* reporter, const sk_sp face) { - uint16_t paintGlyphIds[256]; - uint16_t faceGlyphIds[256]; - - for (size_t testIndex = 0; testIndex < SK_ARRAY_COUNT(charsToGlyphs_TestData); ++testIndex) { - CharsToGlyphs_TestData& test = charsToGlyphs_TestData[testIndex]; - SkTextEncoding encoding = static_cast(test.typefaceEncoding); - - SkFont font(face); - font.textToGlyphs(test.chars, test.charsByteLength, encoding, - paintGlyphIds, SK_ARRAY_COUNT(paintGlyphIds)); - - face->charsToGlyphs(test.chars, test.typefaceEncoding, faceGlyphIds, test.charCount); - - for (int i = 0; i < test.charCount; ++i) { - SkString name; - face->getFamilyName(&name); - SkString a; - a.appendf("%s, paintGlyphIds[%d] = %d, faceGlyphIds[%d] = %d, face = %s", - test.name, i, (int)paintGlyphIds[i], i, (int)faceGlyphIds[i], name.c_str()); - REPORTER_ASSERT(reporter, paintGlyphIds[i] == faceGlyphIds[i], a.c_str()); - } - } -} - static void test_fontstream(skiatest::Reporter* reporter, SkStream* stream, int ttcIndex) { int n = SkFontStream::GetTableTags(stream, ttcIndex, nullptr); SkAutoTArray array(n); @@ -230,7 +186,6 @@ static void test_tables(skiatest::Reporter* reporter) { test_tables(reporter, face); test_unitsPerEm(reporter, face); test_countGlyphs(reporter, face); - test_charsToGlyphs(reporter, face); } } } diff --git a/tests/FontMgrTest.cpp b/tests/FontMgrTest.cpp index 67867b54dd..c0d8b492ee 100644 --- a/tests/FontMgrTest.cpp +++ b/tests/FontMgrTest.cpp @@ -136,12 +136,8 @@ static void test_matchStyleCSS3(skiatest::Reporter* reporter) { return nullptr; } void onGetFontDescriptor(SkFontDescriptor*, bool*) const override { } - virtual int onCharsToGlyphs(const void* chars, Encoding encoding, - uint16_t glyphs[], int glyphCount) const override { - if (glyphs && glyphCount > 0) { - sk_bzero(glyphs, glyphCount * sizeof(glyphs[0])); - } - return 0; + void onCharsToGlyphs(const SkUnichar* chars, int count, SkGlyphID glyphs[]) const override { + sk_bzero(glyphs, count * sizeof(glyphs[0])); } int onCountGlyphs() const override { return 0; } int onGetUPEM() const override { return 0; } diff --git a/tests/PaintTest.cpp b/tests/PaintTest.cpp index f22aaf5ef5..503bd49786 100644 --- a/tests/PaintTest.cpp +++ b/tests/PaintTest.cpp @@ -21,90 +21,6 @@ #include "Test.h" #undef ASSERT -static size_t uni_to_utf8(const SkUnichar src[], void* dst, int count) { - char* u8 = (char*)dst; - for (int i = 0; i < count; ++i) { - int n = SkToInt(SkUTF::ToUTF8(src[i], u8)); - u8 += n; - } - return u8 - (char*)dst; -} - -static size_t uni_to_utf16(const SkUnichar src[], void* dst, int count) { - uint16_t* u16 = (uint16_t*)dst; - for (int i = 0; i < count; ++i) { - int n = SkToInt(SkUTF::ToUTF16(src[i], u16)); - u16 += n; - } - return (char*)u16 - (char*)dst; -} - -static size_t uni_to_utf32(const SkUnichar src[], void* dst, int count) { - SkUnichar* u32 = (SkUnichar*)dst; - if (src != u32) { - memcpy(u32, src, count * sizeof(SkUnichar)); - } - return count * sizeof(SkUnichar); -} - -static int find_first_zero(const uint16_t glyphs[], int count) { - for (int i = 0; i < count; ++i) { - if (0 == glyphs[i]) { - return i; - } - } - return count; -} - -DEF_TEST(Paint_cmap, reporter) { - // need to implement charsToGlyphs on other backends (e.g. linux, win) - // before we can run this tests everywhere - return; - - static const int NGLYPHS = 64; - - SkUnichar src[NGLYPHS]; - SkUnichar dst[NGLYPHS]; // used for utf8, utf16, utf32 storage - - static const struct { - size_t (*fSeedTextProc)(const SkUnichar[], void* dst, int count); - SkTextEncoding fEncoding; - } gRec[] = { - { uni_to_utf8, kUTF8_SkTextEncoding }, - { uni_to_utf16, kUTF16_SkTextEncoding }, - { uni_to_utf32, kUTF32_SkTextEncoding }, - }; - - SkRandom rand; - SkFont font; - font.setTypeface(SkTypeface::MakeDefault()); - SkTypeface* face = font.getTypefaceOrDefault(); - - for (int i = 0; i < 1000; ++i) { - // generate some random text - for (int j = 0; j < NGLYPHS; ++j) { - src[j] = ' ' + j; - } - // inject some random chars, to sometimes abort early - src[rand.nextU() & 63] = rand.nextU() & 0xFFF; - - for (size_t k = 0; k < SK_ARRAY_COUNT(gRec); ++k) { - size_t len = gRec[k].fSeedTextProc(src, dst, NGLYPHS); - - uint16_t glyphs0[NGLYPHS], glyphs1[NGLYPHS]; - - int nglyphs = font.textToGlyphs(dst, len, gRec[k].fEncoding, glyphs0, NGLYPHS); - int first = face->charsToGlyphs(dst, (SkTypeface::Encoding)gRec[k].fEncoding, - glyphs1, NGLYPHS); - int index = find_first_zero(glyphs1, NGLYPHS); - - REPORTER_ASSERT(reporter, NGLYPHS == nglyphs); - REPORTER_ASSERT(reporter, index == first); - REPORTER_ASSERT(reporter, 0 == memcmp(glyphs0, glyphs1, NGLYPHS * sizeof(uint16_t))); - } - } -} - // temparary api for bicubic, just be sure we can set/clear it DEF_TEST(Paint_filterQuality, reporter) { SkPaint p0, p1; diff --git a/tests/SkRemoteGlyphCacheTest.cpp b/tests/SkRemoteGlyphCacheTest.cpp index 07cad45250..7e6cdeca0f 100644 --- a/tests/SkRemoteGlyphCacheTest.cpp +++ b/tests/SkRemoteGlyphCacheTest.cpp @@ -496,7 +496,8 @@ sk_sp make_blob_causing_fallback( SkASSERT(runBuffer.utf8text == nullptr); SkASSERT(runBuffer.clusters == nullptr); - glyphTf->charsToGlyphs(s, SkTypeface::kUTF8_Encoding, runBuffer.glyphs, runSize); + SkFont(sk_ref_sp(glyphTf)).textToGlyphs(s, strlen(s), SkTextEncoding::kUTF8, + runBuffer.glyphs, runSize); SkRect glyphBounds; font.getWidths(runBuffer.glyphs, 1, nullptr, &glyphBounds); diff --git a/tools/fonts/RandomScalerContext.cpp b/tools/fonts/RandomScalerContext.cpp index 3431c933d7..d20bf2b4da 100644 --- a/tools/fonts/RandomScalerContext.cpp +++ b/tools/fonts/RandomScalerContext.cpp @@ -182,11 +182,8 @@ void SkRandomTypeface::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal fProxy->getFontDescriptor(desc, isLocal); } -int SkRandomTypeface::onCharsToGlyphs(const void* chars, - Encoding encoding, - uint16_t glyphs[], - int glyphCount) const { - return fProxy->charsToGlyphs(chars, encoding, glyphs, glyphCount); +void SkRandomTypeface::onCharsToGlyphs(const SkUnichar* uni, int count, SkGlyphID glyphs[]) const { + fProxy->unicharsToGlyphs(uni, count, glyphs); } int SkRandomTypeface::onCountGlyphs() const { return fProxy->countGlyphs(); } diff --git a/tools/fonts/RandomScalerContext.h b/tools/fonts/RandomScalerContext.h index ea1b655fb1..d0eb02c10c 100644 --- a/tools/fonts/RandomScalerContext.h +++ b/tools/fonts/RandomScalerContext.h @@ -33,10 +33,7 @@ protected: sk_sp onMakeClone(const SkFontArguments& args) const override; void onGetFontDescriptor(SkFontDescriptor*, bool* isLocal) const override; - int onCharsToGlyphs(const void* chars, - Encoding encoding, - uint16_t glyphs[], - int glyphCount) const override; + void onCharsToGlyphs(const SkUnichar* chars, int count, SkGlyphID glyphs[]) const override; int onCountGlyphs() const override; int onGetUPEM() const override; diff --git a/tools/fonts/TestEmptyTypeface.h b/tools/fonts/TestEmptyTypeface.h index bd630d349a..dc358a7714 100644 --- a/tools/fonts/TestEmptyTypeface.h +++ b/tools/fonts/TestEmptyTypeface.h @@ -30,14 +30,8 @@ protected: return nullptr; } void onGetFontDescriptor(SkFontDescriptor*, bool*) const override {} - virtual int onCharsToGlyphs(const void* chars, - Encoding encoding, - uint16_t glyphs[], - int glyphCount) const override { - if (glyphs && glyphCount > 0) { - sk_bzero(glyphs, glyphCount * sizeof(glyphs[0])); - } - return 0; + void onCharsToGlyphs(const SkUnichar* chars, int count, SkGlyphID glyphs[]) const override { + sk_bzero(glyphs, count * sizeof(glyphs[0])); } int onCountGlyphs() const override { return 0; } int onGetUPEM() const override { return 0; } diff --git a/tools/fonts/TestSVGTypeface.cpp b/tools/fonts/TestSVGTypeface.cpp index 80ee05af0d..e180f96c39 100644 --- a/tools/fonts/TestSVGTypeface.cpp +++ b/tools/fonts/TestSVGTypeface.cpp @@ -150,27 +150,11 @@ void TestSVGTypeface::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) *isLocal = false; } -int TestSVGTypeface::onCharsToGlyphs(const void* chars, - Encoding encoding, - uint16_t glyphs[], - int glyphCount) const { - auto utf8 = (const char*)chars; - auto utf16 = (const uint16_t*)chars; - auto utf32 = (const SkUnichar*)chars; - - for (int i = 0; i < glyphCount; i++) { - SkUnichar ch; - switch (encoding) { - case kUTF8_Encoding: ch = SkUTF8_NextUnichar(&utf8); break; - case kUTF16_Encoding: ch = SkUTF16_NextUnichar(&utf16); break; - case kUTF32_Encoding: ch = *utf32++; break; - } - if (glyphs) { - SkGlyphID* g = fCMap.find(ch); - glyphs[i] = g ? *g : 0; - } +void TestSVGTypeface::onCharsToGlyphs(const SkUnichar uni[], int count, SkGlyphID glyphs[]) const { + for (int i = 0; i < count; i++) { + SkGlyphID* g = fCMap.find(uni[i]); + glyphs[i] = g ? *g : 0; } - return glyphCount; } void TestSVGTypeface::onGetFamilyName(SkString* familyName) const { *familyName = fName; } diff --git a/tools/fonts/TestSVGTypeface.h b/tools/fonts/TestSVGTypeface.h index ba0d7899d7..592418a82d 100644 --- a/tools/fonts/TestSVGTypeface.h +++ b/tools/fonts/TestSVGTypeface.h @@ -94,10 +94,7 @@ protected: void onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const override; - int onCharsToGlyphs(const void* chars, - Encoding encoding, - uint16_t glyphs[], - int glyphCount) const override; + void onCharsToGlyphs(const SkUnichar* chars, int count, SkGlyphID glyphs[]) const override; int onCountGlyphs() const override { return fGlyphCount; } diff --git a/tools/fonts/TestTypeface.cpp b/tools/fonts/TestTypeface.cpp index 05f5d79940..4641eefe45 100644 --- a/tools/fonts/TestTypeface.cpp +++ b/tools/fonts/TestTypeface.cpp @@ -132,26 +132,10 @@ void TestTypeface::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) co *isLocal = false; } -int TestTypeface::onCharsToGlyphs(const void* chars, - Encoding encoding, - SkGlyphID glyphs[], - int glyphCount) const { - auto utf8 = (const char*)chars; - auto utf16 = (const uint16_t*)chars; - auto utf32 = (const SkUnichar*)chars; - - for (int i = 0; i < glyphCount; ++i) { - SkUnichar ch; - switch (encoding) { - case kUTF8_Encoding: ch = SkUTF8_NextUnichar(&utf8); break; - case kUTF16_Encoding: ch = SkUTF16_NextUnichar(&utf16); break; - case kUTF32_Encoding: ch = *utf32++; break; - } - if (glyphs) { - glyphs[i] = fTestFont->glyphForUnichar(ch); - } +void TestTypeface::onCharsToGlyphs(const SkUnichar uni[], int count, SkGlyphID glyphs[]) const { + for (int i = 0; i < count; ++i) { + glyphs[i] = fTestFont->glyphForUnichar(uni[i]); } - return glyphCount; } void TestTypeface::onGetFamilyName(SkString* familyName) const { *familyName = fTestFont->fName; } diff --git a/tools/fonts/TestTypeface.h b/tools/fonts/TestTypeface.h index 8ea837f65e..7dcd574020 100644 --- a/tools/fonts/TestTypeface.h +++ b/tools/fonts/TestTypeface.h @@ -83,10 +83,7 @@ protected: void onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const override; - int onCharsToGlyphs(const void* chars, - Encoding encoding, - uint16_t glyphs[], - int glyphCount) const override; + void onCharsToGlyphs(const SkUnichar* chars, int count, SkGlyphID glyphs[]) const override; int onCountGlyphs() const override { return (int)fTestFont->fCharCodesCount; }