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 #ifndef SK_FONTHOST_USES_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 } 213 214 SkTypeface* FontConfigTypeface::onRefMatchingStyle(Style style) const { 215 return LegacyCreateTypeface(this, NULL, style); 216 } 217