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