SkAdvancedTypefaceMetrics.cpp revision ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976e
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#ifdef SK_BUILD_FOR_UNIX 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 28namespace skia_advanced_typeface_metrics_utils { 29 30template <typename Data> 31void resetRange(SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* range, 32 int startId) { 33 range->fStartId = startId; 34 range->fAdvance.setCount(0); 35} 36 37template <typename Data> 38SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* appendRange( 39 SkTScopedPtr<SkAdvancedTypefaceMetrics::AdvanceMetric<Data> >* nextSlot, 40 int startId) { 41 nextSlot->reset(new SkAdvancedTypefaceMetrics::AdvanceMetric<Data>); 42 resetRange(nextSlot->get(), startId); 43 return nextSlot->get(); 44} 45 46template <typename Data> 47void finishRange( 48 SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* range, 49 int endId, 50 typename SkAdvancedTypefaceMetrics::AdvanceMetric<Data>::MetricType 51 type) { 52 range->fEndId = endId; 53 range->fType = type; 54 int newLength; 55 if (type == SkAdvancedTypefaceMetrics::AdvanceMetric<Data>::kRange) { 56 newLength = endId - range->fStartId + 1; 57 } else { 58 newLength = 1; 59 } 60 SkASSERT(range->fAdvance.count() >= newLength); 61 range->fAdvance.setCount(newLength); 62} 63 64template <typename Data, typename FontHandle> 65SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* getAdvanceData( 66 FontHandle fontHandle, 67 int num_glyphs, 68 bool (*getAdvance)(FontHandle fontHandle, int gId, Data* data)) { 69 // Assuming that an ASCII representation of a width or a glyph id is, 70 // on average, 3 characters long gives the following cut offs for 71 // using different range types: 72 // When currently in a range 73 // - Removing 4 0's is a win 74 // - Removing 5 repeats is a win 75 // When not currently in a range 76 // - Removing 1 0 is a win 77 // - Removing 3 repeats is a win 78 79 SkTScopedPtr<SkAdvancedTypefaceMetrics::AdvanceMetric<Data> > result; 80 SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* curRange; 81 SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* prevRange = NULL; 82 curRange = appendRange(&result, 0); 83 Data lastAdvance = SK_MinS16; 84 int repeats = 0; 85 for (int gId = 0; gId <= num_glyphs; gId++) { 86 Data advance; 87 if (gId < num_glyphs) { 88 SkAssertResult(getAdvance(fontHandle, gId, &advance)); 89 } else { 90 advance = SK_MinS16; 91 } 92 if (advance == lastAdvance) { 93 repeats++; 94 } else if (curRange->fAdvance.count() == repeats + 1) { 95 if (lastAdvance == 0 && repeats >= 0) { 96 resetRange(curRange, gId); 97 } else if (repeats >= 2) { 98 finishRange(curRange, gId - 1, 99 SkAdvancedTypefaceMetrics::WidthRange::kRun); 100 prevRange = curRange; 101 curRange = appendRange(&curRange->fNext, gId); 102 } 103 repeats = 0; 104 } else { 105 if (lastAdvance == 0 && repeats >= 3) { 106 finishRange(curRange, gId - repeats - 2, 107 SkAdvancedTypefaceMetrics::WidthRange::kRange); 108 prevRange = curRange; 109 curRange = appendRange(&curRange->fNext, gId); 110 } else if (repeats >= 4) { 111 finishRange(curRange, gId - repeats - 2, 112 SkAdvancedTypefaceMetrics::WidthRange::kRange); 113 curRange = appendRange(&curRange->fNext, gId - repeats - 1); 114 curRange->fAdvance.append(1, &lastAdvance); 115 finishRange(curRange, gId - 1, 116 SkAdvancedTypefaceMetrics::WidthRange::kRun); 117 prevRange = curRange; 118 curRange = appendRange(&curRange->fNext, gId); 119 } 120 repeats = 0; 121 } 122 curRange->fAdvance.append(1, &advance); 123 lastAdvance = advance; 124 } 125 if (curRange->fStartId == num_glyphs) { 126 SkASSERT(prevRange); 127 SkASSERT(prevRange->fNext->fStartId == num_glyphs); 128 prevRange->fNext.reset(); 129 } else { 130 finishRange(curRange, num_glyphs - 1, 131 SkAdvancedTypefaceMetrics::WidthRange::kRange); 132 } 133 return result.release(); 134} 135 136// Make AdvanceMetric template functions available for linking with typename 137// WidthRange and VerticalAdvanceRange. 138#if defined(SK_BUILD_FOR_WIN) 139template SkAdvancedTypefaceMetrics::WidthRange* getAdvanceData( 140 HDC hdc, 141 int num_glyphs, 142 bool (*getAdvance)(HDC hdc, int gId, int16_t* data)); 143#elif defined(SK_BUILD_FOR_UNIX) 144template SkAdvancedTypefaceMetrics::WidthRange* getAdvanceData( 145 FT_Face face, 146 int num_glyphs, 147 bool (*getAdvance)(FT_Face face, int gId, int16_t* data)); 148#elif defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS) 149template SkAdvancedTypefaceMetrics::WidthRange* getAdvanceData( 150 CTFontRef ctFont, 151 int num_glyphs, 152 bool (*getAdvance)(CTFontRef ctFont, int gId, int16_t* data)); 153#endif 154template void resetRange( 155 SkAdvancedTypefaceMetrics::WidthRange* range, 156 int startId); 157template SkAdvancedTypefaceMetrics::WidthRange* appendRange( 158 SkTScopedPtr<SkAdvancedTypefaceMetrics::WidthRange >* nextSlot, 159 int startId); 160template void finishRange<int16_t>( 161 SkAdvancedTypefaceMetrics::WidthRange* range, 162 int endId, 163 SkAdvancedTypefaceMetrics::WidthRange::MetricType type); 164 165template void resetRange( 166 SkAdvancedTypefaceMetrics::VerticalAdvanceRange* range, 167 int startId); 168template SkAdvancedTypefaceMetrics::VerticalAdvanceRange* appendRange( 169 SkTScopedPtr<SkAdvancedTypefaceMetrics::VerticalAdvanceRange >* 170 nextSlot, 171 int startId); 172template void finishRange<SkAdvancedTypefaceMetrics::VerticalMetric>( 173 SkAdvancedTypefaceMetrics::VerticalAdvanceRange* range, 174 int endId, 175 SkAdvancedTypefaceMetrics::VerticalAdvanceRange::MetricType type); 176 177} // namespace skia_advanced_typeface_metrics_utils 178