1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/utils/ios/SkFontHost_iOS.mm Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,262 @@ 1.4 +#import <UIKit/UIKit.h> 1.5 + 1.6 +#include "SkStream_NSData.h" 1.7 +#include "SkTypeface.h" 1.8 +#include "SkFontHost.h" 1.9 +#include "SkThread.h" 1.10 +#include "SkTemplates.h" 1.11 + 1.12 +enum FontDesign { 1.13 + kUnknown_Design, 1.14 + kSans_FontDesign, 1.15 + kSerif_FontDesign, 1.16 + 1.17 + kIllegal_FontDesign, // never use with a real font 1.18 +}; 1.19 + 1.20 +// returns kIllegal_FontDesign if not found 1.21 +static FontDesign find_design_from_name(const char name[]) { 1.22 + static const struct { 1.23 + const char* fName; 1.24 + FontDesign fDesign; 1.25 + } gRec[] = { 1.26 + { "sans-serif", kSans_FontDesign }, 1.27 + { "serif", kSerif_FontDesign }, 1.28 + }; 1.29 + 1.30 + for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); i++) { 1.31 + if (!strcasecmp(name, gRec[i].fName)) { 1.32 + return gRec[i].fDesign; 1.33 + } 1.34 + } 1.35 + return kIllegal_FontDesign; 1.36 +} 1.37 + 1.38 +struct FontRes { 1.39 + const char* fName; 1.40 + SkTypeface::Style fStyle; 1.41 + FontDesign fDesign; 1.42 +}; 1.43 + 1.44 +static const FontRes gFontRes[] = { 1.45 + { "DroidSans", SkTypeface::kNormal, kSans_FontDesign }, 1.46 + { "DroidSans", SkTypeface::kBold, kSans_FontDesign }, 1.47 + { "DroidSerif-Regular", SkTypeface::kNormal, kSerif_FontDesign }, 1.48 + { "DroidSerif-Bold", SkTypeface::kBold, kSerif_FontDesign }, 1.49 +// { "PescaderoPro", SkTypeface::kNormal, kSerif_FontDesign }, 1.50 +// { "PescaderoPro-Bold", SkTypeface::kBold, kSerif_FontDesign }, 1.51 +}; 1.52 +#define FONTRES_COUNT SK_ARRAY_COUNT(gFontRes) 1.53 + 1.54 +#define DEFAULT_INDEX_REGULAR 1 1.55 +#define DEFAULT_INDEX_BOLD 2 1.56 + 1.57 +/////////////////////////////////////////////////////////////////////////////// 1.58 + 1.59 +class SkTypeface_Stream : public SkTypeface { 1.60 +public: 1.61 + SkTypeface_Stream(SkStream* stream, Style style); 1.62 + virtual ~SkTypeface_Stream(); 1.63 + 1.64 + SkStream* refStream() { 1.65 + fStream->ref(); 1.66 + return fStream; 1.67 + } 1.68 + 1.69 +private: 1.70 + SkStream* fStream; 1.71 +}; 1.72 + 1.73 +static int32_t gUniqueFontID; 1.74 + 1.75 +SkTypeface_Stream::SkTypeface_Stream(SkStream* stream, Style style) 1.76 +: SkTypeface(style, sk_atomic_inc(&gUniqueFontID) + 1) { 1.77 + fStream = stream; 1.78 + fStream->ref(); 1.79 +} 1.80 + 1.81 +SkTypeface_Stream::~SkTypeface_Stream() { 1.82 + fStream->unref(); 1.83 +} 1.84 + 1.85 +static SkTypeface_Stream* create_from_fontres(const FontRes& res) { 1.86 + SkStream* stream = SkStream_NSData::CreateFromResource(res.fName, "ttf"); 1.87 + SkAutoUnref aur(stream); 1.88 + 1.89 + return SkNEW_ARGS(SkTypeface_Stream, (stream, res.fStyle)); 1.90 +} 1.91 + 1.92 +/////////////////////////////////////////////////////////////////////////////// 1.93 + 1.94 +static int compute_style_distance(SkTypeface::Style a, SkTypeface::Style b) { 1.95 + int dist = 0; 1.96 + int diff = a ^ b; 1.97 + if (diff & SkTypeface::kBold) { 1.98 + dist += 2; 1.99 + } 1.100 + if (diff & SkTypeface::kItalic) { 1.101 + dist += 1; 1.102 + } 1.103 + return dist; 1.104 +} 1.105 + 1.106 +static SkTypeface_Stream* gFonts[FONTRES_COUNT]; 1.107 + 1.108 +static void assure_init_fonts() { 1.109 + static bool gOnce; 1.110 + if (!gOnce) { 1.111 + for (size_t i = 0; i < FONTRES_COUNT; i++) { 1.112 + gFonts[i] = create_from_fontres(gFontRes[i]); 1.113 + gOnce = true; 1.114 + } 1.115 + } 1.116 +} 1.117 + 1.118 +static SkTypeface_Stream* get_default_font(SkTypeface::Style style) { 1.119 + assure_init_fonts(); 1.120 + 1.121 + if (style & SkTypeface::kBold) { 1.122 + return gFonts[DEFAULT_INDEX_BOLD]; 1.123 + } else { 1.124 + return gFonts[DEFAULT_INDEX_REGULAR]; 1.125 + } 1.126 +} 1.127 + 1.128 +static SkTypeface_Stream* find_by_id(SkFontID fontID) { 1.129 + assure_init_fonts(); 1.130 + 1.131 + for (size_t i = 0; i < FONTRES_COUNT; i++) { 1.132 + if (gFonts[i]->uniqueID() == fontID) { 1.133 + return gFonts[i]; 1.134 + } 1.135 + } 1.136 + return NULL; 1.137 +} 1.138 + 1.139 +/////////////////////////////////////////////////////////////////////////////// 1.140 + 1.141 +template <typename T> T* ref_and_return(T* obj) { 1.142 + obj->ref(); 1.143 + return obj; 1.144 +} 1.145 + 1.146 +SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace, 1.147 + const char familyName[], 1.148 + const void* data, size_t bytelength, 1.149 + SkTypeface::Style style) { 1.150 + assure_init_fonts(); 1.151 + 1.152 + if (familyName) { 1.153 + FontDesign design = find_design_from_name(familyName); 1.154 + if (kIllegal_FontDesign != design) { 1.155 + familyName = "$#@*&%*#$@ never match any name"; 1.156 + } 1.157 + 1.158 + int bestDistance = 999; 1.159 + int bestIndex = -1; 1.160 + for (size_t i = 0; i < FONTRES_COUNT; i++) { 1.161 + if (design == gFontRes[i].fDesign || !strcmp(gFontRes[i].fName, familyName)) { 1.162 + int dist = compute_style_distance(style, gFontRes[i].fStyle); 1.163 + if (dist < bestDistance) { 1.164 + bestDistance = dist; 1.165 + bestIndex = i; 1.166 + } 1.167 + } 1.168 + } 1.169 + if (bestIndex >= 0) { 1.170 + return ref_and_return(gFonts[bestIndex]); 1.171 + } 1.172 + } 1.173 + 1.174 + return ref_and_return(get_default_font(style)); 1.175 +} 1.176 + 1.177 +SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) { 1.178 + SkDEBUGFAIL("SkFontHost::CreateTypeface unimplemented"); 1.179 + return NULL; 1.180 +} 1.181 + 1.182 +SkTypeface* SkFontHost::CreateTypefaceFromFile(char const*) { 1.183 +// SkDEBUGFAIL("SkFontHost::CreateTypefaceFromFile unimplemented"); 1.184 + return NULL; 1.185 +} 1.186 + 1.187 +/////////////////////////////////////////////////////////////////////////////// 1.188 + 1.189 +SkStream* SkFontHost::OpenStream(uint32_t uniqueID) { 1.190 + SkTypeface_Stream* tf = find_by_id(uniqueID); 1.191 + SkASSERT(tf); 1.192 + return tf->refStream(); 1.193 +} 1.194 + 1.195 +size_t SkFontHost::GetFileName(SkFontID fontID, char path[], size_t length, 1.196 + int32_t* index) { 1.197 + SkDebugf("SkFontHost::GetFileName unimplemented\n"); 1.198 + return 0; 1.199 +} 1.200 + 1.201 +/////////////////////////////////////////////////////////////////////////////// 1.202 + 1.203 +void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) { 1.204 + SkDEBUGFAIL("SkFontHost::Serialize unimplemented"); 1.205 +} 1.206 + 1.207 +SkTypeface* SkFontHost::Deserialize(SkStream* stream) { 1.208 + int style = stream->readU8(); 1.209 + int len = stream->readPackedUInt(); 1.210 + const char* name = NULL; 1.211 + if (len > 0) { 1.212 + SkString str; 1.213 + str.resize(len); 1.214 + stream->read(str.writable_str(), len); 1.215 + 1.216 + if (str.startsWith("DroidSans")) { 1.217 + name = "sans-serif"; 1.218 + } else if (str.startsWith("DroidSerif")) { 1.219 + name = "serif"; 1.220 + } 1.221 + SkDebugf("---- deserialize typeface <%s> %d %s\n", str.c_str(), style, name); 1.222 + } 1.223 +// name = NULL; style = 0; 1.224 + return SkFontHost::CreateTypeface(NULL, name, NULL, NULL, 1.225 + (SkTypeface::Style)style); 1.226 +} 1.227 + 1.228 +SkFontID SkFontHost::NextLogicalFont(SkFontID currFontID, SkFontID origFontID) { 1.229 + return 0; 1.230 +} 1.231 + 1.232 +#define FONT_CACHE_MEMORY_BUDGET 1 * 1024 * 1024 1.233 + 1.234 +size_t SkFontHost::ShouldPurgeFontCache(size_t sizeAllocatedSoFar) { 1.235 + if (sizeAllocatedSoFar > FONT_CACHE_MEMORY_BUDGET) 1.236 + return sizeAllocatedSoFar - FONT_CACHE_MEMORY_BUDGET; 1.237 + else 1.238 + return 0; // nothing to do 1.239 +} 1.240 + 1.241 +/////////////////////////////////////////////////////////////////////////////// 1.242 +int SkFontHost::ComputeGammaFlag(const SkPaint& paint) { 1.243 + return 0; 1.244 +} 1.245 + 1.246 +void SkFontHost::GetGammaTables(const uint8_t* tables[2]) { 1.247 + tables[0] = NULL; // black gamma (e.g. exp=1.4) 1.248 + tables[1] = NULL; // white gamma (e.g. exp= 1/1.4) 1.249 +} 1.250 + 1.251 +// static 1.252 +SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics( 1.253 + uint32_t fontID, 1.254 + SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) { 1.255 + SkDEBUGFAIL("SkFontHost::GetAdvancedTypefaceMetrics unimplemented"); 1.256 + return NULL; 1.257 +} 1.258 + 1.259 +void SkFontHost::FilterRec(SkScalerContext::Rec* rec, SkTypeface*) { 1.260 +} 1.261 + 1.262 +SkScalerContext* SkFontHost::CreateScalerContext(const SkDescriptor* desc) { 1.263 + SkDEBUGFAIL("SkFontHost::CreateScalarContext unimplemented"); 1.264 + return NULL; 1.265 +} 1.266 \ No newline at end of file