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_WIN)
     14 #include <dwrite.h>
     15 #endif
     16 
     17 #if defined(SK_BUILD_FOR_UNIX) || defined(SK_BUILD_FOR_ANDROID)
     18 // forward declare structs needed for getAdvanceData() template for freetype
     19 struct FT_FaceRec;
     20 typedef struct FT_FaceRec_* FT_Face;
     21 #endif
     22 
     23 #ifdef SK_BUILD_FOR_MAC
     24 #import <ApplicationServices/ApplicationServices.h>
     25 #endif
     26 
     27 #ifdef SK_BUILD_FOR_IOS
     28 #include <CoreText/CoreText.h>
     29 #include <CoreGraphics/CoreGraphics.h>
     30 #include <CoreFoundation/CoreFoundation.h>
     31 #endif
     32 
     33 namespace skia_advanced_typeface_metrics_utils {
     34 
     35 const int16_t kInvalidAdvance = SK_MinS16;
     36 const int16_t kDontCareAdvance = SK_MinS16 + 1;
     37 
     38 template <typename Data>
     39 void stripUninterestingTrailingAdvancesFromRange(
     40                                                  SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* range) {
     41     SkASSERT(false);
     42 }
     43 
     44 template <>
     45 void stripUninterestingTrailingAdvancesFromRange<int16_t>(
     46                                                           SkAdvancedTypefaceMetrics::AdvanceMetric<int16_t>* range) {
     47     SkASSERT(range);
     48 
     49     int expectedAdvanceCount = range->fEndId - range->fStartId + 1;
     50     if (range->fAdvance.count() < expectedAdvanceCount) {
     51         return;
     52     }
     53 
     54     for (int i = expectedAdvanceCount - 1; i >= 0; --i) {
     55         if (range->fAdvance[i] != kDontCareAdvance &&
     56             range->fAdvance[i] != kInvalidAdvance &&
     57             range->fAdvance[i] != 0) {
     58             range->fEndId = range->fStartId + i;
     59             break;
     60         }
     61     }
     62 }
     63 
     64 template <typename Data>
     65 void resetRange(SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* range,
     66                 int startId) {
     67     range->fStartId = startId;
     68     range->fAdvance.setCount(0);
     69 }
     70 
     71 template <typename Data>
     72 SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* appendRange(
     73         SkAutoTDelete<SkAdvancedTypefaceMetrics::AdvanceMetric<Data> >* nextSlot,
     74         int startId) {
     75     nextSlot->reset(new SkAdvancedTypefaceMetrics::AdvanceMetric<Data>);
     76     resetRange(nextSlot->get(), startId);
     77     return nextSlot->get();
     78 }
     79 
     80 template <typename Data>
     81 void zeroWildcardsInRange(
     82                           SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* range) {
     83     SkASSERT(false);
     84 }
     85 
     86 template <>
     87 void zeroWildcardsInRange<int16_t>(
     88                                    SkAdvancedTypefaceMetrics::AdvanceMetric<int16_t>* range) {
     89     SkASSERT(range);
     90     if (range->fType != SkAdvancedTypefaceMetrics::WidthRange::kRange) {
     91         return;
     92     }
     93     SkASSERT(range->fAdvance.count() == range->fEndId - range->fStartId + 1);
     94 
     95     // Zero out wildcards.
     96     for (int i = 0; i < range->fAdvance.count(); ++i) {
     97         if (range->fAdvance[i] == kDontCareAdvance) {
     98             range->fAdvance[i] = 0;
     99         }
    100     }
    101 }
    102 
    103 template <typename Data>
    104 void finishRange(
    105         SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* range,
    106         int endId,
    107         typename SkAdvancedTypefaceMetrics::AdvanceMetric<Data>::MetricType
    108                 type) {
    109     range->fEndId = endId;
    110     range->fType = type;
    111     stripUninterestingTrailingAdvancesFromRange(range);
    112     int newLength;
    113     if (type == SkAdvancedTypefaceMetrics::AdvanceMetric<Data>::kRange) {
    114         newLength = range->fEndId - range->fStartId + 1;
    115     } else {
    116         if (range->fEndId == range->fStartId) {
    117             range->fType =
    118                 SkAdvancedTypefaceMetrics::AdvanceMetric<Data>::kRange;
    119         }
    120         newLength = 1;
    121     }
    122     SkASSERT(range->fAdvance.count() >= newLength);
    123     range->fAdvance.setCount(newLength);
    124     zeroWildcardsInRange(range);
    125 }
    126 
    127 template <typename Data, typename FontHandle>
    128 SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* getAdvanceData(
    129         FontHandle fontHandle,
    130         int num_glyphs,
    131         const uint32_t* subsetGlyphIDs,
    132         uint32_t subsetGlyphIDsLength,
    133         bool (*getAdvance)(FontHandle fontHandle, int gId, Data* data)) {
    134     // Assuming that on average, the ASCII representation of an advance plus
    135     // a space is 8 characters and the ASCII representation of a glyph id is 3
    136     // characters, then the following cut offs for using different range types
    137     // apply:
    138     // The cost of stopping and starting the range is 7 characers
    139     //  a. Removing 4 0's or don't care's is a win
    140     // The cost of stopping and starting the range plus a run is 22
    141     // characters
    142     //  b. Removing 3 repeating advances is a win
    143     //  c. Removing 2 repeating advances and 3 don't cares is a win
    144     // When not currently in a range the cost of a run over a range is 16
    145     // characaters, so:
    146     //  d. Removing a leading 0/don't cares is a win because it is omitted
    147     //  e. Removing 2 repeating advances is a win
    148 
    149     SkAutoTDelete<SkAdvancedTypefaceMetrics::AdvanceMetric<Data> > result;
    150     SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* curRange;
    151     SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* prevRange = NULL;
    152     Data lastAdvance = kInvalidAdvance;
    153     int repeatedAdvances = 0;
    154     int wildCardsInRun = 0;
    155     int trailingWildCards = 0;
    156     uint32_t subsetIndex = 0;
    157 
    158     // Limit the loop count to glyph id ranges provided.
    159     int firstIndex = 0;
    160     int lastIndex = num_glyphs;
    161     if (subsetGlyphIDs) {
    162         firstIndex = static_cast<int>(subsetGlyphIDs[0]);
    163         lastIndex =
    164                 static_cast<int>(subsetGlyphIDs[subsetGlyphIDsLength - 1]) + 1;
    165     }
    166     curRange = appendRange(&result, firstIndex);
    167 
    168     for (int gId = firstIndex; gId <= lastIndex; gId++) {
    169         Data advance = kInvalidAdvance;
    170         if (gId < lastIndex) {
    171             // Get glyph id only when subset is NULL, or the id is in subset.
    172             SkASSERT(!subsetGlyphIDs || (subsetIndex < subsetGlyphIDsLength &&
    173                     static_cast<uint32_t>(gId) <= subsetGlyphIDs[subsetIndex]));
    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.free();
    249     } else {
    250         finishRange(curRange, lastIndex - 1,
    251                     SkAdvancedTypefaceMetrics::WidthRange::kRange);
    252     }
    253     return result.detach();
    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         SkAutoTDelete<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         SkAutoTDelete<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