1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/ports/SkFontHost_linux.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,408 @@ 1.4 +/* 1.5 + * Copyright 2006 The Android Open Source Project 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 "SkFontHost.h" 1.12 +#include "SkFontHost_FreeType_common.h" 1.13 +#include "SkFontDescriptor.h" 1.14 +#include "SkFontMgr.h" 1.15 +#include "SkDescriptor.h" 1.16 +#include "SkOSFile.h" 1.17 +#include "SkPaint.h" 1.18 +#include "SkString.h" 1.19 +#include "SkStream.h" 1.20 +#include "SkThread.h" 1.21 +#include "SkTSearch.h" 1.22 +#include "SkTypefaceCache.h" 1.23 +#include "SkTArray.h" 1.24 + 1.25 +#include <limits> 1.26 + 1.27 +#ifndef SK_FONT_FILE_PREFIX 1.28 +# define SK_FONT_FILE_PREFIX "/usr/share/fonts/truetype/" 1.29 +#endif 1.30 + 1.31 +bool find_name_and_attributes(SkStream* stream, SkString* name, 1.32 + SkTypeface::Style* style, bool* isFixedPitch); 1.33 + 1.34 +/////////////////////////////////////////////////////////////////////////////// 1.35 + 1.36 +/** The base SkTypeface implementation for the custom font manager. */ 1.37 +class SkTypeface_Custom : public SkTypeface_FreeType { 1.38 +public: 1.39 + SkTypeface_Custom(Style style, bool sysFont, bool isFixedPitch, const SkString familyName) 1.40 + : INHERITED(style, SkTypefaceCache::NewFontID(), isFixedPitch) 1.41 + , fIsSysFont(sysFont), fFamilyName(familyName) 1.42 + { } 1.43 + 1.44 + bool isSysFont() const { return fIsSysFont; } 1.45 + 1.46 + virtual const char* getUniqueString() const = 0; 1.47 + 1.48 +protected: 1.49 + virtual void onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const SK_OVERRIDE { 1.50 + desc->setFamilyName(fFamilyName.c_str()); 1.51 + desc->setFontFileName(this->getUniqueString()); 1.52 + *isLocal = !this->isSysFont(); 1.53 + } 1.54 + 1.55 +private: 1.56 + bool fIsSysFont; 1.57 + SkString fFamilyName; 1.58 + 1.59 + typedef SkTypeface_FreeType INHERITED; 1.60 +}; 1.61 + 1.62 +/** The empty SkTypeface implementation for the custom font manager. 1.63 + * Used as the last resort fallback typeface. 1.64 + */ 1.65 +class SkTypeface_Empty : public SkTypeface_Custom { 1.66 +public: 1.67 + SkTypeface_Empty() : INHERITED(SkTypeface::kNormal, true, false, SkString()) {} 1.68 + 1.69 + virtual const char* getUniqueString() const SK_OVERRIDE { return NULL; } 1.70 + 1.71 +protected: 1.72 + virtual SkStream* onOpenStream(int*) const SK_OVERRIDE { return NULL; } 1.73 + 1.74 +private: 1.75 + typedef SkTypeface_Custom INHERITED; 1.76 +}; 1.77 + 1.78 +/** The stream SkTypeface implementation for the custom font manager. */ 1.79 +class SkTypeface_Stream : public SkTypeface_Custom { 1.80 +public: 1.81 + SkTypeface_Stream(Style style, bool sysFont, SkStream* stream, 1.82 + bool isFixedPitch, const SkString familyName) 1.83 + : INHERITED(style, sysFont, isFixedPitch, familyName) 1.84 + , fStream(SkRef(stream)) 1.85 + { } 1.86 + 1.87 + virtual const char* getUniqueString() const SK_OVERRIDE { return NULL; } 1.88 + 1.89 +protected: 1.90 + virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE { 1.91 + *ttcIndex = 0; 1.92 + return SkRef(fStream.get()); 1.93 + } 1.94 + 1.95 +private: 1.96 + SkAutoTUnref<SkStream> fStream; 1.97 + 1.98 + typedef SkTypeface_Custom INHERITED; 1.99 +}; 1.100 + 1.101 +/** The file SkTypeface implementation for the custom font manager. */ 1.102 +class SkTypeface_File : public SkTypeface_Custom { 1.103 +public: 1.104 + SkTypeface_File(Style style, bool sysFont, const char path[], 1.105 + bool isFixedPitch, const SkString familyName) 1.106 + : INHERITED(style, sysFont, isFixedPitch, familyName) 1.107 + , fPath(path) 1.108 + { } 1.109 + 1.110 + virtual const char* getUniqueString() const SK_OVERRIDE { 1.111 + const char* str = strrchr(fPath.c_str(), '/'); 1.112 + if (str) { 1.113 + str += 1; // skip the '/' 1.114 + } 1.115 + return str; 1.116 + } 1.117 + 1.118 +protected: 1.119 + virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE { 1.120 + *ttcIndex = 0; 1.121 + return SkStream::NewFromFile(fPath.c_str()); 1.122 + } 1.123 + 1.124 +private: 1.125 + SkString fPath; 1.126 + 1.127 + typedef SkTypeface_Custom INHERITED; 1.128 +}; 1.129 + 1.130 +/////////////////////////////////////////////////////////////////////////////// 1.131 + 1.132 +/** 1.133 + * SkFontStyleSet_Custom 1.134 + * 1.135 + * This class is used by SkFontMgr_Custom to hold SkTypeface_Custom families. 1.136 + */ 1.137 +class SkFontStyleSet_Custom : public SkFontStyleSet { 1.138 +public: 1.139 + explicit SkFontStyleSet_Custom(const SkString familyName) : fFamilyName(familyName) { } 1.140 + 1.141 + virtual int count() SK_OVERRIDE { 1.142 + return fStyles.count(); 1.143 + } 1.144 + 1.145 + virtual void getStyle(int index, SkFontStyle* style, SkString* name) SK_OVERRIDE { 1.146 + SkASSERT(index < fStyles.count()); 1.147 + bool bold = fStyles[index]->isBold(); 1.148 + bool italic = fStyles[index]->isItalic(); 1.149 + *style = SkFontStyle(bold ? SkFontStyle::kBold_Weight : SkFontStyle::kNormal_Weight, 1.150 + SkFontStyle::kNormal_Width, 1.151 + italic ? SkFontStyle::kItalic_Slant : SkFontStyle::kUpright_Slant); 1.152 + name->reset(); 1.153 + } 1.154 + 1.155 + virtual SkTypeface* createTypeface(int index) SK_OVERRIDE { 1.156 + SkASSERT(index < fStyles.count()); 1.157 + return SkRef(fStyles[index].get()); 1.158 + } 1.159 + 1.160 + static int match_score(const SkFontStyle& pattern, const SkFontStyle& candidate) { 1.161 + int score = 0; 1.162 + score += (pattern.width() - candidate.width()) * 100; 1.163 + score += (pattern.isItalic() == candidate.isItalic()) ? 0 : 1000; 1.164 + score += pattern.weight() - candidate.weight(); 1.165 + return score; 1.166 + } 1.167 + 1.168 + virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE { 1.169 + if (0 == fStyles.count()) { 1.170 + return NULL; 1.171 + } 1.172 + 1.173 + SkTypeface_Custom* closest = fStyles[0]; 1.174 + int minScore = std::numeric_limits<int>::max(); 1.175 + for (int i = 0; i < fStyles.count(); ++i) { 1.176 + bool bold = fStyles[i]->isBold(); 1.177 + bool italic = fStyles[i]->isItalic(); 1.178 + SkFontStyle style = SkFontStyle(bold ? SkFontStyle::kBold_Weight 1.179 + : SkFontStyle::kNormal_Weight, 1.180 + SkFontStyle::kNormal_Width, 1.181 + italic ? SkFontStyle::kItalic_Slant 1.182 + : SkFontStyle::kUpright_Slant); 1.183 + 1.184 + int score = match_score(pattern, style); 1.185 + if (score < minScore) { 1.186 + closest = fStyles[i]; 1.187 + minScore = score; 1.188 + } 1.189 + } 1.190 + return SkRef(closest); 1.191 + } 1.192 + 1.193 +private: 1.194 + SkTArray<SkAutoTUnref<SkTypeface_Custom>, true> fStyles; 1.195 + SkString fFamilyName; 1.196 + 1.197 + void appendTypeface(SkTypeface_Custom* typeface) { 1.198 + fStyles.push_back().reset(typeface); 1.199 + } 1.200 + 1.201 + friend class SkFontMgr_Custom; 1.202 +}; 1.203 + 1.204 +/** 1.205 + * SkFontMgr_Custom 1.206 + * 1.207 + * This class is essentially a collection of SkFontStyleSet_Custom, 1.208 + * one SkFontStyleSet_Custom for each family. This class may be modified 1.209 + * to load fonts from any source by changing the initialization. 1.210 + */ 1.211 +class SkFontMgr_Custom : public SkFontMgr { 1.212 +public: 1.213 + explicit SkFontMgr_Custom(const char* dir) { 1.214 + this->load_system_fonts(dir); 1.215 + } 1.216 + 1.217 +protected: 1.218 + virtual int onCountFamilies() const SK_OVERRIDE { 1.219 + return fFamilies.count(); 1.220 + } 1.221 + 1.222 + virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERRIDE { 1.223 + SkASSERT(index < fFamilies.count()); 1.224 + familyName->set(fFamilies[index]->fFamilyName); 1.225 + } 1.226 + 1.227 + virtual SkFontStyleSet_Custom* onCreateStyleSet(int index) const SK_OVERRIDE { 1.228 + SkASSERT(index < fFamilies.count()); 1.229 + return SkRef(fFamilies[index].get()); 1.230 + } 1.231 + 1.232 + virtual SkFontStyleSet_Custom* onMatchFamily(const char familyName[]) const SK_OVERRIDE { 1.233 + for (int i = 0; i < fFamilies.count(); ++i) { 1.234 + if (fFamilies[i]->fFamilyName.equals(familyName)) { 1.235 + return SkRef(fFamilies[i].get()); 1.236 + } 1.237 + } 1.238 + return NULL; 1.239 + } 1.240 + 1.241 + virtual SkTypeface* onMatchFamilyStyle(const char familyName[], 1.242 + const SkFontStyle& fontStyle) const SK_OVERRIDE 1.243 + { 1.244 + SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName)); 1.245 + return sset->matchStyle(fontStyle); 1.246 + } 1.247 + 1.248 + virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember, 1.249 + const SkFontStyle& fontStyle) const SK_OVERRIDE 1.250 + { 1.251 + for (int i = 0; i < fFamilies.count(); ++i) { 1.252 + for (int j = 0; j < fFamilies[i]->fStyles.count(); ++j) { 1.253 + if (fFamilies[i]->fStyles[j] == familyMember) { 1.254 + return fFamilies[i]->matchStyle(fontStyle); 1.255 + } 1.256 + } 1.257 + } 1.258 + return NULL; 1.259 + } 1.260 + 1.261 + virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const SK_OVERRIDE { 1.262 + SkAutoTUnref<SkStream> stream(new SkMemoryStream(data)); 1.263 + return this->createFromStream(stream, ttcIndex); 1.264 + } 1.265 + 1.266 + virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) const SK_OVERRIDE { 1.267 + if (NULL == stream || stream->getLength() <= 0) { 1.268 + SkDELETE(stream); 1.269 + return NULL; 1.270 + } 1.271 + 1.272 + bool isFixedPitch; 1.273 + SkTypeface::Style style; 1.274 + SkString name; 1.275 + if (find_name_and_attributes(stream, &name, &style, &isFixedPitch)) { 1.276 + return SkNEW_ARGS(SkTypeface_Stream, (style, false, stream, isFixedPitch, name)); 1.277 + } else { 1.278 + return NULL; 1.279 + } 1.280 + } 1.281 + 1.282 + virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE { 1.283 + SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path)); 1.284 + return stream.get() ? this->createFromStream(stream, ttcIndex) : NULL; 1.285 + } 1.286 + 1.287 + virtual SkTypeface* onLegacyCreateTypeface(const char familyName[], 1.288 + unsigned styleBits) const SK_OVERRIDE 1.289 + { 1.290 + SkTypeface::Style oldStyle = (SkTypeface::Style)styleBits; 1.291 + SkFontStyle style = SkFontStyle(oldStyle & SkTypeface::kBold 1.292 + ? SkFontStyle::kBold_Weight 1.293 + : SkFontStyle::kNormal_Weight, 1.294 + SkFontStyle::kNormal_Width, 1.295 + oldStyle & SkTypeface::kItalic 1.296 + ? SkFontStyle::kItalic_Slant 1.297 + : SkFontStyle::kUpright_Slant); 1.298 + SkTypeface* tf = NULL; 1.299 + 1.300 + if (NULL != familyName) { 1.301 + tf = this->onMatchFamilyStyle(familyName, style); 1.302 + } 1.303 + 1.304 + if (NULL == tf) { 1.305 + tf = gDefaultFamily->matchStyle(style); 1.306 + } 1.307 + 1.308 + return SkSafeRef(tf); 1.309 + } 1.310 + 1.311 +private: 1.312 + 1.313 + static bool get_name_and_style(const char path[], SkString* name, 1.314 + SkTypeface::Style* style, bool* isFixedPitch) { 1.315 + SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path)); 1.316 + if (stream.get()) { 1.317 + return find_name_and_attributes(stream, name, style, isFixedPitch); 1.318 + } else { 1.319 + SkDebugf("---- failed to open <%s> as a font\n", path); 1.320 + return false; 1.321 + } 1.322 + } 1.323 + 1.324 + void load_directory_fonts(const SkString& directory) { 1.325 + SkOSFile::Iter iter(directory.c_str(), ".ttf"); 1.326 + SkString name; 1.327 + 1.328 + while (iter.next(&name, false)) { 1.329 + SkString filename( 1.330 + SkOSPath::SkPathJoin(directory.c_str(), name.c_str())); 1.331 + 1.332 + bool isFixedPitch; 1.333 + SkString realname; 1.334 + SkTypeface::Style style = SkTypeface::kNormal; // avoid uninitialized warning 1.335 + 1.336 + if (!get_name_and_style(filename.c_str(), &realname, &style, &isFixedPitch)) { 1.337 + SkDebugf("------ can't load <%s> as a font\n", filename.c_str()); 1.338 + continue; 1.339 + } 1.340 + 1.341 + SkTypeface_Custom* tf = SkNEW_ARGS(SkTypeface_File, ( 1.342 + style, 1.343 + true, // system-font (cannot delete) 1.344 + filename.c_str(), 1.345 + isFixedPitch, 1.346 + realname)); 1.347 + 1.348 + SkFontStyleSet_Custom* addTo = this->onMatchFamily(realname.c_str()); 1.349 + if (NULL == addTo) { 1.350 + addTo = new SkFontStyleSet_Custom(realname); 1.351 + fFamilies.push_back().reset(addTo); 1.352 + } 1.353 + addTo->appendTypeface(tf); 1.354 + } 1.355 + 1.356 + SkOSFile::Iter dirIter(directory.c_str()); 1.357 + while (dirIter.next(&name, true)) { 1.358 + if (name.startsWith(".")) { 1.359 + continue; 1.360 + } 1.361 + SkString dirname( 1.362 + SkOSPath::SkPathJoin(directory.c_str(), name.c_str())); 1.363 + load_directory_fonts(dirname); 1.364 + } 1.365 + } 1.366 + 1.367 + void load_system_fonts(const char* dir) { 1.368 + SkString baseDirectory(dir); 1.369 + load_directory_fonts(baseDirectory); 1.370 + 1.371 + if (fFamilies.empty()) { 1.372 + SkFontStyleSet_Custom* family = new SkFontStyleSet_Custom(SkString()); 1.373 + fFamilies.push_back().reset(family); 1.374 + family->appendTypeface(SkNEW(SkTypeface_Empty)); 1.375 + } 1.376 + 1.377 + // Try to pick a default font. 1.378 + static const char* gDefaultNames[] = { 1.379 + "Arial", "Verdana", "Times New Roman", "Droid Sans", NULL 1.380 + }; 1.381 + for (size_t i = 0; i < SK_ARRAY_COUNT(gDefaultNames); ++i) { 1.382 + SkFontStyleSet_Custom* set = this->onMatchFamily(gDefaultNames[i]); 1.383 + if (NULL == set) { 1.384 + continue; 1.385 + } 1.386 + 1.387 + SkTypeface* tf = set->matchStyle(SkFontStyle(SkFontStyle::kNormal_Weight, 1.388 + SkFontStyle::kNormal_Width, 1.389 + SkFontStyle::kUpright_Slant)); 1.390 + if (NULL == tf) { 1.391 + continue; 1.392 + } 1.393 + 1.394 + gDefaultFamily = set; 1.395 + gDefaultNormal = tf; 1.396 + break; 1.397 + } 1.398 + if (NULL == gDefaultNormal) { 1.399 + gDefaultFamily = fFamilies[0]; 1.400 + gDefaultNormal = gDefaultFamily->fStyles[0]; 1.401 + } 1.402 + } 1.403 + 1.404 + SkTArray<SkAutoTUnref<SkFontStyleSet_Custom>, true> fFamilies; 1.405 + SkFontStyleSet_Custom* gDefaultFamily; 1.406 + SkTypeface* gDefaultNormal; 1.407 +}; 1.408 + 1.409 +SkFontMgr* SkFontMgr::Factory() { 1.410 + return new SkFontMgr_Custom(SK_FONT_FILE_PREFIX); 1.411 +}