SkAdvancedTypefaceMetrics.cpp revision 856b984c51f19e8d7bebe0f06e21972233e78f1a
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
13SK_DEFINE_INST_COUNT(SkAdvancedTypefaceMetrics)
14
15#if defined(SK_BUILD_FOR_WIN)
16#include <dwrite.h>
17#endif
18
19#if defined(SK_BUILD_FOR_UNIX) || defined(SK_BUILD_FOR_ANDROID)
20// forward declare structs needed for getAdvanceData() template for freetype
21struct FT_FaceRec;
22typedef struct FT_FaceRec_* FT_Face;
23#endif
24
25#ifdef SK_BUILD_FOR_MAC
26#import <ApplicationServices/ApplicationServices.h>
27#endif
28
29#ifdef SK_BUILD_FOR_IOS
30#include <CoreText/CoreText.h>
31#include <CoreGraphics/CoreGraphics.h>
32#include <CoreFoundation/CoreFoundation.h>
33#endif
34
35namespace skia_advanced_typeface_metrics_utils {
36
37const int16_t kInvalidAdvance = SK_MinS16;
38const int16_t kDontCareAdvance = SK_MinS16 + 1;
39
40template <typename Data>
41void stripUninterestingTrailingAdvancesFromRange(
42                                                 SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* range) {
43    SkASSERT(false);
44}
45
46template <>
47void stripUninterestingTrailingAdvancesFromRange<int16_t>(
48                                                          SkAdvancedTypefaceMetrics::AdvanceMetric<int16_t>* range) {
49    SkASSERT(range);
50
51    int expectedAdvanceCount = range->fEndId - range->fStartId + 1;
52    if (range->fAdvance.count() < expectedAdvanceCount) {
53        return;
54    }
55
56    for (int i = expectedAdvanceCount - 1; i >= 0; --i) {
57        if (range->fAdvance[i] != kDontCareAdvance &&
58            range->fAdvance[i] != kInvalidAdvance &&
59            range->fAdvance[i] != 0) {
60            range->fEndId = range->fStartId + i;
61            break;
62        }
63    }
64}
65
66template <typename Data>
67void resetRange(SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* range,
68                int startId) {
69    range->fStartId = startId;
70    range->fAdvance.setCount(0);
71}
72
73template <typename Data>
74SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* appendRange(
75        SkTScopedPtr<SkAdvancedTypefaceMetrics::AdvanceMetric<Data> >* nextSlot,
76        int startId) {
77    nextSlot->reset(new SkAdvancedTypefaceMetrics::AdvanceMetric<Data>);
78    resetRange(nextSlot->get(), startId);
79    return nextSlot->get();
80}
81
82template <typename Data>
83void zeroWildcardsInRange(
84                          SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* range) {
85    SkASSERT(false);
86}
87
88template <>
89void zeroWildcardsInRange<int16_t>(
90                                   SkAdvancedTypefaceMetrics::AdvanceMetric<int16_t>* range) {
91    SkASSERT(range);
92    if (range->fType != SkAdvancedTypefaceMetrics::WidthRange::kRange) {
93        return;
94    }
95    SkASSERT(range->fAdvance.count() == range->fEndId - range->fStartId + 1);
96
97    // Zero out wildcards.
98    for (int i = 0; i < range->fAdvance.count(); ++i) {
99        if (range->fAdvance[i] == kDontCareAdvance) {
100            range->fAdvance[i] = 0;
101        }
102    }
103}
104
105template <typename Data>
106void finishRange(
107        SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* range,
108        int endId,
109        typename SkAdvancedTypefaceMetrics::AdvanceMetric<Data>::MetricType
110                type) {
111    range->fEndId = endId;
112    range->fType = type;
113    stripUninterestingTrailingAdvancesFromRange(range);
114    int newLength;
115    if (type == SkAdvancedTypefaceMetrics::AdvanceMetric<Data>::kRange) {
116        newLength = range->fEndId - range->fStartId + 1;
117    } else {
118        if (range->fEndId == range->fStartId) {
119            range->fType =
120                SkAdvancedTypefaceMetrics::AdvanceMetric<Data>::kRange;
121        }
122        newLength = 1;
123    }
124    SkASSERT(range->fAdvance.count() >= newLength);
125    range->fAdvance.setCount(newLength);
126    zeroWildcardsInRange(range);
127}
128
129template <typename Data, typename FontHandle>
130SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* getAdvanceData(
131        FontHandle fontHandle,
132        int num_glyphs,
133        const uint32_t* subsetGlyphIDs,
134        uint32_t subsetGlyphIDsLength,
135        bool (*getAdvance)(FontHandle fontHandle, int gId, Data* data)) {
136    // Assuming that on average, the ASCII representation of an advance plus
137    // a space is 8 characters and the ASCII representation of a glyph id is 3
138    // characters, then the following cut offs for using different range types
139    // apply:
140    // The cost of stopping and starting the range is 7 characers
141    //  a. Removing 4 0's or don't care's is a win
142    // The cost of stopping and starting the range plus a run is 22
143    // characters
144    //  b. Removing 3 repeating advances is a win
145    //  c. Removing 2 repeating advances and 3 don't cares is a win
146    // When not currently in a range the cost of a run over a range is 16
147    // characaters, so:
148    //  d. Removing a leading 0/don't cares is a win because it is omitted
149    //  e. Removing 2 repeating advances is a win
150
151    SkTScopedPtr<SkAdvancedTypefaceMetrics::AdvanceMetric<Data> > result;
152    SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* curRange;
153    SkAdvancedTypefaceMetrics::AdvanceMetric<Data>* prevRange = NULL;
154    Data lastAdvance = kInvalidAdvance;
155    int repeatedAdvances = 0;
156    int wildCardsInRun = 0;
157    int trailingWildCards = 0;
158    uint32_t subsetIndex = 0;
159
160    // Limit the loop count to glyph id ranges provided.
161    int firstIndex = 0;
162    int lastIndex = num_glyphs;
163    if (subsetGlyphIDs) {
164        firstIndex = static_cast<int>(subsetGlyphIDs[0]);
165        lastIndex =
166                static_cast<int>(subsetGlyphIDs[subsetGlyphIDsLength - 1]) + 1;
167    }
168    curRange = appendRange(&result, firstIndex);
169
170    for (int gId = firstIndex; gId <= lastIndex; gId++) {
171        Data advance = kInvalidAdvance;
172        if (gId < lastIndex) {
173            // Get glyph id only when subset is NULL, or the id is in subset.
174            if (!subsetGlyphIDs ||
175                (subsetIndex < subsetGlyphIDsLength &&
176                 static_cast<uint32_t>(gId) == subsetGlyphIDs[subsetIndex])) {
177                SkAssertResult(getAdvance(fontHandle, gId, &advance));
178                ++subsetIndex;
179            } else {
180                advance = kDontCareAdvance;
181            }
182        }
183        if (advance == lastAdvance) {
184            repeatedAdvances++;
185            trailingWildCards = 0;
186        } else if (advance == kDontCareAdvance) {
187            wildCardsInRun++;
188            trailingWildCards++;
189        } else if (curRange->fAdvance.count() ==
190                   repeatedAdvances + 1 + wildCardsInRun) {  // All in run.
191            if (lastAdvance == 0) {
192                resetRange(curRange, gId);
193                trailingWildCards = 0;
194            } else if (repeatedAdvances + 1 >= 2 || trailingWildCards >= 4) {
195                finishRange(curRange, gId - 1,
196                            SkAdvancedTypefaceMetrics::WidthRange::kRun);
197                prevRange = curRange;
198                curRange = appendRange(&curRange->fNext, gId);
199                trailingWildCards = 0;
200            }
201            repeatedAdvances = 0;
202            wildCardsInRun = trailingWildCards;
203            trailingWildCards = 0;
204        } else {
205            if (lastAdvance == 0 &&
206                    repeatedAdvances + 1 + wildCardsInRun >= 4) {
207                finishRange(curRange,
208                            gId - repeatedAdvances - wildCardsInRun - 2,
209                            SkAdvancedTypefaceMetrics::WidthRange::kRange);
210                prevRange = curRange;
211                curRange = appendRange(&curRange->fNext, gId);
212                trailingWildCards = 0;
213            } else if (trailingWildCards >= 4 && repeatedAdvances + 1 < 2) {
214                finishRange(curRange,
215                            gId - trailingWildCards - 1,
216                            SkAdvancedTypefaceMetrics::WidthRange::kRange);
217                prevRange = curRange;
218                curRange = appendRange(&curRange->fNext, gId);
219                trailingWildCards = 0;
220            } else if (lastAdvance != 0 &&
221                       (repeatedAdvances + 1 >= 3 ||
222                        (repeatedAdvances + 1 >= 2 && wildCardsInRun >= 3))) {
223                finishRange(curRange,
224                            gId - repeatedAdvances - wildCardsInRun - 2,
225                            SkAdvancedTypefaceMetrics::WidthRange::kRange);
226                curRange =
227                    appendRange(&curRange->fNext,
228                                gId - repeatedAdvances - wildCardsInRun - 1);
229                curRange->fAdvance.append(1, &lastAdvance);
230                finishRange(curRange, gId - 1,
231                            SkAdvancedTypefaceMetrics::WidthRange::kRun);
232                prevRange = curRange;
233                curRange = appendRange(&curRange->fNext, gId);
234                trailingWildCards = 0;
235            }
236            repeatedAdvances = 0;
237            wildCardsInRun = trailingWildCards;
238            trailingWildCards = 0;
239        }
240        curRange->fAdvance.append(1, &advance);
241        if (advance != kDontCareAdvance) {
242            lastAdvance = advance;
243        }
244    }
245    if (curRange->fStartId == lastIndex) {
246        SkASSERT(prevRange);
247        SkASSERT(prevRange->fNext->fStartId == lastIndex);
248        prevRange->fNext.reset();
249    } else {
250        finishRange(curRange, lastIndex - 1,
251                    SkAdvancedTypefaceMetrics::WidthRange::kRange);
252    }
253    return result.release();
254}
255
256// Make AdvanceMetric template functions available for linking with typename
257// WidthRange and VerticalAdvanceRange.
258#if defined(SK_BUILD_FOR_WIN)
259template SkAdvancedTypefaceMetrics::WidthRange* getAdvanceData(
260        HDC hdc,
261        int num_glyphs,
262        const uint32_t* subsetGlyphIDs,
263        uint32_t subsetGlyphIDsLength,
264        bool (*getAdvance)(HDC hdc, int gId, int16_t* data));
265template SkAdvancedTypefaceMetrics::WidthRange* getAdvanceData(
266        IDWriteFontFace* fontFace,
267        int num_glyphs,
268        const uint32_t* subsetGlyphIDs,
269        uint32_t subsetGlyphIDsLength,
270        bool (*getAdvance)(IDWriteFontFace* fontFace, int gId, int16_t* data));
271#elif defined(SK_BUILD_FOR_UNIX) || defined(SK_BUILD_FOR_ANDROID)
272template SkAdvancedTypefaceMetrics::WidthRange* getAdvanceData(
273        FT_Face face,
274        int num_glyphs,
275        const uint32_t* subsetGlyphIDs,
276        uint32_t subsetGlyphIDsLength,
277        bool (*getAdvance)(FT_Face face, int gId, int16_t* data));
278#elif defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
279template SkAdvancedTypefaceMetrics::WidthRange* getAdvanceData(
280        CTFontRef ctFont,
281        int num_glyphs,
282        const uint32_t* subsetGlyphIDs,
283        uint32_t subsetGlyphIDsLength,
284        bool (*getAdvance)(CTFontRef ctFont, int gId, int16_t* data));
285#endif
286template void resetRange(
287        SkAdvancedTypefaceMetrics::WidthRange* range,
288        int startId);
289template SkAdvancedTypefaceMetrics::WidthRange* appendRange(
290        SkTScopedPtr<SkAdvancedTypefaceMetrics::WidthRange >* nextSlot,
291        int startId);
292template void finishRange<int16_t>(
293        SkAdvancedTypefaceMetrics::WidthRange* range,
294        int endId,
295        SkAdvancedTypefaceMetrics::WidthRange::MetricType type);
296
297template void resetRange(
298        SkAdvancedTypefaceMetrics::VerticalAdvanceRange* range,
299        int startId);
300template SkAdvancedTypefaceMetrics::VerticalAdvanceRange* appendRange(
301        SkTScopedPtr<SkAdvancedTypefaceMetrics::VerticalAdvanceRange >*
302            nextSlot,
303        int startId);
304template void finishRange<SkAdvancedTypefaceMetrics::VerticalMetric>(
305        SkAdvancedTypefaceMetrics::VerticalAdvanceRange* range,
306        int endId,
307        SkAdvancedTypefaceMetrics::VerticalAdvanceRange::MetricType type);
308
309// additional declaration needed for testing with a face of an unknown type
310template SkAdvancedTypefaceMetrics::WidthRange* getAdvanceData(
311        void* fontData,
312        int num_glyphs,
313        const uint32_t* subsetGlyphIDs,
314        uint32_t subsetGlyphIDsLength,
315        bool (*getAdvance)(void* fontData, int gId, int16_t* data));
316
317} // namespace skia_advanced_typeface_metrics_utils
318