blob: c53328b89b987ebe221a6fa30ca75b28861450dc [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001/*
2 * Copyright 2008 Google Inc.
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
reed@google.comd71fe992013-02-25 20:38:07 +00008#include "SkFontConfigInterface.h"
djsollen@google.com6930b572013-05-15 20:11:20 +00009#include "SkFontConfigTypeface.h"
reed@google.comd71fe992013-02-25 20:38:07 +000010#include "SkFontDescriptor.h"
agl@chromium.orgdf8ecfb2009-04-28 17:30:01 +000011#include "SkFontHost.h"
reed@google.com0da48612013-03-19 16:06:52 +000012#include "SkFontHost_FreeType_common.h"
reed@google.com822bde72013-03-04 16:28:33 +000013#include "SkFontStream.h"
agl@chromium.orgdf8ecfb2009-04-28 17:30:01 +000014#include "SkStream.h"
reed@google.com80f54652013-02-25 22:19:20 +000015#include "SkTypeface.h"
reed@google.comf71a2332013-02-27 19:06:30 +000016#include "SkTypefaceCache.h"
reed@google.comb1c65b62013-02-26 15:50:51 +000017
reed@google.comd71fe992013-02-25 20:38:07 +000018SK_DECLARE_STATIC_MUTEX(gFontConfigInterfaceMutex);
19static SkFontConfigInterface* gFontConfigInterface;
agl@chromium.orgdf8ecfb2009-04-28 17:30:01 +000020
reed@google.comd71fe992013-02-25 20:38:07 +000021SkFontConfigInterface* SkFontConfigInterface::RefGlobal() {
22 SkAutoMutexAcquire ac(gFontConfigInterfaceMutex);
skia.committer@gmail.com5ca3bd02013-02-26 07:01:22 +000023
reed@google.comd71fe992013-02-25 20:38:07 +000024 return SkSafeRef(gFontConfigInterface);
25}
bungeman@google.comb13d63c2012-11-06 16:55:24 +000026
reed@google.comd71fe992013-02-25 20:38:07 +000027SkFontConfigInterface* SkFontConfigInterface::SetGlobal(SkFontConfigInterface* fc) {
28 SkAutoMutexAcquire ac(gFontConfigInterfaceMutex);
agl@chromium.orgdf8ecfb2009-04-28 17:30:01 +000029
reed@google.comd71fe992013-02-25 20:38:07 +000030 SkRefCnt_SafeAssign(gFontConfigInterface, fc);
31 return fc;
32}
bungeman@google.comb13d63c2012-11-06 16:55:24 +000033
reed@google.comd71fe992013-02-25 20:38:07 +000034///////////////////////////////////////////////////////////////////////////////
reed@google.comf71a2332013-02-27 19:06:30 +000035///////////////////////////////////////////////////////////////////////////////
36
37// convenience function to create the direct interface if none is installed.
38extern SkFontConfigInterface* SkCreateDirectFontConfigInterface();
reed@google.comd71fe992013-02-25 20:38:07 +000039
reed@google.com80f54652013-02-25 22:19:20 +000040static SkFontConfigInterface* RefFCI() {
reed@google.comb1c65b62013-02-26 15:50:51 +000041 for (;;) {
42 SkFontConfigInterface* fci = SkFontConfigInterface::RefGlobal();
43 if (fci) {
44 return fci;
45 }
reed@google.comd66045e2013-03-04 19:07:02 +000046 fci = SkFontConfigInterface::GetSingletonDirectInterface();
reed@google.com750a24b2013-04-22 18:45:12 +000047 SkFontConfigInterface::SetGlobal(fci);
reed@google.comb1c65b62013-02-26 15:50:51 +000048 }
reed@google.com80f54652013-02-25 22:19:20 +000049}
50
reed@google.com381bb432013-05-13 19:43:59 +000051// export this to SkFontMgr_fontconfig.cpp until this file just goes away.
52SkFontConfigInterface* SkFontHost_fontconfig_ref_global();
53SkFontConfigInterface* SkFontHost_fontconfig_ref_global() {
54 return RefFCI();
55}
56
57///////////////////////////////////////////////////////////////////////////////
58
reed@google.comf71a2332013-02-27 19:06:30 +000059struct FindRec {
60 FindRec(const char* name, SkTypeface::Style style)
61 : fFamilyName(name) // don't need to make a deep copy
62 , fStyle(style) {}
63
64 const char* fFamilyName;
65 SkTypeface::Style fStyle;
66};
67
68static bool find_proc(SkTypeface* face, SkTypeface::Style style, void* ctx) {
69 FontConfigTypeface* fci = (FontConfigTypeface*)face;
70 const FindRec* rec = (const FindRec*)ctx;
71
72 return rec->fStyle == style && fci->isFamilyName(rec->fFamilyName);
73}
74
agl@chromium.orgdf8ecfb2009-04-28 17:30:01 +000075SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
76 const char familyName[],
reed@google.com80f54652013-02-25 22:19:20 +000077 SkTypeface::Style style) {
78 SkAutoTUnref<SkFontConfigInterface> fci(RefFCI());
79 if (NULL == fci.get()) {
80 return NULL;
81 }
82
agl@chromium.orgdf8ecfb2009-04-28 17:30:01 +000083 if (familyFace) {
reed@google.comf71a2332013-02-27 19:06:30 +000084 FontConfigTypeface* fct = (FontConfigTypeface*)familyFace;
85 familyName = fct->getFamilyName();
agl@chromium.orgdf8ecfb2009-04-28 17:30:01 +000086 }
87
reed@google.comf71a2332013-02-27 19:06:30 +000088 FindRec rec(familyName, style);
89 SkTypeface* face = SkTypefaceCache::FindByProcAndRef(find_proc, &rec);
90 if (face) {
reed@google.com0b8a2fe2013-03-13 14:58:41 +000091// SkDebugf("found cached face <%s> <%s> %p [%d]\n", familyName, ((FontConfigTypeface*)face)->getFamilyName(), face, face->getRefCnt());
reed@google.comf71a2332013-02-27 19:06:30 +000092 return face;
93 }
94
95 SkFontConfigInterface::FontIdentity indentity;
96 SkString outFamilyName;
97 SkTypeface::Style outStyle;
98
99 if (!fci->matchFamilyName(familyName, style,
100 &indentity, &outFamilyName, &outStyle)) {
agl@chromium.orgdf8ecfb2009-04-28 17:30:01 +0000101 return NULL;
102 }
agl@chromium.orgdf8ecfb2009-04-28 17:30:01 +0000103
reed@google.comf71a2332013-02-27 19:06:30 +0000104 face = SkNEW_ARGS(FontConfigTypeface, (outStyle, indentity, outFamilyName));
105 SkTypefaceCache::Add(face, style);
reed@google.com0b8a2fe2013-03-13 14:58:41 +0000106// SkDebugf("add face <%s> <%s> %p [%d]\n", familyName, outFamilyName.c_str(), face, face->getRefCnt());
reed@google.comf71a2332013-02-27 19:06:30 +0000107 return face;
agl@chromium.orgdf8ecfb2009-04-28 17:30:01 +0000108}
109
reed@google.com80f54652013-02-25 22:19:20 +0000110SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
111 if (!stream) {
reed@google.comd71fe992013-02-25 20:38:07 +0000112 return NULL;
reed@google.com80f54652013-02-25 22:19:20 +0000113 }
reed@google.comf71a2332013-02-27 19:06:30 +0000114 const size_t length = stream->getLength();
reed@google.com80f54652013-02-25 22:19:20 +0000115 if (!length) {
reed@google.comd71fe992013-02-25 20:38:07 +0000116 return NULL;
reed@google.com80f54652013-02-25 22:19:20 +0000117 }
118 if (length >= 1024 * 1024 * 1024) {
reed@google.comd71fe992013-02-25 20:38:07 +0000119 return NULL; // don't accept too large fonts (>= 1GB) for safety.
reed@google.com80f54652013-02-25 22:19:20 +0000120 }
agl@chromium.orgdf8ecfb2009-04-28 17:30:01 +0000121
reed@google.comf71a2332013-02-27 19:06:30 +0000122 // TODO should the caller give us the style?
123 SkTypeface::Style style = SkTypeface::kNormal;
124 SkTypeface* face = SkNEW_ARGS(FontConfigTypeface, (style, stream));
reed@google.comf71a2332013-02-27 19:06:30 +0000125 return face;
reed@android.comac981542009-07-31 16:17:01 +0000126}
127
reed@google.com80f54652013-02-25 22:19:20 +0000128SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
mike@reedtribe.orgf3811622013-03-19 02:18:33 +0000129 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
130 return stream.get() ? CreateTypefaceFromStream(stream) : NULL;
agl@chromium.orgdf8ecfb2009-04-28 17:30:01 +0000131}
132
reed@google.com822bde72013-03-04 16:28:33 +0000133///////////////////////////////////////////////////////////////////////////////
134
reed@google.com2cdc6712013-03-21 18:22:00 +0000135SkStream* FontConfigTypeface::onOpenStream(int* ttcIndex) const {
136 SkStream* stream = this->getLocalStream();
reed@google.comf71a2332013-02-27 19:06:30 +0000137 if (stream) {
reed@google.com5bfc8392013-03-05 22:12:11 +0000138 // should have been provided by CreateFromStream()
139 *ttcIndex = 0;
bungeman@google.com6cab1a42013-05-29 13:43:31 +0000140
141 SkAutoTUnref<SkStream> dupStream(stream->duplicate());
142 if (dupStream) {
143 return dupStream.detach();
144 }
145
146 // TODO: update interface use, remove the following code in this block.
147 size_t length = stream->getLength();
148
149 const void* memory = stream->getMemoryBase();
150 if (NULL != memory) {
151 return new SkMemoryStream(memory, length, true);
152 }
153
154 SkAutoTMalloc<uint8_t> allocMemory(length);
155 stream->rewind();
156 if (length == stream->read(allocMemory.get(), length)) {
bungeman@google.com88605bb2013-06-06 17:25:42 +0000157 SkAutoTUnref<SkMemoryStream> copyStream(new SkMemoryStream());
158 copyStream->setMemoryOwned(allocMemory.detach(), length);
159 return copyStream.detach();
bungeman@google.com6cab1a42013-05-29 13:43:31 +0000160 }
161
162 stream->rewind();
163 stream->ref();
reed@google.comf71a2332013-02-27 19:06:30 +0000164 } else {
165 SkAutoTUnref<SkFontConfigInterface> fci(RefFCI());
166 if (NULL == fci.get()) {
167 return NULL;
168 }
reed@google.com2cdc6712013-03-21 18:22:00 +0000169 stream = fci->openStream(this->getIdentity());
170 *ttcIndex = this->getIdentity().fTTCIndex;
reed@google.comf71a2332013-02-27 19:06:30 +0000171 }
172 return stream;
reed@google.comd71fe992013-02-25 20:38:07 +0000173}
174
reed@google.com822bde72013-03-04 16:28:33 +0000175int FontConfigTypeface::onGetTableTags(SkFontTableTag tags[]) const {
reed@google.com5bfc8392013-03-05 22:12:11 +0000176 int ttcIndex;
reed@google.com2cdc6712013-03-21 18:22:00 +0000177 SkAutoTUnref<SkStream> stream(this->openStream(&ttcIndex));
reed@google.com5bfc8392013-03-05 22:12:11 +0000178 return stream.get()
179 ? SkFontStream::GetTableTags(stream, ttcIndex, tags)
180 : 0;
reed@google.com822bde72013-03-04 16:28:33 +0000181}
182
183size_t FontConfigTypeface::onGetTableData(SkFontTableTag tag, size_t offset,
184 size_t length, void* data) const {
reed@google.com5bfc8392013-03-05 22:12:11 +0000185 int ttcIndex;
reed@google.com2cdc6712013-03-21 18:22:00 +0000186 SkAutoTUnref<SkStream> stream(this->openStream(&ttcIndex));
reed@google.com5bfc8392013-03-05 22:12:11 +0000187 return stream.get()
188 ? SkFontStream::GetTableData(stream, ttcIndex,
189 tag, offset, length, data)
190 : 0;
reed@google.com822bde72013-03-04 16:28:33 +0000191}
192
reed@google.com5526ede2013-03-25 13:03:37 +0000193void FontConfigTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
194 bool* isLocalStream) const {
reed@google.com822bde72013-03-04 16:28:33 +0000195 desc->setFamilyName(this->getFamilyName());
reed@google.com5526ede2013-03-25 13:03:37 +0000196 *isLocalStream = SkToBool(this->getLocalStream());
reed@google.com822bde72013-03-04 16:28:33 +0000197}
reed@google.com070da5e2013-03-27 20:01:49 +0000198
199///////////////////////////////////////////////////////////////////////////////