blob: 776a24af42cdba8c9e8b53f061c21ca4fd065a71 [file] [log] [blame]
vandebo@chromium.org2a22e102011-01-25 21:01:34 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * Copyright 2011 The Android Open Source Project
vandebo@chromium.org2a22e102011-01-25 21:01:34 +00003 *
epoger@google.comec3ed6a2011-07-28 14:26:00 +00004 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
vandebo@chromium.org2a22e102011-01-25 21:01:34 +00006 */
7
vandebo@chromium.org325cb9a2011-03-30 18:36:29 +00008#include "SkAdvancedTypefaceMetrics.h"
reed@google.com5526ede2013-03-25 13:03:37 +00009#include "SkFontDescriptor.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000010#include "SkFontHost.h"
reed@google.com5526ede2013-03-25 13:03:37 +000011#include "SkFontStream.h"
12#include "SkStream.h"
13#include "SkTypeface.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000014
reed@google.comfcb57b52012-06-26 17:55:30 +000015SK_DEFINE_INST_COUNT(SkTypeface)
16
reed@google.come4959052011-05-02 17:35:04 +000017//#define TRACE_LIFECYCLE
reed@google.com2f3dc9d2011-05-02 17:33:45 +000018
19#ifdef TRACE_LIFECYCLE
20 static int32_t gTypefaceCounter;
21#endif
22
bungeman@google.comfe747652013-03-25 19:36:11 +000023SkTypeface::SkTypeface(Style style, SkFontID fontID, bool isFixedPitch)
24 : fUniqueID(fontID), fStyle(style), fIsFixedPitch(isFixedPitch) {
reed@google.com2f3dc9d2011-05-02 17:33:45 +000025#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
bungeman@google.comcb1bbb32012-10-12 18:48:35 +000040SkTypeface* SkTypeface::GetDefaultTypeface() {
reed@google.com538f7842011-12-16 17:56:23 +000041 // 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 =
reed@google.com0389d932012-05-07 21:06:55 +000048 SkFontHost::CreateTypeface(NULL, NULL, SkTypeface::kNormal);
reed@google.com538f7842011-12-16 17:56:23 +000049 }
50 return gDefaultTypeface;
51}
52
reed@google.comfed86bd2013-03-14 15:04:57 +000053SkTypeface* SkTypeface::RefDefault() {
54 return SkRef(GetDefaultTypeface());
55}
56
reed@android.comef772dd2009-03-03 21:20:49 +000057uint32_t SkTypeface::UniqueID(const SkTypeface* face) {
reed@google.com538f7842011-12-16 17:56:23 +000058 if (NULL == face) {
bungeman@google.comcb1bbb32012-10-12 18:48:35 +000059 face = GetDefaultTypeface();
reed@android.comb1d9d2e2009-03-04 17:37:51 +000060 }
reed@google.com538f7842011-12-16 17:56:23 +000061 return face->uniqueID();
reed@android.com8a1c16f2008-12-17 15:59:43 +000062}
63
reed@android.comef772dd2009-03-03 21:20:49 +000064bool SkTypeface::Equal(const SkTypeface* facea, const SkTypeface* faceb) {
reed@android.comb1d9d2e2009-03-04 17:37:51 +000065 return SkTypeface::UniqueID(facea) == SkTypeface::UniqueID(faceb);
reed@android.com8a1c16f2008-12-17 15:59:43 +000066}
67
68///////////////////////////////////////////////////////////////////////////////
69
reed@android.com069b8272009-03-04 15:31:48 +000070SkTypeface* SkTypeface::CreateFromName(const char name[], Style style) {
reed@google.com0389d932012-05-07 21:06:55 +000071 return SkFontHost::CreateTypeface(NULL, name, style);
reed@android.com8a1c16f2008-12-17 15:59:43 +000072}
73
reed@android.comef772dd2009-03-03 21:20:49 +000074SkTypeface* SkTypeface::CreateFromTypeface(const SkTypeface* family, Style s) {
reed@google.com49690442013-03-04 14:39:47 +000075 if (family && family->style() == s) {
76 family->ref();
77 return const_cast<SkTypeface*>(family);
78 }
reed@google.com0389d932012-05-07 21:06:55 +000079 return SkFontHost::CreateTypeface(family, NULL, s);
reed@android.com8a1c16f2008-12-17 15:59:43 +000080}
81
reed@android.comef772dd2009-03-03 21:20:49 +000082SkTypeface* SkTypeface::CreateFromStream(SkStream* stream) {
reed@android.comb1d9d2e2009-03-04 17:37:51 +000083 return SkFontHost::CreateTypefaceFromStream(stream);
reed@android.com8a1c16f2008-12-17 15:59:43 +000084}
85
reed@android.comef772dd2009-03-03 21:20:49 +000086SkTypeface* SkTypeface::CreateFromFile(const char path[]) {
reed@android.com03ca3d12008-12-22 15:35:46 +000087 return SkFontHost::CreateTypefaceFromFile(path);
reed@android.com8a1c16f2008-12-17 15:59:43 +000088}
89
90///////////////////////////////////////////////////////////////////////////////
91
reed@google.com5526ede2013-03-25 13:03:37 +000092void 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 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000111}
112
113SkTypeface* SkTypeface::Deserialize(SkStream* stream) {
reed@google.com5526ede2013-03-25 13:03:37 +0000114 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 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000126
reed@google.com5526ede2013-03-25 13:03:37 +0000127 return SkTypeface::CreateFromName(desc.getFamilyName(), desc.getStyle());
vandebo@chromium.org2a22e102011-01-25 21:01:34 +0000128}
reed@google.comf11508d2012-04-17 18:01:31 +0000129
130///////////////////////////////////////////////////////////////////////////////
131
132int SkTypeface::countTables() const {
reed@google.com6c66d2f2013-03-21 20:34:27 +0000133 return this->onGetTableTags(NULL);
reed@google.comf11508d2012-04-17 18:01:31 +0000134}
135
136int SkTypeface::getTableTags(SkFontTableTag tags[]) const {
reed@google.com6c66d2f2013-03-21 20:34:27 +0000137 return this->onGetTableTags(tags);
reed@google.comf11508d2012-04-17 18:01:31 +0000138}
139
140size_t SkTypeface::getTableSize(SkFontTableTag tag) const {
reed@google.com6c66d2f2013-03-21 20:34:27 +0000141 return this->onGetTableData(tag, 0, ~0U, NULL);
reed@google.comf11508d2012-04-17 18:01:31 +0000142}
143
144size_t SkTypeface::getTableData(SkFontTableTag tag, size_t offset, size_t length,
145 void* data) const {
reed@google.com6c66d2f2013-03-21 20:34:27 +0000146 return this->onGetTableData(tag, offset, length, data);
reed@google.comf11508d2012-04-17 18:01:31 +0000147}
148
reed@google.comfed86bd2013-03-14 15:04:57 +0000149SkStream* SkTypeface::openStream(int* ttcIndex) const {
reed@google.com2cdc6712013-03-21 18:22:00 +0000150 int ttcIndexStorage;
151 if (NULL == ttcIndex) {
152 // So our subclasses don't need to check for null param
153 ttcIndex = &ttcIndexStorage;
reed@google.comfed86bd2013-03-14 15:04:57 +0000154 }
reed@google.com2cdc6712013-03-21 18:22:00 +0000155 return this->onOpenStream(ttcIndex);
reed@google.comfed86bd2013-03-14 15:04:57 +0000156}
157
reed@google.com4b2af9c2012-07-31 17:24:44 +0000158int SkTypeface::getUnitsPerEm() const {
reed@google.com38c37dd2013-03-21 15:36:26 +0000159 // should we try to cache this in the base-class?
160 return this->onGetUPEM();
reed@google.com4b2af9c2012-07-31 17:24:44 +0000161}
mike@reedtribe.orgdc09f072013-03-03 01:15:48 +0000162
reed@google.com5526ede2013-03-25 13:03:37 +0000163SkAdvancedTypefaceMetrics* SkTypeface::getAdvancedTypefaceMetrics(
164 SkAdvancedTypefaceMetrics::PerGlyphInfo info,
165 const uint32_t* glyphIDs,
166 uint32_t glyphIDsCount) const {
167 return this->onGetAdvancedTypefaceMetrics(info, glyphIDs, glyphIDsCount);
168}
mike@reedtribe.orgdc09f072013-03-03 01:15:48 +0000169
reed@google.com5526ede2013-03-25 13:03:37 +0000170///////////////////////////////////////////////////////////////////////////////
171///////////////////////////////////////////////////////////////////////////////
mike@reedtribe.orgdc09f072013-03-03 01:15:48 +0000172
reed@google.com38c37dd2013-03-21 15:36:26 +0000173int 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
reed@google.com6c66d2f2013-03-21 20:34:27 +0000187int 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}
reed@google.com5526ede2013-03-25 13:03:37 +0000201