epoger@google.com | ec3ed6a | 2011-07-28 14:26:00 +0000 | [diff] [blame] | 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 | |
reed@google.com | d71fe99 | 2013-02-25 20:38:07 +0000 | [diff] [blame] | 8 | #include "SkFontConfigInterface.h" |
djsollen@google.com | 6930b57 | 2013-05-15 20:11:20 +0000 | [diff] [blame] | 9 | #include "SkFontConfigTypeface.h" |
reed@google.com | d71fe99 | 2013-02-25 20:38:07 +0000 | [diff] [blame] | 10 | #include "SkFontDescriptor.h" |
agl@chromium.org | df8ecfb | 2009-04-28 17:30:01 +0000 | [diff] [blame] | 11 | #include "SkStream.h" |
reed@google.com | 80f5465 | 2013-02-25 22:19:20 +0000 | [diff] [blame] | 12 | #include "SkTypeface.h" |
reed@google.com | f71a233 | 2013-02-27 19:06:30 +0000 | [diff] [blame] | 13 | #include "SkTypefaceCache.h" |
reed@google.com | b1c65b6 | 2013-02-26 15:50:51 +0000 | [diff] [blame] | 14 | |
djsollen@google.com | 6d2fef9 | 2013-09-06 18:00:04 +0000 | [diff] [blame] | 15 | /////////////////////////////////////////////////////////////////////////////// |
| 16 | /////////////////////////////////////////////////////////////////////////////// |
| 17 | |
reed@google.com | d71fe99 | 2013-02-25 20:38:07 +0000 | [diff] [blame] | 18 | SK_DECLARE_STATIC_MUTEX(gFontConfigInterfaceMutex); |
| 19 | static SkFontConfigInterface* gFontConfigInterface; |
agl@chromium.org | df8ecfb | 2009-04-28 17:30:01 +0000 | [diff] [blame] | 20 | |
reed@google.com | d71fe99 | 2013-02-25 20:38:07 +0000 | [diff] [blame] | 21 | SkFontConfigInterface* SkFontConfigInterface::RefGlobal() { |
| 22 | SkAutoMutexAcquire ac(gFontConfigInterfaceMutex); |
skia.committer@gmail.com | 5ca3bd0 | 2013-02-26 07:01:22 +0000 | [diff] [blame] | 23 | |
reed@google.com | d71fe99 | 2013-02-25 20:38:07 +0000 | [diff] [blame] | 24 | return SkSafeRef(gFontConfigInterface); |
| 25 | } |
bungeman@google.com | b13d63c | 2012-11-06 16:55:24 +0000 | [diff] [blame] | 26 | |
reed@google.com | d71fe99 | 2013-02-25 20:38:07 +0000 | [diff] [blame] | 27 | SkFontConfigInterface* SkFontConfigInterface::SetGlobal(SkFontConfigInterface* fc) { |
| 28 | SkAutoMutexAcquire ac(gFontConfigInterfaceMutex); |
agl@chromium.org | df8ecfb | 2009-04-28 17:30:01 +0000 | [diff] [blame] | 29 | |
reed@google.com | d71fe99 | 2013-02-25 20:38:07 +0000 | [diff] [blame] | 30 | SkRefCnt_SafeAssign(gFontConfigInterface, fc); |
| 31 | return fc; |
| 32 | } |
bungeman@google.com | b13d63c | 2012-11-06 16:55:24 +0000 | [diff] [blame] | 33 | |
reed@google.com | d71fe99 | 2013-02-25 20:38:07 +0000 | [diff] [blame] | 34 | /////////////////////////////////////////////////////////////////////////////// |
reed@google.com | f71a233 | 2013-02-27 19:06:30 +0000 | [diff] [blame] | 35 | /////////////////////////////////////////////////////////////////////////////// |
| 36 | |
| 37 | // convenience function to create the direct interface if none is installed. |
| 38 | extern SkFontConfigInterface* SkCreateDirectFontConfigInterface(); |
reed@google.com | d71fe99 | 2013-02-25 20:38:07 +0000 | [diff] [blame] | 39 | |
reed@google.com | 80f5465 | 2013-02-25 22:19:20 +0000 | [diff] [blame] | 40 | static SkFontConfigInterface* RefFCI() { |
reed@google.com | b1c65b6 | 2013-02-26 15:50:51 +0000 | [diff] [blame] | 41 | for (;;) { |
| 42 | SkFontConfigInterface* fci = SkFontConfigInterface::RefGlobal(); |
| 43 | if (fci) { |
| 44 | return fci; |
| 45 | } |
tomhudson | e438ddb | 2014-07-01 18:54:41 -0700 | [diff] [blame] | 46 | fci = SkFontConfigInterface::GetSingletonDirectInterface(&gFontConfigInterfaceMutex); |
reed@google.com | 750a24b | 2013-04-22 18:45:12 +0000 | [diff] [blame] | 47 | SkFontConfigInterface::SetGlobal(fci); |
reed@google.com | b1c65b6 | 2013-02-26 15:50:51 +0000 | [diff] [blame] | 48 | } |
reed@google.com | 80f5465 | 2013-02-25 22:19:20 +0000 | [diff] [blame] | 49 | } |
| 50 | |
reed@google.com | 381bb43 | 2013-05-13 19:43:59 +0000 | [diff] [blame] | 51 | // export this to SkFontMgr_fontconfig.cpp until this file just goes away. |
| 52 | SkFontConfigInterface* SkFontHost_fontconfig_ref_global(); |
| 53 | SkFontConfigInterface* SkFontHost_fontconfig_ref_global() { |
| 54 | return RefFCI(); |
| 55 | } |
| 56 | |
| 57 | /////////////////////////////////////////////////////////////////////////////// |
| 58 | |
bungeman | e892616 | 2015-02-19 07:29:28 -0800 | [diff] [blame] | 59 | struct NameStyle { |
| 60 | NameStyle(const char* name, const SkFontStyle& style) |
reed@google.com | f71a233 | 2013-02-27 19:06:30 +0000 | [diff] [blame] | 61 | : fFamilyName(name) // don't need to make a deep copy |
| 62 | , fStyle(style) {} |
| 63 | |
| 64 | const char* fFamilyName; |
bungeman | a4c4a2d | 2014-10-20 13:33:19 -0700 | [diff] [blame] | 65 | SkFontStyle fStyle; |
reed@google.com | f71a233 | 2013-02-27 19:06:30 +0000 | [diff] [blame] | 66 | }; |
| 67 | |
bungeman | e892616 | 2015-02-19 07:29:28 -0800 | [diff] [blame] | 68 | static bool find_by_NameStyle(SkTypeface* cachedTypeface, |
| 69 | const SkFontStyle& cachedStyle, |
| 70 | void* ctx) |
| 71 | { |
| 72 | FontConfigTypeface* cachedFCTypeface = static_cast<FontConfigTypeface*>(cachedTypeface); |
| 73 | const NameStyle* nameStyle = static_cast<const NameStyle*>(ctx); |
reed@google.com | f71a233 | 2013-02-27 19:06:30 +0000 | [diff] [blame] | 74 | |
bungeman | e892616 | 2015-02-19 07:29:28 -0800 | [diff] [blame] | 75 | return nameStyle->fStyle == cachedStyle && |
| 76 | cachedFCTypeface->isFamilyName(nameStyle->fFamilyName); |
reed@google.com | f71a233 | 2013-02-27 19:06:30 +0000 | [diff] [blame] | 77 | } |
| 78 | |
bungeman | e892616 | 2015-02-19 07:29:28 -0800 | [diff] [blame] | 79 | static bool find_by_FontIdentity(SkTypeface* cachedTypeface, const SkFontStyle&, void* ctx) { |
| 80 | typedef SkFontConfigInterface::FontIdentity FontIdentity; |
| 81 | FontConfigTypeface* cachedFCTypeface = static_cast<FontConfigTypeface*>(cachedTypeface); |
| 82 | FontIdentity* indentity = static_cast<FontIdentity*>(ctx); |
| 83 | |
| 84 | return cachedFCTypeface->getIdentity() == *indentity; |
| 85 | } |
| 86 | |
| 87 | SkTypeface* FontConfigTypeface::LegacyCreateTypeface(const char familyName[], |
| 88 | SkTypeface::Style style) |
| 89 | { |
reed@google.com | 80f5465 | 2013-02-25 22:19:20 +0000 | [diff] [blame] | 90 | SkAutoTUnref<SkFontConfigInterface> fci(RefFCI()); |
halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 91 | if (nullptr == fci.get()) { |
| 92 | return nullptr; |
reed@google.com | 80f5465 | 2013-02-25 22:19:20 +0000 | [diff] [blame] | 93 | } |
| 94 | |
bungeman | e892616 | 2015-02-19 07:29:28 -0800 | [diff] [blame] | 95 | // Check if requested NameStyle is in the NameStyle cache. |
bungeman | a4c4a2d | 2014-10-20 13:33:19 -0700 | [diff] [blame] | 96 | SkFontStyle requestedStyle(style); |
bungeman | e892616 | 2015-02-19 07:29:28 -0800 | [diff] [blame] | 97 | NameStyle nameStyle(familyName, requestedStyle); |
| 98 | SkTypeface* face = SkTypefaceCache::FindByProcAndRef(find_by_NameStyle, &nameStyle); |
reed@google.com | f71a233 | 2013-02-27 19:06:30 +0000 | [diff] [blame] | 99 | if (face) { |
bungeman | a4c4a2d | 2014-10-20 13:33:19 -0700 | [diff] [blame] | 100 | //SkDebugf("found cached face <%s> <%s> %p [%d]\n", |
| 101 | // familyName, ((FontConfigTypeface*)face)->getFamilyName(), |
| 102 | // face, face->getRefCnt()); |
reed@google.com | f71a233 | 2013-02-27 19:06:30 +0000 | [diff] [blame] | 103 | return face; |
| 104 | } |
| 105 | |
| 106 | SkFontConfigInterface::FontIdentity indentity; |
bungeman | a4c4a2d | 2014-10-20 13:33:19 -0700 | [diff] [blame] | 107 | SkString outFamilyName; |
| 108 | SkTypeface::Style outStyle; |
| 109 | if (!fci->matchFamilyName(familyName, style, &indentity, &outFamilyName, &outStyle)) { |
halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 110 | return nullptr; |
agl@chromium.org | df8ecfb | 2009-04-28 17:30:01 +0000 | [diff] [blame] | 111 | } |
agl@chromium.org | df8ecfb | 2009-04-28 17:30:01 +0000 | [diff] [blame] | 112 | |
bungeman | e892616 | 2015-02-19 07:29:28 -0800 | [diff] [blame] | 113 | // Check if a typeface with this FontIdentity is already in the FontIdentity cache. |
| 114 | face = SkTypefaceCache::FindByProcAndRef(find_by_FontIdentity, &indentity); |
| 115 | if (!face) { |
| 116 | face = FontConfigTypeface::Create(SkFontStyle(outStyle), indentity, outFamilyName); |
| 117 | // Add this FontIdentity to the FontIdentity cache. |
| 118 | SkTypefaceCache::Add(face, requestedStyle); |
reed@google.com | d44d988 | 2013-09-18 20:32:25 +0000 | [diff] [blame] | 119 | } |
bungeman | e892616 | 2015-02-19 07:29:28 -0800 | [diff] [blame] | 120 | // TODO: Ensure requested NameStyle and resolved NameStyle are both in the NameStyle cache. |
reed@google.com | d44d988 | 2013-09-18 20:32:25 +0000 | [diff] [blame] | 121 | |
bungeman | a4c4a2d | 2014-10-20 13:33:19 -0700 | [diff] [blame] | 122 | //SkDebugf("add face <%s> <%s> %p [%d]\n", |
| 123 | // familyName, outFamilyName.c_str(), |
| 124 | // face, face->getRefCnt()); |
reed@google.com | f71a233 | 2013-02-27 19:06:30 +0000 | [diff] [blame] | 125 | return face; |
agl@chromium.org | df8ecfb | 2009-04-28 17:30:01 +0000 | [diff] [blame] | 126 | } |
| 127 | |
reed@google.com | 822bde7 | 2013-03-04 16:28:33 +0000 | [diff] [blame] | 128 | /////////////////////////////////////////////////////////////////////////////// |
| 129 | |
bungeman | 5f213d9 | 2015-01-27 05:39:10 -0800 | [diff] [blame] | 130 | SkStreamAsset* FontConfigTypeface::onOpenStream(int* ttcIndex) const { |
| 131 | SkStreamAsset* stream = this->getLocalStream(); |
reed@google.com | f71a233 | 2013-02-27 19:06:30 +0000 | [diff] [blame] | 132 | if (stream) { |
bungeman | 5f213d9 | 2015-01-27 05:39:10 -0800 | [diff] [blame] | 133 | // TODO: should have been provided by CreateFromStream() |
reed@google.com | 5bfc839 | 2013-03-05 22:12:11 +0000 | [diff] [blame] | 134 | *ttcIndex = 0; |
bungeman | 5f213d9 | 2015-01-27 05:39:10 -0800 | [diff] [blame] | 135 | return stream->duplicate(); |
reed@google.com | f71a233 | 2013-02-27 19:06:30 +0000 | [diff] [blame] | 136 | } |
bungeman | 5f213d9 | 2015-01-27 05:39:10 -0800 | [diff] [blame] | 137 | |
| 138 | SkAutoTUnref<SkFontConfigInterface> fci(RefFCI()); |
halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 139 | if (nullptr == fci.get()) { |
| 140 | return nullptr; |
bungeman | 5f213d9 | 2015-01-27 05:39:10 -0800 | [diff] [blame] | 141 | } |
| 142 | |
| 143 | *ttcIndex = this->getIdentity().fTTCIndex; |
| 144 | return fci->openStream(this->getIdentity()); |
reed@google.com | d71fe99 | 2013-02-25 20:38:07 +0000 | [diff] [blame] | 145 | } |
| 146 | |
bungeman | b374d6a | 2014-09-17 07:48:59 -0700 | [diff] [blame] | 147 | void FontConfigTypeface::onGetFamilyName(SkString* familyName) const { |
bungeman | cd87c51 | 2015-02-18 13:22:26 -0800 | [diff] [blame] | 148 | *familyName = fFamilyName; |
bungeman | b374d6a | 2014-09-17 07:48:59 -0700 | [diff] [blame] | 149 | } |
| 150 | |
reed@google.com | 5526ede | 2013-03-25 13:03:37 +0000 | [diff] [blame] | 151 | void FontConfigTypeface::onGetFontDescriptor(SkFontDescriptor* desc, |
| 152 | bool* isLocalStream) const { |
bungeman | cd87c51 | 2015-02-18 13:22:26 -0800 | [diff] [blame] | 153 | SkString name; |
| 154 | this->getFamilyName(&name); |
| 155 | desc->setFamilyName(name.c_str()); |
reed@google.com | 5526ede | 2013-03-25 13:03:37 +0000 | [diff] [blame] | 156 | *isLocalStream = SkToBool(this->getLocalStream()); |
reed@google.com | 822bde7 | 2013-03-04 16:28:33 +0000 | [diff] [blame] | 157 | } |