Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(542)

Side by Side Diff: skia/ext/SkFontHost_fontconfig.cpp

Issue 12391070: Call Skia's version of SkFontHost_fontconfig (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « content/zygote/zygote_main_linux.cc ('k') | skia/ext/SkFontHost_fontconfig_control.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /* libs/graphics/ports/SkFontHost_fontconfig.cpp
2 **
3 ** Copyright 2008, Google Inc.
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 ** http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17
18 // -----------------------------------------------------------------------------
19 // This file provides implementations of the font resolution members of
20 // SkFontHost by using the fontconfig[1] library. Fontconfig is usually found
21 // on Linux systems and handles configuration, parsing and caching issues
22 // involved with enumerating and matching fonts.
23 //
24 // [1] http://fontconfig.org
25 // -----------------------------------------------------------------------------
26
27 #include <map>
28 #include <string>
29
30 #include <sys/mman.h>
31 #include <sys/stat.h>
32 #include <unistd.h>
33
34 #include "base/compiler_specific.h"
35 #include "third_party/skia/src/core/SkFontDescriptor.h"
36 #include "SkFontHost.h"
37 #include "SkStream.h"
38 #include "SkFontHost_fontconfig_control.h"
39 #include "SkFontHost_fontconfig_impl.h"
40 #include "SkFontHost_fontconfig_direct.h"
41
42 static FontConfigInterface* global_fc_impl = NULL;
43
44 void SkiaFontConfigUseDirectImplementation() {
45 if (global_fc_impl)
46 delete global_fc_impl;
47 global_fc_impl = new FontConfigDirect;
48 }
49
50 void SkiaFontConfigSetImplementation(FontConfigInterface* font_config) {
51 if (global_fc_impl)
52 delete global_fc_impl;
53 global_fc_impl = font_config;
54 }
55
56 static FontConfigInterface* GetFcImpl() {
57 if (!global_fc_impl)
58 global_fc_impl = new FontConfigDirect;
59 return global_fc_impl;
60 }
61
62 SK_DECLARE_STATIC_MUTEX(global_remote_font_map_lock);
63 static std::map<uint32_t, std::pair<uint8_t*, size_t> >* global_remote_fonts;
64
65 // Initialize the map declared above. Note that its corresponding mutex must be
66 // locked before calling this function.
67 static void AllocateGlobalRemoteFontsMapOnce() {
68 if (!global_remote_fonts) {
69 global_remote_fonts =
70 new std::map<uint32_t, std::pair<uint8_t*, size_t> >();
71 }
72 }
73
74 static unsigned global_next_remote_font_id;
75
76 // This is the maximum size of the font cache.
77 static const unsigned kFontCacheMemoryBudget = 2 * 1024 * 1024; // 2MB
78
79 // UniqueIds are encoded as (filefaceid << 8) | style
80 // For system fonts, filefaceid = (fileid << 4) | face_index.
81 // For remote fonts, filefaceid = fileid.
82
83 static unsigned UniqueIdToFileFaceId(unsigned uniqueid)
84 {
85 return uniqueid >> 8;
86 }
87
88 static SkTypeface::Style UniqueIdToStyle(unsigned uniqueid)
89 {
90 return static_cast<SkTypeface::Style>(uniqueid & 0xff);
91 }
92
93 static unsigned FileFaceIdAndStyleToUniqueId(unsigned filefaceid,
94 SkTypeface::Style style)
95 {
96 SkASSERT((style & 0xff) == style);
97 return (filefaceid << 8) | static_cast<int>(style);
98 }
99
100 static const unsigned kRemoteFontMask = 0x00800000u;
101
102 static bool IsRemoteFont(unsigned filefaceid)
103 {
104 return filefaceid & kRemoteFontMask;
105 }
106
107 class FontConfigTypeface : public SkTypeface {
108 public:
109 FontConfigTypeface(Style style, uint32_t id)
110 : SkTypeface(style, id)
111 { }
112
113 virtual ~FontConfigTypeface()
114 {
115 const uint32_t id = uniqueID();
116 if (IsRemoteFont(UniqueIdToFileFaceId(id))) {
117 SkAutoMutexAcquire ac(global_remote_font_map_lock);
118 AllocateGlobalRemoteFontsMapOnce();
119 std::map<uint32_t, std::pair<uint8_t*, size_t> >::iterator iter
120 = global_remote_fonts->find(id);
121 if (iter != global_remote_fonts->end()) {
122 sk_free(iter->second.first); // remove the font on memory.
123 global_remote_fonts->erase(iter);
124 }
125 }
126 }
127 };
128
129 // static
130 SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
131 const char familyName[],
132 SkTypeface::Style style)
133 {
134 std::string resolved_family_name;
135
136 if (familyFace) {
137 // Given the fileid we can ask fontconfig for the familyname of the
138 // font.
139 const unsigned filefaceid = UniqueIdToFileFaceId(familyFace->uniqueID()) ;
140 if (!GetFcImpl()->Match(&resolved_family_name, NULL,
141 true /* filefaceid valid */, filefaceid, "",
142 NULL, 0, NULL, NULL)) {
143 return NULL;
144 }
145 } else if (familyName) {
146 resolved_family_name = familyName;
147 }
148
149 bool bold = style & SkTypeface::kBold;
150 bool italic = style & SkTypeface::kItalic;
151 unsigned filefaceid;
152 if (!GetFcImpl()->Match(NULL, &filefaceid,
153 false, -1, /* no filefaceid */
154 resolved_family_name, NULL, 0,
155 &bold, &italic)) {
156 return NULL;
157 }
158 const SkTypeface::Style resulting_style = static_cast<SkTypeface::Style>(
159 (bold ? SkTypeface::kBold : 0) |
160 (italic ? SkTypeface::kItalic : 0));
161
162 const unsigned id = FileFaceIdAndStyleToUniqueId(filefaceid,
163 resulting_style);
164 SkTypeface* typeface = SkNEW_ARGS(FontConfigTypeface, (resulting_style, id)) ;
165 return typeface;
166 }
167
168 // static
169 SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream)
170 {
171 if (!stream)
172 return NULL;
173
174 const size_t length = stream->read(0, 0);
175 if (!length)
176 return NULL;
177 if (length >= 1024 * 1024 * 1024)
178 return NULL; // don't accept too large fonts (>= 1GB) for safety.
179
180 uint8_t* font = (uint8_t*)sk_malloc_throw(length);
181 if (stream->read(font, length) != length) {
182 sk_free(font);
183 return NULL;
184 }
185
186 SkTypeface::Style style = static_cast<SkTypeface::Style>(0);
187 unsigned id = 0;
188 {
189 SkAutoMutexAcquire ac(global_remote_font_map_lock);
190 AllocateGlobalRemoteFontsMapOnce();
191 id = FileFaceIdAndStyleToUniqueId(
192 global_next_remote_font_id | kRemoteFontMask, style);
193
194 if (++global_next_remote_font_id >= kRemoteFontMask)
195 global_next_remote_font_id = 0;
196
197 if (!global_remote_fonts->insert(
198 std::make_pair(id, std::make_pair(font, length))).second) {
199 sk_free(font);
200 return NULL;
201 }
202 }
203
204 SkTypeface* typeface = SkNEW_ARGS(FontConfigTypeface, (style, id));
205 return typeface;
206 }
207
208 // static
209 SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[])
210 {
211 SkASSERT(!"SkFontHost::CreateTypefaceFromFile unimplemented");
212 return NULL;
213 }
214
215 uint32_t SkFontHost::NextLogicalFont(SkFontID curr, SkFontID orig) {
216 // We don't handle font fallback, WebKit does.
217 return 0;
218 }
219
220 ///////////////////////////////////////////////////////////////////////////////
221
222 // Serialize, Deserialize need to be compatible across platforms, hence the use
223 // of SkFontDescriptor.
224
225 void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) {
226 SkFontDescriptor desc(face->style());
227
228 std::string resolved_family_name;
229
230 const unsigned filefaceid = UniqueIdToFileFaceId(face->uniqueID());
231 if (GetFcImpl()->Match(&resolved_family_name, NULL,
232 true /* filefaceid valid */, filefaceid, "", NULL, 0, NULL, NULL))
233 desc.setFamilyName(resolved_family_name.c_str());
234 else
235 desc.setFamilyName("sans-serif");
236
237 // would also like other names (see SkFontDescriptor.h)
238
239 desc.serialize(stream);
240
241 // by convention, we also write out the actual sfnt data, preceeded by
242 // a packed-length. For now we skip that, so we just write the zero.
243 stream->writePackedUInt(0);
244 }
245
246 SkTypeface* SkFontHost::Deserialize(SkStream* stream) {
247 SkFontDescriptor desc(stream);
248
249 // by convention, Serialize will have also written the actual sfnt data.
250 // for now, we just want to skip it.
251 size_t size = stream->readPackedUInt();
252 stream->skip(size);
253
254 return SkFontHost::CreateTypeface(NULL, desc.getFamilyName(),
255 desc.getStyle());
256 }
257
258 ///////////////////////////////////////////////////////////////////////////////
259
260 class SkFileDescriptorStream : public SkStream {
261 public:
262 SkFileDescriptorStream(int fd) {
263 memory_ = NULL;
264 offset_ = 0;
265
266 // this ensures that if we fail in the constructor, we will safely
267 // ignore all subsequent calls to read() because we will always trim
268 // the requested size down to 0
269 length_ = 0;
270
271 struct stat st;
272 if (fstat(fd, &st))
273 return;
274
275 void* memory = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
276 close(fd);
277 if (memory == MAP_FAILED)
278 return;
279
280 memory_ = reinterpret_cast<uint8_t*>(memory);
281 length_ = st.st_size;
282 }
283
284 virtual ~SkFileDescriptorStream() {
285 munmap(const_cast<uint8_t*>(memory_), length_);
286 }
287
288 virtual bool rewind() OVERRIDE {
289 offset_ = 0;
290 return true;
291 }
292
293 // SkStream implementation.
294 virtual size_t read(void* buffer, size_t size) OVERRIDE {
295 if (!buffer && !size) {
296 // This is request for the length of the stream.
297 return length_;
298 }
299
300 size_t remaining = length_ - offset_;
301 if (size > remaining)
302 size = remaining;
303 if (buffer)
304 memcpy(buffer, memory_ + offset_, size);
305
306 offset_ += size;
307 return size;
308 }
309
310 virtual const void* getMemoryBase() OVERRIDE {
311 return memory_;
312 }
313
314 private:
315 const uint8_t* memory_;
316 size_t offset_, length_;
317 };
318
319 ///////////////////////////////////////////////////////////////////////////////
320
321 // static
322 SkStream* SkFontHost::OpenStream(uint32_t id)
323 {
324 const unsigned filefaceid = UniqueIdToFileFaceId(id);
325
326 if (IsRemoteFont(filefaceid)) {
327 // remote font
328 SkAutoMutexAcquire ac(global_remote_font_map_lock);
329 AllocateGlobalRemoteFontsMapOnce();
330 std::map<uint32_t, std::pair<uint8_t*, size_t> >::const_iterator iter
331 = global_remote_fonts->find(id);
332 if (iter == global_remote_fonts->end())
333 return NULL;
334 return SkNEW_ARGS(
335 SkMemoryStream, (iter->second.first, iter->second.second));
336 }
337
338 // system font
339 const int fd = GetFcImpl()->Open(filefaceid);
340 if (fd < 0)
341 return NULL;
342
343 return SkNEW_ARGS(SkFileDescriptorStream, (fd));
344 }
345
346 // static
347 size_t SkFontHost::GetFileName(SkFontID fontID, char path[], size_t length,
348 int32_t* index) {
349 const unsigned filefaceid = UniqueIdToFileFaceId(fontID);
350
351 if (IsRemoteFont(filefaceid))
352 return 0;
353
354 if (index) {
355 *index = filefaceid & 0xfu;
356 // 1 is a bogus return value.
357 // We had better change the signature of this function in Skia
358 // to return bool to indicate success/failure and have another
359 // out param for fileName length.
360 if (!path)
361 return 1;
362 }
363
364 if (path)
365 SkASSERT(!"SkFontHost::GetFileName does not support the font path "
366 "retrieval.");
367
368 return 0;
369 }
OLDNEW
« no previous file with comments | « content/zygote/zygote_main_linux.cc ('k') | skia/ext/SkFontHost_fontconfig_control.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698