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