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