/* * Copyright 2011 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "SkAdvancedTypefaceMetrics.h" #include "SkTypes.h" #if defined(SK_BUILD_FOR_WIN) #include #endif // forward declare structs needed for getAdvanceData() template for freetype struct FT_FaceRec_; typedef struct FT_FaceRec_* FT_Face; #ifdef SK_BUILD_FOR_MAC #import #endif #ifdef SK_BUILD_FOR_IOS #include #include #include #endif namespace skia_advanced_typeface_metrics_utils { const int16_t kInvalidAdvance = SK_MinS16; const int16_t kDontCareAdvance = SK_MinS16 + 1; template void stripUninterestingTrailingAdvancesFromRange( SkAdvancedTypefaceMetrics::AdvanceMetric* range) { SkASSERT(false); } template <> void stripUninterestingTrailingAdvancesFromRange( SkAdvancedTypefaceMetrics::AdvanceMetric* range) { SkASSERT(range); int expectedAdvanceCount = range->fEndId - range->fStartId + 1; if (range->fAdvance.count() < expectedAdvanceCount) { return; } for (int i = expectedAdvanceCount - 1; i >= 0; --i) { if (range->fAdvance[i] != kDontCareAdvance && range->fAdvance[i] != kInvalidAdvance && range->fAdvance[i] != 0) { range->fEndId = range->fStartId + i; break; } } } template void resetRange(SkAdvancedTypefaceMetrics::AdvanceMetric* range, int startId) { range->fStartId = startId; range->fAdvance.setCount(0); } template class AutoTDelete> SkAdvancedTypefaceMetrics::AdvanceMetric* appendRange( AutoTDelete >* nextSlot, int startId) { nextSlot->reset(new SkAdvancedTypefaceMetrics::AdvanceMetric); resetRange(nextSlot->get(), startId); return nextSlot->get(); } template void zeroWildcardsInRange( SkAdvancedTypefaceMetrics::AdvanceMetric* range) { SkASSERT(false); } template <> void zeroWildcardsInRange( SkAdvancedTypefaceMetrics::AdvanceMetric* range) { SkASSERT(range); if (range->fType != SkAdvancedTypefaceMetrics::WidthRange::kRange) { return; } SkASSERT(range->fAdvance.count() == range->fEndId - range->fStartId + 1); // Zero out wildcards. for (int i = 0; i < range->fAdvance.count(); ++i) { if (range->fAdvance[i] == kDontCareAdvance) { range->fAdvance[i] = 0; } } } template void finishRange( SkAdvancedTypefaceMetrics::AdvanceMetric* range, int endId, typename SkAdvancedTypefaceMetrics::AdvanceMetric::MetricType type) { range->fEndId = endId; range->fType = type; stripUninterestingTrailingAdvancesFromRange(range); int newLength; if (type == SkAdvancedTypefaceMetrics::AdvanceMetric::kRange) { newLength = range->fEndId - range->fStartId + 1; } else { if (range->fEndId == range->fStartId) { range->fType = SkAdvancedTypefaceMetrics::AdvanceMetric::kRange; } newLength = 1; } SkASSERT(range->fAdvance.count() >= newLength); range->fAdvance.setCount(newLength); zeroWildcardsInRange(range); } template SkAdvancedTypefaceMetrics::AdvanceMetric* getAdvanceData( FontHandle fontHandle, int num_glyphs, const uint32_t* subsetGlyphIDs, uint32_t subsetGlyphIDsLength, bool (*getAdvance)(FontHandle fontHandle, int gId, Data* data)) { // Assuming that on average, the ASCII representation of an advance plus // a space is 8 characters and the ASCII representation of a glyph id is 3 // characters, then the following cut offs for using different range types // apply: // The cost of stopping and starting the range is 7 characers // a. Removing 4 0's or don't care's is a win // The cost of stopping and starting the range plus a run is 22 // characters // b. Removing 3 repeating advances is a win // c. Removing 2 repeating advances and 3 don't cares is a win // When not currently in a range the cost of a run over a range is 16 // characaters, so: // d. Removing a leading 0/don't cares is a win because it is omitted // e. Removing 2 repeating advances is a win SkAutoTDelete > result; SkAdvancedTypefaceMetrics::AdvanceMetric* curRange; SkAdvancedTypefaceMetrics::AdvanceMetric* prevRange = nullptr; Data lastAdvance = kInvalidAdvance; int repeatedAdvances = 0; int wildCardsInRun = 0; int trailingWildCards = 0; uint32_t subsetIndex = 0; // Limit the loop count to glyph id ranges provided. int firstIndex = 0; int lastIndex = num_glyphs; if (subsetGlyphIDs) { firstIndex = static_cast(subsetGlyphIDs[0]); lastIndex = static_cast(subsetGlyphIDs[subsetGlyphIDsLength - 1]) + 1; } curRange = appendRange(&result, firstIndex); for (int gId = firstIndex; gId <= lastIndex; gId++) { Data advance = kInvalidAdvance; if (gId < lastIndex) { // Get glyph id only when subset is nullptr, or the id is in subset. SkASSERT(!subsetGlyphIDs || (subsetIndex < subsetGlyphIDsLength && static_cast(gId) <= subsetGlyphIDs[subsetIndex])); if (!subsetGlyphIDs || (subsetIndex < subsetGlyphIDsLength && static_cast(gId) == subsetGlyphIDs[subsetIndex])) { SkAssertResult(getAdvance(fontHandle, gId, &advance)); ++subsetIndex; } else { advance = kDontCareAdvance; } } if (advance == lastAdvance) { repeatedAdvances++; trailingWildCards = 0; } else if (advance == kDontCareAdvance) { wildCardsInRun++; trailingWildCards++; } else if (curRange->fAdvance.count() == repeatedAdvances + 1 + wildCardsInRun) { // All in run. if (lastAdvance == 0) { resetRange(curRange, gId); trailingWildCards = 0; } else if (repeatedAdvances + 1 >= 2 || trailingWildCards >= 4) { finishRange(curRange, gId - 1, SkAdvancedTypefaceMetrics::WidthRange::kRun); prevRange = curRange; curRange = appendRange(&curRange->fNext, gId); trailingWildCards = 0; } repeatedAdvances = 0; wildCardsInRun = trailingWildCards; trailingWildCards = 0; } else { if (lastAdvance == 0 && repeatedAdvances + 1 + wildCardsInRun >= 4) { finishRange(curRange, gId - repeatedAdvances - wildCardsInRun - 2, SkAdvancedTypefaceMetrics::WidthRange::kRange); prevRange = curRange; curRange = appendRange(&curRange->fNext, gId); trailingWildCards = 0; } else if (trailingWildCards >= 4 && repeatedAdvances + 1 < 2) { finishRange(curRange, gId - trailingWildCards - 1, SkAdvancedTypefaceMetrics::WidthRange::kRange); prevRange = curRange; curRange = appendRange(&curRange->fNext, gId); trailingWildCards = 0; } else if (lastAdvance != 0 && (repeatedAdvances + 1 >= 3 || (repeatedAdvances + 1 >= 2 && wildCardsInRun >= 3))) { finishRange(curRange, gId - repeatedAdvances - wildCardsInRun - 2, SkAdvancedTypefaceMetrics::WidthRange::kRange); curRange = appendRange(&curRange->fNext, gId - repeatedAdvances - wildCardsInRun - 1); curRange->fAdvance.append(1, &lastAdvance); finishRange(curRange, gId - 1, SkAdvancedTypefaceMetrics::WidthRange::kRun); prevRange = curRange; curRange = appendRange(&curRange->fNext, gId); trailingWildCards = 0; } repeatedAdvances = 0; wildCardsInRun = trailingWildCards; trailingWildCards = 0; } curRange->fAdvance.append(1, &advance); if (advance != kDontCareAdvance) { lastAdvance = advance; } } if (curRange->fStartId == lastIndex) { SkASSERT(prevRange); SkASSERT(prevRange->fNext->fStartId == lastIndex); prevRange->fNext.reset(); } else { finishRange(curRange, lastIndex - 1, SkAdvancedTypefaceMetrics::WidthRange::kRange); } return result.release(); } // Make AdvanceMetric template functions available for linking with typename // WidthRange and VerticalAdvanceRange. template SkAdvancedTypefaceMetrics::WidthRange* getAdvanceData( FT_Face face, int num_glyphs, const uint32_t* subsetGlyphIDs, uint32_t subsetGlyphIDsLength, bool (*getAdvance)(FT_Face face, int gId, int16_t* data)); #if defined(SK_BUILD_FOR_WIN) template SkAdvancedTypefaceMetrics::WidthRange* getAdvanceData( HDC hdc, int num_glyphs, const uint32_t* subsetGlyphIDs, uint32_t subsetGlyphIDsLength, bool (*getAdvance)(HDC hdc, int gId, int16_t* data)); template SkAdvancedTypefaceMetrics::WidthRange* getAdvanceData( IDWriteFontFace* fontFace, int num_glyphs, const uint32_t* subsetGlyphIDs, uint32_t subsetGlyphIDsLength, bool (*getAdvance)(IDWriteFontFace* fontFace, int gId, int16_t* data)); #elif defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS) template SkAdvancedTypefaceMetrics::WidthRange* getAdvanceData( CTFontRef ctFont, int num_glyphs, const uint32_t* subsetGlyphIDs, uint32_t subsetGlyphIDsLength, bool (*getAdvance)(CTFontRef ctFont, int gId, int16_t* data)); #endif template void resetRange( SkAdvancedTypefaceMetrics::WidthRange* range, int startId); template SkAdvancedTypefaceMetrics::WidthRange* appendRange( SkAutoTDelete* nextSlot, int startId); template void finishRange( SkAdvancedTypefaceMetrics::WidthRange* range, int endId, SkAdvancedTypefaceMetrics::WidthRange::MetricType type); template void resetRange( SkAdvancedTypefaceMetrics::VerticalAdvanceRange* range, int startId); template SkAdvancedTypefaceMetrics::VerticalAdvanceRange* appendRange( SkAutoTDelete* nextSlot, int startId); template void finishRange( SkAdvancedTypefaceMetrics::VerticalAdvanceRange* range, int endId, SkAdvancedTypefaceMetrics::VerticalAdvanceRange::MetricType type); // additional declaration needed for testing with a face of an unknown type template SkAdvancedTypefaceMetrics::WidthRange* getAdvanceData( void* fontData, int num_glyphs, const uint32_t* subsetGlyphIDs, uint32_t subsetGlyphIDsLength, bool (*getAdvance)(void* fontData, int gId, int16_t* data)); } // namespace skia_advanced_typeface_metrics_utils