SkTypeface.cpp revision fe74765f0d302669ae49e68074492bdfe0ce6e6f
1/*
2 * Copyright 2011 The Android Open Source Project
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkAdvancedTypefaceMetrics.h"
9#include "SkFontDescriptor.h"
10#include "SkFontHost.h"
11#include "SkFontStream.h"
12#include "SkStream.h"
13#include "SkTypeface.h"
14
15SK_DEFINE_INST_COUNT(SkTypeface)
16
17//#define TRACE_LIFECYCLE
18
19#ifdef TRACE_LIFECYCLE
20    static int32_t gTypefaceCounter;
21#endif
22
23SkTypeface::SkTypeface(Style style, SkFontID fontID, bool isFixedPitch)
24    : fUniqueID(fontID), fStyle(style), fIsFixedPitch(isFixedPitch) {
25#ifdef TRACE_LIFECYCLE
26    SkDebugf("SkTypeface: create  %p fontID %d total %d\n",
27             this, fontID, ++gTypefaceCounter);
28#endif
29}
30
31SkTypeface::~SkTypeface() {
32#ifdef TRACE_LIFECYCLE
33    SkDebugf("SkTypeface: destroy %p fontID %d total %d\n",
34             this, fUniqueID, --gTypefaceCounter);
35#endif
36}
37
38///////////////////////////////////////////////////////////////////////////////
39
40SkTypeface* SkTypeface::GetDefaultTypeface() {
41    // we keep a reference to this guy for all time, since if we return its
42    // fontID, the font cache may later on ask to resolve that back into a
43    // typeface object.
44    static SkTypeface* gDefaultTypeface;
45
46    if (NULL == gDefaultTypeface) {
47        gDefaultTypeface =
48        SkFontHost::CreateTypeface(NULL, NULL, SkTypeface::kNormal);
49    }
50    return gDefaultTypeface;
51}
52
53SkTypeface* SkTypeface::RefDefault() {
54    return SkRef(GetDefaultTypeface());
55}
56
57uint32_t SkTypeface::UniqueID(const SkTypeface* face) {
58    if (NULL == face) {
59        face = GetDefaultTypeface();
60    }
61    return face->uniqueID();
62}
63
64bool SkTypeface::Equal(const SkTypeface* facea, const SkTypeface* faceb) {
65    return SkTypeface::UniqueID(facea) == SkTypeface::UniqueID(faceb);
66}
67
68///////////////////////////////////////////////////////////////////////////////
69
70SkTypeface* SkTypeface::CreateFromName(const char name[], Style style) {
71    return SkFontHost::CreateTypeface(NULL, name, style);
72}
73
74SkTypeface* SkTypeface::CreateFromTypeface(const SkTypeface* family, Style s) {
75    if (family && family->style() == s) {
76        family->ref();
77        return const_cast<SkTypeface*>(family);
78    }
79    return SkFontHost::CreateTypeface(family, NULL, s);
80}
81
82SkTypeface* SkTypeface::CreateFromStream(SkStream* stream) {
83    return SkFontHost::CreateTypefaceFromStream(stream);
84}
85
86SkTypeface* SkTypeface::CreateFromFile(const char path[]) {
87    return SkFontHost::CreateTypefaceFromFile(path);
88}
89
90///////////////////////////////////////////////////////////////////////////////
91
92void SkTypeface::serialize(SkWStream* wstream) const {
93    bool isLocal = false;
94    SkFontDescriptor desc(this->style());
95    this->onGetFontDescriptor(&desc, &isLocal);
96
97    desc.serialize(wstream);
98    if (isLocal) {
99        int ttcIndex;   // TODO: write this to the stream?
100        SkAutoTUnref<SkStream> rstream(this->openStream(&ttcIndex));
101        if (rstream.get()) {
102            size_t length = rstream->getLength();
103            wstream->writePackedUInt(length);
104            wstream->writeStream(rstream, length);
105        } else {
106            wstream->writePackedUInt(0);
107        }
108    } else {
109        wstream->writePackedUInt(0);
110    }
111}
112
113SkTypeface* SkTypeface::Deserialize(SkStream* stream) {
114    SkFontDescriptor desc(stream);
115    size_t length = stream->readPackedUInt();
116    if (length > 0) {
117        void* addr = sk_malloc_flags(length, 0);
118        if (addr) {
119            SkAutoTUnref<SkStream> localStream(SkNEW_ARGS(SkMemoryStream,
120                                                        (addr, length, false)));
121            return SkTypeface::CreateFromStream(localStream.get());
122        }
123        // failed to allocate, so just skip and create-from-name
124        stream->skip(length);
125    }
126
127    return SkTypeface::CreateFromName(desc.getFamilyName(), desc.getStyle());
128}
129
130///////////////////////////////////////////////////////////////////////////////
131
132int SkTypeface::countTables() const {
133    return this->onGetTableTags(NULL);
134}
135
136int SkTypeface::getTableTags(SkFontTableTag tags[]) const {
137    return this->onGetTableTags(tags);
138}
139
140size_t SkTypeface::getTableSize(SkFontTableTag tag) const {
141    return this->onGetTableData(tag, 0, ~0U, NULL);
142}
143
144size_t SkTypeface::getTableData(SkFontTableTag tag, size_t offset, size_t length,
145                                void* data) const {
146    return this->onGetTableData(tag, offset, length, data);
147}
148
149SkStream* SkTypeface::openStream(int* ttcIndex) const {
150    int ttcIndexStorage;
151    if (NULL == ttcIndex) {
152        // So our subclasses don't need to check for null param
153        ttcIndex = &ttcIndexStorage;
154    }
155    return this->onOpenStream(ttcIndex);
156}
157
158int SkTypeface::getUnitsPerEm() const {
159    // should we try to cache this in the base-class?
160    return this->onGetUPEM();
161}
162
163SkAdvancedTypefaceMetrics* SkTypeface::getAdvancedTypefaceMetrics(
164                                SkAdvancedTypefaceMetrics::PerGlyphInfo info,
165                                const uint32_t* glyphIDs,
166                                uint32_t glyphIDsCount) const {
167    return this->onGetAdvancedTypefaceMetrics(info, glyphIDs, glyphIDsCount);
168}
169
170///////////////////////////////////////////////////////////////////////////////
171///////////////////////////////////////////////////////////////////////////////
172
173int SkTypeface::onGetUPEM() const {
174    int upem = 0;
175
176    SkAdvancedTypefaceMetrics* metrics;
177    metrics = this->getAdvancedTypefaceMetrics(
178                             SkAdvancedTypefaceMetrics::kNo_PerGlyphInfo,
179                             NULL, 0);
180    if (metrics) {
181        upem = metrics->fEmSize;
182        metrics->unref();
183    }
184    return upem;
185}
186
187int SkTypeface::onGetTableTags(SkFontTableTag tags[]) const {
188    int ttcIndex;
189    SkAutoTUnref<SkStream> stream(this->openStream(&ttcIndex));
190    return stream.get() ? SkFontStream::GetTableTags(stream, ttcIndex, tags) : 0;
191}
192
193size_t SkTypeface::onGetTableData(SkFontTableTag tag, size_t offset,
194                                  size_t length, void* data) const {
195    int ttcIndex;
196    SkAutoTUnref<SkStream> stream(this->openStream(&ttcIndex));
197    return stream.get()
198        ? SkFontStream::GetTableData(stream, ttcIndex, tag, offset, length, data)
199        : 0;
200}
201
202