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