SkAdvancedTypefaceMetrics.cpp revision 369ca40621a3adb502a95761e68fee825cab8c45
1/* 2 * Copyright (C) 2011 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "SkAdvancedTypefaceMetrics.h" 18#include "SkTypes.h" 19 20#ifdef SK_BUILD_FOR_UNIX 21#include <ft2build.h> 22#include FT_FREETYPE_H 23#endif 24 25namespace skia_advanced_typeface_metrics_utils { 26 27template <typename Data> 28void resetRange(SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* range, 29 int startId) { 30 range->fStartId = startId; 31 range->fAdvance.setCount(0); 32} 33 34template <typename Data> 35SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* appendRange( 36 SkTScopedPtr<SkAdvancedTypefaceMetrics::AdvanceMetric<Data> >* nextSlot, 37 int startId) { 38 nextSlot->reset(new SkAdvancedTypefaceMetrics::AdvanceMetric<Data>); 39 resetRange(nextSlot->get(), startId); 40 return nextSlot->get(); 41} 42 43template <typename Data> 44void finishRange( 45 SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* range, 46 int endId, 47 typename SkAdvancedTypefaceMetrics::AdvanceMetric<Data>::MetricType 48 type) { 49 range->fEndId = endId; 50 range->fType = type; 51 int newLength; 52 if (type == SkAdvancedTypefaceMetrics::AdvanceMetric<Data>::kRange) { 53 newLength = endId - range->fStartId + 1; 54 } else { 55 newLength = 1; 56 } 57 SkASSERT(range->fAdvance.count() >= newLength); 58 range->fAdvance.setCount(newLength); 59} 60 61template <typename Data, typename FontHandle> 62SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* getAdvanceData( 63 FontHandle fontHandle, 64 int num_glyphs, 65 bool (*getAdvance)(FontHandle fontHandle, int gId, Data* data)) { 66 // Assuming that an ASCII representation of a width or a glyph id is, 67 // on average, 3 characters long gives the following cut offs for 68 // using different range types: 69 // When currently in a range 70 // - Removing 4 0's is a win 71 // - Removing 5 repeats is a win 72 // When not currently in a range 73 // - Removing 1 0 is a win 74 // - Removing 3 repeats is a win 75 76 SkTScopedPtr<SkAdvancedTypefaceMetrics::AdvanceMetric<Data> > result; 77 SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* curRange; 78 curRange = appendRange(&result, 0); 79 Data lastAdvance = SK_MinS16; 80 int repeats = 0; 81 for (int gId = 0; gId < num_glyphs; gId++) { 82 Data advance; 83 if (!getAdvance(fontHandle, gId, &advance)) { 84 num_glyphs = (gId > 0) ? gId - 1 : 0; 85 break; 86 } 87 if (advance == lastAdvance) { 88 repeats++; 89 } else if (curRange->fAdvance.count() == repeats + 1) { 90 if (lastAdvance == 0 && repeats >= 0) { 91 resetRange(curRange, gId); 92 } else if (repeats >= 2) { 93 finishRange(curRange, gId - 1, 94 SkAdvancedTypefaceMetrics::WidthRange::kRun); 95 curRange = appendRange(&curRange->fNext, gId); 96 } 97 repeats = 0; 98 } else { 99 if (lastAdvance == 0 && repeats >= 3) { 100 finishRange(curRange, gId - repeats - 2, 101 SkAdvancedTypefaceMetrics::WidthRange::kRange); 102 curRange = appendRange(&curRange->fNext, gId); 103 } else if (repeats >= 4) { 104 finishRange(curRange, gId - repeats - 2, 105 SkAdvancedTypefaceMetrics::WidthRange::kRange); 106 curRange = appendRange(&curRange->fNext, gId - repeats - 1); 107 curRange->fAdvance.append(1, &lastAdvance); 108 finishRange(curRange, gId - 1, 109 SkAdvancedTypefaceMetrics::WidthRange::kRun); 110 curRange = appendRange(&curRange->fNext, gId); 111 } 112 repeats = 0; 113 } 114 curRange->fAdvance.append(1, &advance); 115 lastAdvance = advance; 116 } 117 finishRange(curRange, num_glyphs - 1, 118 SkAdvancedTypefaceMetrics::WidthRange::kRange); 119 return result.release(); 120} 121 122// Make AdvanceMetric template functions available for linking with typename 123// WidthRange and VerticalAdvanceRange. 124#if defined(SK_BUILD_FOR_WIN) 125template SkAdvancedTypefaceMetrics::WidthRange* getAdvanceData( 126 HDC hdc, 127 int num_glyphs, 128 bool (*getAdvance)(HDC hdc, int gId, int16_t* data)); 129#elif defined(SK_BUILD_FOR_UNIX) 130template SkAdvancedTypefaceMetrics::WidthRange* getAdvanceData( 131 FT_Face face, 132 int num_glyphs, 133 bool (*getAdvance)(FT_Face face, int gId, int16_t* data)); 134#endif 135template void resetRange( 136 SkAdvancedTypefaceMetrics::WidthRange* range, 137 int startId); 138template SkAdvancedTypefaceMetrics::WidthRange* appendRange( 139 SkTScopedPtr<SkAdvancedTypefaceMetrics::WidthRange >* nextSlot, 140 int startId); 141template void finishRange<int16_t>( 142 SkAdvancedTypefaceMetrics::WidthRange* range, 143 int endId, 144 SkAdvancedTypefaceMetrics::WidthRange::MetricType type); 145 146template void resetRange( 147 SkAdvancedTypefaceMetrics::VerticalAdvanceRange* range, 148 int startId); 149template SkAdvancedTypefaceMetrics::VerticalAdvanceRange* appendRange( 150 SkTScopedPtr<SkAdvancedTypefaceMetrics::VerticalAdvanceRange >* 151 nextSlot, 152 int startId); 153template void finishRange<SkAdvancedTypefaceMetrics::VerticalMetric>( 154 SkAdvancedTypefaceMetrics::VerticalAdvanceRange* range, 155 int endId, 156 SkAdvancedTypefaceMetrics::VerticalAdvanceRange::MetricType type); 157 158} // namespace skia_advanced_typeface_metrics_utils 159