Home | History | Annotate | Download | only in core
      1 
      2 /*
      3  * Copyright 2011 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 
     10 #include "SkAdvancedTypefaceMetrics.h"
     11 #include "SkTypes.h"
     12 
     13 SK_DEFINE_INST_COUNT(SkAdvancedTypefaceMetrics)
     14 
     15 #if defined(SK_BUILD_FOR_WIN)
     16 #include <dwrite.h>
     17 #endif
     18 
     19 #if defined(SK_BUILD_FOR_UNIX) || defined(SK_BUILD_FOR_ANDROID)
     20 // forward declare structs needed for getAdvanceData() template for freetype
     21 struct FT_FaceRec;
     22 typedef struct FT_FaceRec_* FT_Face;
     23 #endif
     24 
     25 #ifdef SK_BUILD_FOR_MAC
     26 #import <ApplicationServices/ApplicationServices.h>
     27 #endif
     28 
     29 #ifdef SK_BUILD_FOR_IOS
     30 #include <CoreText/CoreText.h>
     31 #include <CoreGraphics/CoreGraphics.h>
     32 #include <CoreFoundation/CoreFoundation.h>
     33 #endif
     34 
     35 namespace skia_advanced_typeface_metrics_utils {
     36 
     37 const int16_t kInvalidAdvance = SK_MinS16;
     38 const int16_t kDontCareAdvance = SK_MinS16 + 1;
     39 
     40 template <typename Data>
     41 void stripUninterestingTrailingAdvancesFromRange(
     42                                                  SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* range) {
     43     SkASSERT(false);
     44 }
     45 
     46 template <>
     47 void stripUninterestingTrailingAdvancesFromRange<int16_t>(
     48                                                           SkAdvancedTypefaceMetrics::AdvanceMetric<int16_t>* range) {
     49     SkASSERT(range);
     50 
     51     int expectedAdvanceCount = range->fEndId - range->fStartId + 1;
     52     if (range->fAdvance.count() < expectedAdvanceCount) {
     53         return;
     54     }
     55 
     56     for (int i = expectedAdvanceCount - 1; i >= 0; --i) {
     57         if (range->fAdvance[i] != kDontCareAdvance &&
     58             range->fAdvance[i] != kInvalidAdvance &&
     59             range->fAdvance[i] != 0) {
     60             range->fEndId = range->fStartId + i;
     61             break;
     62         }
     63     }
     64 }
     65 
     66 template <typename Data>
     67 void resetRange(SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* range,
     68                 int startId) {
     69     range->fStartId = startId;
     70     range->fAdvance.setCount(0);
     71 }
     72 
     73 template <typename Data>
     74 SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* appendRange(
     75         SkTScopedPtr<SkAdvancedTypefaceMetrics::AdvanceMetric<Data> >* nextSlot,
     76         int startId) {
     77     nextSlot->reset(new SkAdvancedTypefaceMetrics::AdvanceMetric<Data>);
     78     resetRange(nextSlot->get(), startId);
     79     return nextSlot->get();
     80 }
     81 
     82 template <typename Data>
     83 void zeroWildcardsInRange(
     84                           SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* range) {
     85     SkASSERT(false);
     86 }
     87 
     88 template <>
     89 void zeroWildcardsInRange<int16_t>(
     90                                    SkAdvancedTypefaceMetrics::AdvanceMetric<int16_t>* range) {
     91     SkASSERT(range);
     92     if (range->fType != SkAdvancedTypefaceMetrics::WidthRange::kRange) {
     93         return;
     94     }
     95     SkASSERT(range->fAdvance.count() == range->fEndId - range->fStartId + 1);
     96 
     97     // Zero out wildcards.
     98     for (int i = 0; i < range->fAdvance.count(); ++i) {
     99         if (range->fAdvance[i] == kDontCareAdvance) {
    100             range->fAdvance[i] = 0;
    101         }
    102     }
    103 }
    104 
    105 template <typename Data>
    106 void finishRange(
    107         SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* range,
    108         int endId,
    109         typename SkAdvancedTypefaceMetrics::AdvanceMetric<Data>::MetricType
    110                 type) {
    111     range->fEndId = endId;
    112     range->fType = type;
    113     stripUninterestingTrailingAdvancesFromRange(range);
    114     int newLength;
    115     if (type == SkAdvancedTypefaceMetrics::AdvanceMetric<Data>::kRange) {
    116         newLength = range->fEndId - range->fStartId + 1;
    117     } else {
    118         if (range->fEndId == range->fStartId) {
    119             range->fType =
    120                 SkAdvancedTypefaceMetrics::AdvanceMetric<Data>::kRange;
    121         }
    122         newLength = 1;
    123     }
    124     SkASSERT(range->fAdvance.count() >= newLength);
    125     range->fAdvance.setCount(newLength);
    126     zeroWildcardsInRange(range);
    127 }
    128 
    129 template <typename Data, typename FontHandle>
    130 SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* getAdvanceData(
    131         FontHandle fontHandle,
    132         int num_glyphs,
    133         const uint32_t* subsetGlyphIDs,
    134         uint32_t subsetGlyphIDsLength,
    135         bool (*getAdvance)(FontHandle fontHandle, int gId, Data* data)) {
    136     // Assuming that on average, the ASCII representation of an advance plus
    137     // a space is 8 characters and the ASCII representation of a glyph id is 3
    138     // characters, then the following cut offs for using different range types
    139     // apply:
    140     // The cost of stopping and starting the range is 7 characers
    141     //  a. Removing 4 0's or don't care's is a win
    142     // The cost of stopping and starting the range plus a run is 22
    143     // characters
    144     //  b. Removing 3 repeating advances is a win
    145     //  c. Removing 2 repeating advances and 3 don't cares is a win
    146     // When not currently in a range the cost of a run over a range is 16
    147     // characaters, so:
    148     //  d. Removing a leading 0/don't cares is a win because it is omitted
    149     //  e. Removing 2 repeating advances is a win
    150 
    151     SkTScopedPtr<SkAdvancedTypefaceMetrics::AdvanceMetric<Data> > result;
    152     SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* curRange;
    153     SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* prevRange = NULL;
    154     Data lastAdvance = kInvalidAdvance;
    155     int repeatedAdvances = 0;
    156     int wildCardsInRun = 0;
    157     int trailingWildCards = 0;
    158     uint32_t subsetIndex = 0;
    159 
    160     // Limit the loop count to glyph id ranges provided.
    161     int firstIndex = 0;
    162     int lastIndex = num_glyphs;
    163     if (subsetGlyphIDs) {
    164         firstIndex = static_cast<int>(subsetGlyphIDs[0]);
    165         lastIndex =
    166                 static_cast<int>(subsetGlyphIDs[subsetGlyphIDsLength - 1]) + 1;
    167     }
    168     curRange = appendRange(&result, firstIndex);
    169 
    170     for (int gId = firstIndex; gId <= lastIndex; gId++) {
    171         Data advance = kInvalidAdvance;
    172         if (gId < lastIndex) {
    173             // Get glyph id only when subset is NULL, or the id is in subset.
    174             if (!subsetGlyphIDs ||
    175                 (subsetIndex < subsetGlyphIDsLength &&
    176                  static_cast<uint32_t>(gId) == subsetGlyphIDs[subsetIndex])) {
    177                 SkAssertResult(getAdvance(fontHandle, gId, &advance));
    178                 ++subsetIndex;
    179             } else {
    180                 advance = kDontCareAdvance;
    181             }
    182         }
    183         if (advance == lastAdvance) {
    184             repeatedAdvances++;
    185             trailingWildCards = 0;
    186         } else if (advance == kDontCareAdvance) {
    187             wildCardsInRun++;
    188             trailingWildCards++;
    189         } else if (curRange->fAdvance.count() ==
    190                    repeatedAdvances + 1 + wildCardsInRun) {  // All in run.
    191             if (lastAdvance == 0) {
    192                 resetRange(curRange, gId);
    193                 trailingWildCards = 0;
    194             } else if (repeatedAdvances + 1 >= 2 || trailingWildCards >= 4) {
    195                 finishRange(curRange, gId - 1,
    196                             SkAdvancedTypefaceMetrics::WidthRange::kRun);
    197                 prevRange = curRange;
    198                 curRange = appendRange(&curRange->fNext, gId);
    199                 trailingWildCards = 0;
    200             }
    201             repeatedAdvances = 0;
    202             wildCardsInRun = trailingWildCards;
    203             trailingWildCards = 0;
    204         } else {
    205             if (lastAdvance == 0 &&
    206                     repeatedAdvances + 1 + wildCardsInRun >= 4) {
    207                 finishRange(curRange,
    208                             gId - repeatedAdvances - wildCardsInRun - 2,
    209                             SkAdvancedTypefaceMetrics::WidthRange::kRange);
    210                 prevRange = curRange;
    211                 curRange = appendRange(&curRange->fNext, gId);
    212                 trailingWildCards = 0;
    213             } else if (trailingWildCards >= 4 && repeatedAdvances + 1 < 2) {
    214                 finishRange(curRange,
    215                             gId - trailingWildCards - 1,
    216                             SkAdvancedTypefaceMetrics::WidthRange::kRange);
    217                 prevRange = curRange;
    218                 curRange = appendRange(&curRange->fNext, gId);
    219                 trailingWildCards = 0;
    220             } else if (lastAdvance != 0 &&
    221                        (repeatedAdvances + 1 >= 3 ||
    222                         (repeatedAdvances + 1 >= 2 && wildCardsInRun >= 3))) {
    223                 finishRange(curRange,
    224                             gId - repeatedAdvances - wildCardsInRun - 2,
    225                             SkAdvancedTypefaceMetrics::WidthRange::kRange);
    226                 curRange =
    227                     appendRange(&curRange->fNext,
    228                                 gId - repeatedAdvances - wildCardsInRun - 1);
    229                 curRange->fAdvance.append(1, &lastAdvance);
    230                 finishRange(curRange, gId - 1,
    231                             SkAdvancedTypefaceMetrics::WidthRange::kRun);
    232                 prevRange = curRange;
    233                 curRange = appendRange(&curRange->fNext, gId);
    234                 trailingWildCards = 0;
    235             }
    236             repeatedAdvances = 0;
    237             wildCardsInRun = trailingWildCards;
    238             trailingWildCards = 0;
    239         }
    240         curRange->fAdvance.append(1, &advance);
    241         if (advance != kDontCareAdvance) {
    242             lastAdvance = advance;
    243         }
    244     }
    245     if (curRange->fStartId == lastIndex) {
    246         SkASSERT(prevRange);
    247         SkASSERT(prevRange->fNext->fStartId == lastIndex);
    248         prevRange->fNext.reset();
    249     } else {
    250         finishRange(curRange, lastIndex - 1,
    251                     SkAdvancedTypefaceMetrics::WidthRange::kRange);
    252     }
    253     return result.release();
    254 }
    255 
    256 // Make AdvanceMetric template functions available for linking with typename
    257 // WidthRange and VerticalAdvanceRange.
    258 #if defined(SK_BUILD_FOR_WIN)
    259 template SkAdvancedTypefaceMetrics::WidthRange* getAdvanceData(
    260         HDC hdc,
    261         int num_glyphs,
    262         const uint32_t* subsetGlyphIDs,
    263         uint32_t subsetGlyphIDsLength,
    264         bool (*getAdvance)(HDC hdc, int gId, int16_t* data));
    265 template SkAdvancedTypefaceMetrics::WidthRange* getAdvanceData(
    266         IDWriteFontFace* fontFace,
    267         int num_glyphs,
    268         const uint32_t* subsetGlyphIDs,
    269         uint32_t subsetGlyphIDsLength,
    270         bool (*getAdvance)(IDWriteFontFace* fontFace, int gId, int16_t* data));
    271 #elif defined(SK_BUILD_FOR_UNIX) || defined(SK_BUILD_FOR_ANDROID)
    272 template SkAdvancedTypefaceMetrics::WidthRange* getAdvanceData(
    273         FT_Face face,
    274         int num_glyphs,
    275         const uint32_t* subsetGlyphIDs,
    276         uint32_t subsetGlyphIDsLength,
    277         bool (*getAdvance)(FT_Face face, int gId, int16_t* data));
    278 #elif defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
    279 template SkAdvancedTypefaceMetrics::WidthRange* getAdvanceData(
    280         CTFontRef ctFont,
    281         int num_glyphs,
    282         const uint32_t* subsetGlyphIDs,
    283         uint32_t subsetGlyphIDsLength,
    284         bool (*getAdvance)(CTFontRef ctFont, int gId, int16_t* data));
    285 #endif
    286 template void resetRange(
    287         SkAdvancedTypefaceMetrics::WidthRange* range,
    288         int startId);
    289 template SkAdvancedTypefaceMetrics::WidthRange* appendRange(
    290         SkTScopedPtr<SkAdvancedTypefaceMetrics::WidthRange >* nextSlot,
    291         int startId);
    292 template void finishRange<int16_t>(
    293         SkAdvancedTypefaceMetrics::WidthRange* range,
    294         int endId,
    295         SkAdvancedTypefaceMetrics::WidthRange::MetricType type);
    296 
    297 template void resetRange(
    298         SkAdvancedTypefaceMetrics::VerticalAdvanceRange* range,
    299         int startId);
    300 template SkAdvancedTypefaceMetrics::VerticalAdvanceRange* appendRange(
    301         SkTScopedPtr<SkAdvancedTypefaceMetrics::VerticalAdvanceRange >*
    302             nextSlot,
    303         int startId);
    304 template void finishRange<SkAdvancedTypefaceMetrics::VerticalMetric>(
    305         SkAdvancedTypefaceMetrics::VerticalAdvanceRange* range,
    306         int endId,
    307         SkAdvancedTypefaceMetrics::VerticalAdvanceRange::MetricType type);
    308 
    309 // additional declaration needed for testing with a face of an unknown type
    310 template SkAdvancedTypefaceMetrics::WidthRange* getAdvanceData(
    311         void* fontData,
    312         int num_glyphs,
    313         const uint32_t* subsetGlyphIDs,
    314         uint32_t subsetGlyphIDsLength,
    315         bool (*getAdvance)(void* fontData, int gId, int16_t* data));
    316 
    317 } // namespace skia_advanced_typeface_metrics_utils
    318