• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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