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