1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/ports/SkFontHost_fontconfig.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,212 @@ 1.4 +/* 1.5 + * Copyright 2008 Google Inc. 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license that can be 1.8 + * found in the LICENSE file. 1.9 + */ 1.10 + 1.11 +#include "SkFontConfigInterface.h" 1.12 +#include "SkFontConfigTypeface.h" 1.13 +#include "SkFontDescriptor.h" 1.14 +#include "SkFontHost.h" 1.15 +#include "SkFontHost_FreeType_common.h" 1.16 +#include "SkFontStream.h" 1.17 +#include "SkStream.h" 1.18 +#include "SkTypeface.h" 1.19 +#include "SkTypefaceCache.h" 1.20 + 1.21 +// Defined in SkFontHost_FreeType.cpp 1.22 +bool find_name_and_attributes(SkStream* stream, SkString* name, 1.23 + SkTypeface::Style* style, bool* isFixedWidth); 1.24 + 1.25 +/////////////////////////////////////////////////////////////////////////////// 1.26 +/////////////////////////////////////////////////////////////////////////////// 1.27 + 1.28 +SK_DECLARE_STATIC_MUTEX(gFontConfigInterfaceMutex); 1.29 +static SkFontConfigInterface* gFontConfigInterface; 1.30 + 1.31 +SkFontConfigInterface* SkFontConfigInterface::RefGlobal() { 1.32 + SkAutoMutexAcquire ac(gFontConfigInterfaceMutex); 1.33 + 1.34 + return SkSafeRef(gFontConfigInterface); 1.35 +} 1.36 + 1.37 +SkFontConfigInterface* SkFontConfigInterface::SetGlobal(SkFontConfigInterface* fc) { 1.38 + SkAutoMutexAcquire ac(gFontConfigInterfaceMutex); 1.39 + 1.40 + SkRefCnt_SafeAssign(gFontConfigInterface, fc); 1.41 + return fc; 1.42 +} 1.43 + 1.44 +/////////////////////////////////////////////////////////////////////////////// 1.45 +/////////////////////////////////////////////////////////////////////////////// 1.46 + 1.47 +// convenience function to create the direct interface if none is installed. 1.48 +extern SkFontConfigInterface* SkCreateDirectFontConfigInterface(); 1.49 + 1.50 +static SkFontConfigInterface* RefFCI() { 1.51 + for (;;) { 1.52 + SkFontConfigInterface* fci = SkFontConfigInterface::RefGlobal(); 1.53 + if (fci) { 1.54 + return fci; 1.55 + } 1.56 + fci = SkFontConfigInterface::GetSingletonDirectInterface(); 1.57 + SkFontConfigInterface::SetGlobal(fci); 1.58 + } 1.59 +} 1.60 + 1.61 +// export this to SkFontMgr_fontconfig.cpp until this file just goes away. 1.62 +SkFontConfigInterface* SkFontHost_fontconfig_ref_global(); 1.63 +SkFontConfigInterface* SkFontHost_fontconfig_ref_global() { 1.64 + return RefFCI(); 1.65 +} 1.66 + 1.67 +/////////////////////////////////////////////////////////////////////////////// 1.68 + 1.69 +struct FindRec { 1.70 + FindRec(const char* name, SkTypeface::Style style) 1.71 + : fFamilyName(name) // don't need to make a deep copy 1.72 + , fStyle(style) {} 1.73 + 1.74 + const char* fFamilyName; 1.75 + SkTypeface::Style fStyle; 1.76 +}; 1.77 + 1.78 +static bool find_proc(SkTypeface* face, SkTypeface::Style style, void* ctx) { 1.79 + FontConfigTypeface* fci = (FontConfigTypeface*)face; 1.80 + const FindRec* rec = (const FindRec*)ctx; 1.81 + 1.82 + return rec->fStyle == style && fci->isFamilyName(rec->fFamilyName); 1.83 +} 1.84 + 1.85 +SkTypeface* FontConfigTypeface::LegacyCreateTypeface( 1.86 + const SkTypeface* familyFace, 1.87 + const char familyName[], 1.88 + SkTypeface::Style style) { 1.89 + SkAutoTUnref<SkFontConfigInterface> fci(RefFCI()); 1.90 + if (NULL == fci.get()) { 1.91 + return NULL; 1.92 + } 1.93 + 1.94 + if (familyFace) { 1.95 + FontConfigTypeface* fct = (FontConfigTypeface*)familyFace; 1.96 + familyName = fct->getFamilyName(); 1.97 + } 1.98 + 1.99 + FindRec rec(familyName, style); 1.100 + SkTypeface* face = SkTypefaceCache::FindByProcAndRef(find_proc, &rec); 1.101 + if (face) { 1.102 +// SkDebugf("found cached face <%s> <%s> %p [%d]\n", familyName, ((FontConfigTypeface*)face)->getFamilyName(), face, face->getRefCnt()); 1.103 + return face; 1.104 + } 1.105 + 1.106 + SkFontConfigInterface::FontIdentity indentity; 1.107 + SkString outFamilyName; 1.108 + SkTypeface::Style outStyle; 1.109 + 1.110 + if (!fci->matchFamilyName(familyName, style, 1.111 + &indentity, &outFamilyName, &outStyle)) { 1.112 + return NULL; 1.113 + } 1.114 + 1.115 + // check if we, in fact, already have this. perhaps fontconfig aliased the 1.116 + // requested name to some other name we actually have... 1.117 + rec.fFamilyName = outFamilyName.c_str(); 1.118 + rec.fStyle = outStyle; 1.119 + face = SkTypefaceCache::FindByProcAndRef(find_proc, &rec); 1.120 + if (face) { 1.121 + return face; 1.122 + } 1.123 + 1.124 + face = SkNEW_ARGS(FontConfigTypeface, (outStyle, indentity, outFamilyName)); 1.125 + SkTypefaceCache::Add(face, style); 1.126 +// SkDebugf("add face <%s> <%s> %p [%d]\n", familyName, outFamilyName.c_str(), face, face->getRefCnt()); 1.127 + return face; 1.128 +} 1.129 + 1.130 +#ifdef SK_FONTHOST_DOES_NOT_USE_FONTMGR 1.131 + 1.132 +SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace, 1.133 + const char familyName[], 1.134 + SkTypeface::Style style) { 1.135 + return FontConfigTypeface::LegacyCreateTypeface(familyFace, familyName, 1.136 + style); 1.137 +} 1.138 + 1.139 +SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) { 1.140 + if (!stream) { 1.141 + return NULL; 1.142 + } 1.143 + const size_t length = stream->getLength(); 1.144 + if (!length) { 1.145 + return NULL; 1.146 + } 1.147 + if (length >= 1024 * 1024 * 1024) { 1.148 + return NULL; // don't accept too large fonts (>= 1GB) for safety. 1.149 + } 1.150 + 1.151 + // ask freetype for reported style and if it is a fixed width font 1.152 + SkTypeface::Style style = SkTypeface::kNormal; 1.153 + bool isFixedWidth = false; 1.154 + if (!find_name_and_attributes(stream, NULL, &style, &isFixedWidth)) { 1.155 + return NULL; 1.156 + } 1.157 + 1.158 + SkTypeface* face = SkNEW_ARGS(FontConfigTypeface, (style, isFixedWidth, stream)); 1.159 + return face; 1.160 +} 1.161 + 1.162 +SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) { 1.163 + SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path)); 1.164 + return stream.get() ? CreateTypefaceFromStream(stream) : NULL; 1.165 +} 1.166 + 1.167 +#endif 1.168 + 1.169 +/////////////////////////////////////////////////////////////////////////////// 1.170 + 1.171 +SkStream* FontConfigTypeface::onOpenStream(int* ttcIndex) const { 1.172 + SkStream* stream = this->getLocalStream(); 1.173 + if (stream) { 1.174 + // should have been provided by CreateFromStream() 1.175 + *ttcIndex = 0; 1.176 + 1.177 + SkAutoTUnref<SkStream> dupStream(stream->duplicate()); 1.178 + if (dupStream) { 1.179 + return dupStream.detach(); 1.180 + } 1.181 + 1.182 + // TODO: update interface use, remove the following code in this block. 1.183 + size_t length = stream->getLength(); 1.184 + 1.185 + const void* memory = stream->getMemoryBase(); 1.186 + if (NULL != memory) { 1.187 + return new SkMemoryStream(memory, length, true); 1.188 + } 1.189 + 1.190 + SkAutoTMalloc<uint8_t> allocMemory(length); 1.191 + stream->rewind(); 1.192 + if (length == stream->read(allocMemory.get(), length)) { 1.193 + SkAutoTUnref<SkMemoryStream> copyStream(new SkMemoryStream()); 1.194 + copyStream->setMemoryOwned(allocMemory.detach(), length); 1.195 + return copyStream.detach(); 1.196 + } 1.197 + 1.198 + stream->rewind(); 1.199 + stream->ref(); 1.200 + } else { 1.201 + SkAutoTUnref<SkFontConfigInterface> fci(RefFCI()); 1.202 + if (NULL == fci.get()) { 1.203 + return NULL; 1.204 + } 1.205 + stream = fci->openStream(this->getIdentity()); 1.206 + *ttcIndex = this->getIdentity().fTTCIndex; 1.207 + } 1.208 + return stream; 1.209 +} 1.210 + 1.211 +void FontConfigTypeface::onGetFontDescriptor(SkFontDescriptor* desc, 1.212 + bool* isLocalStream) const { 1.213 + desc->setFamilyName(this->getFamilyName()); 1.214 + *isLocalStream = SkToBool(this->getLocalStream()); 1.215 +}