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

Side by Side Diff: trunk/src/ports/SkFontConfigInterface_direct.cpp

Issue 12319150: remove all global associative maps for fontconfig host (Closed) Base URL: http://skia.googlecode.com/svn/
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 | « trunk/include/ports/SkFontConfigInterface.h ('k') | trunk/src/ports/SkFontHost_fontconfig.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2009 Google Inc. 2 * Copyright 2009 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 /* migrated from chrome/src/skia/ext/SkFontHost_fontconfig_direct.cpp */ 8 /* migrated from chrome/src/skia/ext/SkFontHost_fontconfig_direct.cpp */
9 9
10 #include <map>
11 #include <string> 10 #include <string>
12 #include <unistd.h> 11 #include <unistd.h>
13 #include <fcntl.h> 12 #include <fcntl.h>
14 13
15 #include <fontconfig/fontconfig.h> 14 #include <fontconfig/fontconfig.h>
16 15
17 #include "SkFontConfigInterface.h" 16 #include "SkFontConfigInterface.h"
18 //#include "SkUtils.h"
19 #include "SkStream.h" 17 #include "SkStream.h"
20 18
21 class SkFontConfigInterfaceDirect : public SkFontConfigInterface { 19 class SkFontConfigInterfaceDirect : public SkFontConfigInterface {
22 public: 20 public:
23 SkFontConfigInterfaceDirect(); 21 SkFontConfigInterfaceDirect();
24 virtual ~SkFontConfigInterfaceDirect(); 22 virtual ~SkFontConfigInterfaceDirect();
25 23
26 virtual bool match(const char familyName[], SkTypeface::Style requested, 24 virtual bool matchFamilyName(const char familyName[],
27 unsigned* fileFaceID, SkTypeface::Style* outStyle) SK_OVERRIDE; 25 SkTypeface::Style requested,
28 virtual bool getFamilyName(unsigned fileFaceID, SkString* name) SK_OVERRIDE; 26 FontIdentity* outFontIdentifier,
29 virtual SkStream* openStream(unsigned fileFaceID) SK_OVERRIDE; 27 SkString* outFamilyName,
28 SkTypeface::Style* outStyle) SK_OVERRIDE;
29 virtual SkStream* openStream(const FontIdentity&) SK_OVERRIDE;
30 30
31 private: 31 private:
32 SkMutex mutex_; 32 SkMutex mutex_;
33
34 // fileid stored in two maps below are unique per font file.
35 std::map<unsigned, std::string> fileid_to_filename_;
36 std::map<std::string, unsigned> filename_to_fileid_;
37
38 // Cache of |family,style| to |FontMatch| to minimize querying FontConfig.
39 typedef std::pair<std::string, int> FontMatchKey;
40 struct FontMatch {
41 std::string family;
42 SkTypeface::Style style;
43 unsigned filefaceid;
44 };
45 std::map<FontMatchKey, FontMatch> font_match_cache_;
46
47 unsigned next_file_id_;
48 }; 33 };
49 34
50 SkFontConfigInterface* SkCreateDirectFontConfigInterface(); 35 SkFontConfigInterface* SkCreateDirectFontConfigInterface();
51 SkFontConfigInterface* SkCreateDirectFontConfigInterface() { 36 SkFontConfigInterface* SkCreateDirectFontConfigInterface() {
52 return SkNEW(SkFontConfigInterfaceDirect); 37 return SkNEW(SkFontConfigInterfaceDirect);
53 } 38 }
54 39
55 namespace { 40 namespace {
56 41
57 // Equivalence classes, used to match the Liberation and other fonts 42 // Equivalence classes, used to match the Liberation and other fonts
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 break; 268 break;
284 } 269 }
285 if (!acceptable_substitute) 270 if (!acceptable_substitute)
286 return NULL; 271 return NULL;
287 } 272 }
288 273
289 return match; 274 return match;
290 } 275 }
291 276
292 // Retrieves |is_bold|, |is_italic| and |font_family| properties from |font|. 277 // Retrieves |is_bold|, |is_italic| and |font_family| properties from |font|.
293 bool GetFontProperties(FcPattern* font, 278 SkTypeface::Style GetFontStyle(FcPattern* font) {
294 std::string* font_family,
295 SkTypeface::Style* style) {
296 FcChar8* c_family;
297 if (FcPatternGetString(font, FC_FAMILY, 0, &c_family))
298 return false;
299
300 int resulting_bold; 279 int resulting_bold;
301 if (FcPatternGetInteger(font, FC_WEIGHT, 0, &resulting_bold)) 280 if (FcPatternGetInteger(font, FC_WEIGHT, 0, &resulting_bold))
302 resulting_bold = FC_WEIGHT_NORMAL; 281 resulting_bold = FC_WEIGHT_NORMAL;
303 282
304 int resulting_italic; 283 int resulting_italic;
305 if (FcPatternGetInteger(font, FC_SLANT, 0, &resulting_italic)) 284 if (FcPatternGetInteger(font, FC_SLANT, 0, &resulting_italic))
306 resulting_italic = FC_SLANT_ROMAN; 285 resulting_italic = FC_SLANT_ROMAN;
307 286
308 // If we ask for an italic font, fontconfig might take a roman font and set 287 // If we ask for an italic font, fontconfig might take a roman font and set
309 // the undocumented property FC_MATRIX to a skew matrix. It'll then say 288 // the undocumented property FC_MATRIX to a skew matrix. It'll then say
310 // that the font is italic or oblique. So, if we see a matrix, we don't 289 // that the font is italic or oblique. So, if we see a matrix, we don't
311 // believe that it's italic. 290 // believe that it's italic.
312 FcValue matrix; 291 FcValue matrix;
313 const bool have_matrix = FcPatternGet(font, FC_MATRIX, 0, &matrix) == 0; 292 const bool have_matrix = FcPatternGet(font, FC_MATRIX, 0, &matrix) == 0;
314 293
315 // If we ask for an italic font, fontconfig might take a roman font and set 294 // If we ask for an italic font, fontconfig might take a roman font and set
316 // FC_EMBOLDEN. 295 // FC_EMBOLDEN.
317 FcValue embolden; 296 FcValue embolden;
318 const bool have_embolden = FcPatternGet(font, FC_EMBOLDEN, 0, &embolden) == 0; 297 const bool have_embolden = FcPatternGet(font, FC_EMBOLDEN, 0, &embolden) == 0;
319 298
320 int styleBits = 0; 299 int styleBits = 0;
321 if (resulting_bold > FC_WEIGHT_MEDIUM && !have_embolden) { 300 if (resulting_bold > FC_WEIGHT_MEDIUM && !have_embolden) {
322 styleBits |= SkTypeface::kBold; 301 styleBits |= SkTypeface::kBold;
323 } 302 }
324 if (resulting_italic > FC_SLANT_ROMAN && !have_matrix) { 303 if (resulting_italic > FC_SLANT_ROMAN && !have_matrix) {
325 styleBits |= SkTypeface::kItalic; 304 styleBits |= SkTypeface::kItalic;
326 } 305 }
327 306
328 *font_family = reinterpret_cast<char*>(c_family); 307 return (SkTypeface::Style)styleBits;
329 *style = (SkTypeface::Style)styleBits;
330 return true;
331 } 308 }
332 309
333 } // anonymous namespace 310 } // anonymous namespace
334 311
335 /////////////////////////////////////////////////////////////////////////////// 312 ///////////////////////////////////////////////////////////////////////////////
336 313
337 #define kMaxFontFamilyLength 1024 314 #define kMaxFontFamilyLength 2048
338 315
339 SkFontConfigInterfaceDirect::SkFontConfigInterfaceDirect() : next_file_id_(0) { 316 SkFontConfigInterfaceDirect::SkFontConfigInterfaceDirect() {
340 FcInit(); 317 FcInit();
341 } 318 }
342 319
343 SkFontConfigInterfaceDirect::~SkFontConfigInterfaceDirect() { 320 SkFontConfigInterfaceDirect::~SkFontConfigInterfaceDirect() {
344 } 321 }
345 322
346 bool SkFontConfigInterfaceDirect::match(const char familyName[], 323 bool SkFontConfigInterfaceDirect::matchFamilyName(const char familyName[],
347 SkTypeface::Style style, 324 SkTypeface::Style style,
348 unsigned* result_filefaceid, 325 FontIdentity* outIdentity,
349 SkTypeface::Style* result_style) { 326 SkString* outFamilyName,
327 SkTypeface::Style* outStyle) {
350 std::string familyStr(familyName ? familyName : ""); 328 std::string familyStr(familyName ? familyName : "");
351 if (familyStr.length() > kMaxFontFamilyLength) { 329 if (familyStr.length() > kMaxFontFamilyLength) {
352 return false; 330 return false;
353 } 331 }
354 332
355 SkAutoMutexAcquire ac(mutex_); 333 SkAutoMutexAcquire ac(mutex_);
356 334
357 // search our cache
358 {
359 FontMatchKey key = FontMatchKey(familyStr, style);
360 const std::map<FontMatchKey, FontMatch>::const_iterator i =
361 font_match_cache_.find(key);
362 if (i != font_match_cache_.end()) {
363 *result_style = i->second.style;
364 *result_filefaceid = i->second.filefaceid;
365 return true;
366 }
367 }
368
369 FcPattern* pattern = FcPatternCreate(); 335 FcPattern* pattern = FcPatternCreate();
370 336
371 if (familyName) { 337 if (familyName) {
372 FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName); 338 FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName);
373 } 339 }
374 FcPatternAddInteger(pattern, FC_WEIGHT, 340 FcPatternAddInteger(pattern, FC_WEIGHT,
375 (style & SkTypeface::kBold) ? FC_WEIGHT_BOLD 341 (style & SkTypeface::kBold) ? FC_WEIGHT_BOLD
376 : FC_WEIGHT_NORMAL); 342 : FC_WEIGHT_NORMAL);
377 FcPatternAddInteger(pattern, FC_SLANT, 343 FcPatternAddInteger(pattern, FC_SLANT,
378 (style & SkTypeface::kItalic) ? FC_SLANT_ITALIC 344 (style & SkTypeface::kItalic) ? FC_SLANT_ITALIC
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
422 388
423 FcPattern* match = MatchFont(font_set, post_config_family, familyStr); 389 FcPattern* match = MatchFont(font_set, post_config_family, familyStr);
424 if (!match) { 390 if (!match) {
425 FcPatternDestroy(pattern); 391 FcPatternDestroy(pattern);
426 FcFontSetDestroy(font_set); 392 FcFontSetDestroy(font_set);
427 return false; 393 return false;
428 } 394 }
429 395
430 FcPatternDestroy(pattern); 396 FcPatternDestroy(pattern);
431 397
398 // From here out we just extract our results from 'match'
399
400 if (FcPatternGetString(match, FC_FAMILY, 0, &post_config_family) != FcResult Match) {
401 FcFontSetDestroy(font_set);
402 return false;
403 }
404
432 FcChar8* c_filename; 405 FcChar8* c_filename;
433 if (FcPatternGetString(match, FC_FILE, 0, &c_filename) != FcResultMatch) { 406 if (FcPatternGetString(match, FC_FILE, 0, &c_filename) != FcResultMatch) {
434 FcFontSetDestroy(font_set); 407 FcFontSetDestroy(font_set);
435 return false; 408 return false;
436 } 409 }
410
437 int face_index; 411 int face_index;
438 if (FcPatternGetInteger(match, FC_INDEX, 0, &face_index) != FcResultMatch) { 412 if (FcPatternGetInteger(match, FC_INDEX, 0, &face_index) != FcResultMatch) {
439 FcFontSetDestroy(font_set); 413 FcFontSetDestroy(font_set);
440 return false; 414 return false;
441 } 415 }
442 416
443 FontMatch font_match;
444 {
445 unsigned out_fileid;
446 const std::string filename(reinterpret_cast<char*>(c_filename));
447 const std::map<std::string, unsigned>::const_iterator
448 i = filename_to_fileid_.find(filename);
449 if (i == filename_to_fileid_.end()) {
450 out_fileid = next_file_id_++;
451 filename_to_fileid_[filename] = out_fileid;
452 fileid_to_filename_[out_fileid] = filename;
453 } else {
454 out_fileid = i->second;
455 }
456 // fileid stored in filename_to_fileid_ and fileid_to_filename_ is
457 // unique only up to the font file. We have to encode face_index for
458 // the out param.
459 font_match.filefaceid =
460 FileIdAndFaceIndexToFileFaceId(out_fileid, face_index);
461 }
462
463 bool success = GetFontProperties(match,
464 &font_match.family,
465 &font_match.style);
466 FcFontSetDestroy(font_set); 417 FcFontSetDestroy(font_set);
467 418
468 if (success) { 419 if (outIdentity) {
469 font_match_cache_[FontMatchKey(familyStr, style)] = font_match; 420 outIdentity->fIntPtr = face_index;
470 *result_filefaceid = font_match.filefaceid; 421 outIdentity->fString.set((const char*)c_filename);
471 *result_style = font_match.style;
472 } 422 }
473 423 if (outFamilyName) {
474 return success; 424 outFamilyName->set((const char*)post_config_family);
425 }
426 if (outStyle) {
427 *outStyle = GetFontStyle(match);
428 }
429 return true;
475 } 430 }
476 431
477 #include <fontconfig/fcfreetype.h> 432 SkStream* SkFontConfigInterfaceDirect::openStream(const FontIdentity& identity) {
478 433 int fd = open(identity.fString.c_str(), O_RDONLY);
479 bool SkFontConfigInterfaceDirect::getFamilyName(unsigned filefaceid, 434 return (fd >= 0) ? SkNEW_ARGS(SkFDStream, (fd, true)) : NULL;
480 SkString* result_family) {
481 SkAutoMutexAcquire ac(mutex_);
482
483 #if 0
484 FcPattern* pattern = FcPatternCreate();
485 SkString filename;
486
487 {
488 const std::map<unsigned, std::string>::const_iterator
489 i = fileid_to_filename_.find(FileFaceIdToFileId(filefaceid));
490 if (i == fileid_to_filename_.end()) {
491 FcPatternDestroy(pattern);
492 return false;
493 }
494 int face_index = filefaceid & 0xfu;
495 filename.set(i->second.c_str());
496 FcPatternAddString(pattern, FC_FILE,
497 reinterpret_cast<const FcChar8*>(i->second.c_str()));
498 FcPatternAddInteger(pattern, FC_INDEX, face_index);
499 }
500
501 FcPatternAddBool(pattern, FC_SCALABLE, FcTrue);
502
503 FcConfigSubstitute(NULL, pattern, FcMatchPattern);
504 FcDefaultSubstitute(pattern);
505
506 FcResult result;
507 FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result);
508 if (!font_set || font_set->nfont <= 0) {
509 FcPatternDestroy(pattern);
510 return false;
511 }
512
513 bool found = false;
514 for (int i = 0; i < font_set->nfont; ++i) {
515 FcChar8* file;
516 FcPatternGetString(font_set->fonts[i], FC_FILE, 0, &file);
517 if (filename.equals((const char*)file)) {
518 FcChar8* family;
519 FcPatternGetString(font_set->fonts[i], FC_FAMILY, 0, &family);
520 result_family->set((const char*)family);
521 found = true;
522 break;
523 }
524 }
525
526 FcPatternDestroy(pattern);
527 FcFontSetDestroy(font_set);
528 return found;
529 #else
530 const std::map<unsigned, std::string>::const_iterator
531 i = fileid_to_filename_.find(FileFaceIdToFileId(filefaceid));
532 if (i == fileid_to_filename_.end()) {
533 return false;
534 }
535
536 int face_index = filefaceid & 0xfu;
537 int count;
538 FcPattern* pattern = FcFreeTypeQuery((const FcChar8*)i->second.c_str(),
539 face_index, NULL, &count);
540 if (!pattern || count <= 0) {
541 return false;
542 }
543
544 FcChar8* family;
545 FcPatternGetString(pattern, FC_FAMILY, 0, &family);
546
547 result_family->set((const char*)family);
548 return true;
549 #endif
550 } 435 }
551 436
552 SkStream* SkFontConfigInterfaceDirect::openStream(unsigned filefaceid) { 437
553 SkAutoMutexAcquire ac(mutex_);
554 const std::map<unsigned, std::string>::const_iterator
555 i = fileid_to_filename_.find(FileFaceIdToFileId(filefaceid));
556 if (i == fileid_to_filename_.end()) {
557 return NULL;
558 }
559 int fd = open(i->second.c_str(), O_RDONLY);
560 return (fd >= 0) ? SkNEW_ARGS(SkFDStream, (fd, true)) : NULL;
561 }
OLDNEW
« no previous file with comments | « trunk/include/ports/SkFontConfigInterface.h ('k') | trunk/src/ports/SkFontHost_fontconfig.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698