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