|
1 /* |
|
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 |
|
8 #include "SkFontConfigInterface.h" |
|
9 #include "SkFontConfigTypeface.h" |
|
10 #include "SkFontDescriptor.h" |
|
11 #include "SkFontHost.h" |
|
12 #include "SkFontHost_FreeType_common.h" |
|
13 #include "SkFontStream.h" |
|
14 #include "SkStream.h" |
|
15 #include "SkTypeface.h" |
|
16 #include "SkTypefaceCache.h" |
|
17 |
|
18 // Defined in SkFontHost_FreeType.cpp |
|
19 bool find_name_and_attributes(SkStream* stream, SkString* name, |
|
20 SkTypeface::Style* style, bool* isFixedWidth); |
|
21 |
|
22 /////////////////////////////////////////////////////////////////////////////// |
|
23 /////////////////////////////////////////////////////////////////////////////// |
|
24 |
|
25 SK_DECLARE_STATIC_MUTEX(gFontConfigInterfaceMutex); |
|
26 static SkFontConfigInterface* gFontConfigInterface; |
|
27 |
|
28 SkFontConfigInterface* SkFontConfigInterface::RefGlobal() { |
|
29 SkAutoMutexAcquire ac(gFontConfigInterfaceMutex); |
|
30 |
|
31 return SkSafeRef(gFontConfigInterface); |
|
32 } |
|
33 |
|
34 SkFontConfigInterface* SkFontConfigInterface::SetGlobal(SkFontConfigInterface* fc) { |
|
35 SkAutoMutexAcquire ac(gFontConfigInterfaceMutex); |
|
36 |
|
37 SkRefCnt_SafeAssign(gFontConfigInterface, fc); |
|
38 return fc; |
|
39 } |
|
40 |
|
41 /////////////////////////////////////////////////////////////////////////////// |
|
42 /////////////////////////////////////////////////////////////////////////////// |
|
43 |
|
44 // convenience function to create the direct interface if none is installed. |
|
45 extern SkFontConfigInterface* SkCreateDirectFontConfigInterface(); |
|
46 |
|
47 static SkFontConfigInterface* RefFCI() { |
|
48 for (;;) { |
|
49 SkFontConfigInterface* fci = SkFontConfigInterface::RefGlobal(); |
|
50 if (fci) { |
|
51 return fci; |
|
52 } |
|
53 fci = SkFontConfigInterface::GetSingletonDirectInterface(); |
|
54 SkFontConfigInterface::SetGlobal(fci); |
|
55 } |
|
56 } |
|
57 |
|
58 // export this to SkFontMgr_fontconfig.cpp until this file just goes away. |
|
59 SkFontConfigInterface* SkFontHost_fontconfig_ref_global(); |
|
60 SkFontConfigInterface* SkFontHost_fontconfig_ref_global() { |
|
61 return RefFCI(); |
|
62 } |
|
63 |
|
64 /////////////////////////////////////////////////////////////////////////////// |
|
65 |
|
66 struct FindRec { |
|
67 FindRec(const char* name, SkTypeface::Style style) |
|
68 : fFamilyName(name) // don't need to make a deep copy |
|
69 , fStyle(style) {} |
|
70 |
|
71 const char* fFamilyName; |
|
72 SkTypeface::Style fStyle; |
|
73 }; |
|
74 |
|
75 static bool find_proc(SkTypeface* face, SkTypeface::Style style, void* ctx) { |
|
76 FontConfigTypeface* fci = (FontConfigTypeface*)face; |
|
77 const FindRec* rec = (const FindRec*)ctx; |
|
78 |
|
79 return rec->fStyle == style && fci->isFamilyName(rec->fFamilyName); |
|
80 } |
|
81 |
|
82 SkTypeface* FontConfigTypeface::LegacyCreateTypeface( |
|
83 const SkTypeface* familyFace, |
|
84 const char familyName[], |
|
85 SkTypeface::Style style) { |
|
86 SkAutoTUnref<SkFontConfigInterface> fci(RefFCI()); |
|
87 if (NULL == fci.get()) { |
|
88 return NULL; |
|
89 } |
|
90 |
|
91 if (familyFace) { |
|
92 FontConfigTypeface* fct = (FontConfigTypeface*)familyFace; |
|
93 familyName = fct->getFamilyName(); |
|
94 } |
|
95 |
|
96 FindRec rec(familyName, style); |
|
97 SkTypeface* face = SkTypefaceCache::FindByProcAndRef(find_proc, &rec); |
|
98 if (face) { |
|
99 // SkDebugf("found cached face <%s> <%s> %p [%d]\n", familyName, ((FontConfigTypeface*)face)->getFamilyName(), face, face->getRefCnt()); |
|
100 return face; |
|
101 } |
|
102 |
|
103 SkFontConfigInterface::FontIdentity indentity; |
|
104 SkString outFamilyName; |
|
105 SkTypeface::Style outStyle; |
|
106 |
|
107 if (!fci->matchFamilyName(familyName, style, |
|
108 &indentity, &outFamilyName, &outStyle)) { |
|
109 return NULL; |
|
110 } |
|
111 |
|
112 // check if we, in fact, already have this. perhaps fontconfig aliased the |
|
113 // requested name to some other name we actually have... |
|
114 rec.fFamilyName = outFamilyName.c_str(); |
|
115 rec.fStyle = outStyle; |
|
116 face = SkTypefaceCache::FindByProcAndRef(find_proc, &rec); |
|
117 if (face) { |
|
118 return face; |
|
119 } |
|
120 |
|
121 face = SkNEW_ARGS(FontConfigTypeface, (outStyle, indentity, outFamilyName)); |
|
122 SkTypefaceCache::Add(face, style); |
|
123 // SkDebugf("add face <%s> <%s> %p [%d]\n", familyName, outFamilyName.c_str(), face, face->getRefCnt()); |
|
124 return face; |
|
125 } |
|
126 |
|
127 #ifdef SK_FONTHOST_DOES_NOT_USE_FONTMGR |
|
128 |
|
129 SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace, |
|
130 const char familyName[], |
|
131 SkTypeface::Style style) { |
|
132 return FontConfigTypeface::LegacyCreateTypeface(familyFace, familyName, |
|
133 style); |
|
134 } |
|
135 |
|
136 SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) { |
|
137 if (!stream) { |
|
138 return NULL; |
|
139 } |
|
140 const size_t length = stream->getLength(); |
|
141 if (!length) { |
|
142 return NULL; |
|
143 } |
|
144 if (length >= 1024 * 1024 * 1024) { |
|
145 return NULL; // don't accept too large fonts (>= 1GB) for safety. |
|
146 } |
|
147 |
|
148 // ask freetype for reported style and if it is a fixed width font |
|
149 SkTypeface::Style style = SkTypeface::kNormal; |
|
150 bool isFixedWidth = false; |
|
151 if (!find_name_and_attributes(stream, NULL, &style, &isFixedWidth)) { |
|
152 return NULL; |
|
153 } |
|
154 |
|
155 SkTypeface* face = SkNEW_ARGS(FontConfigTypeface, (style, isFixedWidth, stream)); |
|
156 return face; |
|
157 } |
|
158 |
|
159 SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) { |
|
160 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path)); |
|
161 return stream.get() ? CreateTypefaceFromStream(stream) : NULL; |
|
162 } |
|
163 |
|
164 #endif |
|
165 |
|
166 /////////////////////////////////////////////////////////////////////////////// |
|
167 |
|
168 SkStream* FontConfigTypeface::onOpenStream(int* ttcIndex) const { |
|
169 SkStream* stream = this->getLocalStream(); |
|
170 if (stream) { |
|
171 // should have been provided by CreateFromStream() |
|
172 *ttcIndex = 0; |
|
173 |
|
174 SkAutoTUnref<SkStream> dupStream(stream->duplicate()); |
|
175 if (dupStream) { |
|
176 return dupStream.detach(); |
|
177 } |
|
178 |
|
179 // TODO: update interface use, remove the following code in this block. |
|
180 size_t length = stream->getLength(); |
|
181 |
|
182 const void* memory = stream->getMemoryBase(); |
|
183 if (NULL != memory) { |
|
184 return new SkMemoryStream(memory, length, true); |
|
185 } |
|
186 |
|
187 SkAutoTMalloc<uint8_t> allocMemory(length); |
|
188 stream->rewind(); |
|
189 if (length == stream->read(allocMemory.get(), length)) { |
|
190 SkAutoTUnref<SkMemoryStream> copyStream(new SkMemoryStream()); |
|
191 copyStream->setMemoryOwned(allocMemory.detach(), length); |
|
192 return copyStream.detach(); |
|
193 } |
|
194 |
|
195 stream->rewind(); |
|
196 stream->ref(); |
|
197 } else { |
|
198 SkAutoTUnref<SkFontConfigInterface> fci(RefFCI()); |
|
199 if (NULL == fci.get()) { |
|
200 return NULL; |
|
201 } |
|
202 stream = fci->openStream(this->getIdentity()); |
|
203 *ttcIndex = this->getIdentity().fTTCIndex; |
|
204 } |
|
205 return stream; |
|
206 } |
|
207 |
|
208 void FontConfigTypeface::onGetFontDescriptor(SkFontDescriptor* desc, |
|
209 bool* isLocalStream) const { |
|
210 desc->setFamilyName(this->getFamilyName()); |
|
211 *isLocalStream = SkToBool(this->getLocalStream()); |
|
212 } |