diff -r 000000000000 -r 6474c204b198 gfx/skia/trunk/src/utils/ios/SkFontHost_iOS.mm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gfx/skia/trunk/src/utils/ios/SkFontHost_iOS.mm Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,262 @@ +#import + +#include "SkStream_NSData.h" +#include "SkTypeface.h" +#include "SkFontHost.h" +#include "SkThread.h" +#include "SkTemplates.h" + +enum FontDesign { + kUnknown_Design, + kSans_FontDesign, + kSerif_FontDesign, + + kIllegal_FontDesign, // never use with a real font +}; + +// returns kIllegal_FontDesign if not found +static FontDesign find_design_from_name(const char name[]) { + static const struct { + const char* fName; + FontDesign fDesign; + } gRec[] = { + { "sans-serif", kSans_FontDesign }, + { "serif", kSerif_FontDesign }, + }; + + for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); i++) { + if (!strcasecmp(name, gRec[i].fName)) { + return gRec[i].fDesign; + } + } + return kIllegal_FontDesign; +} + +struct FontRes { + const char* fName; + SkTypeface::Style fStyle; + FontDesign fDesign; +}; + +static const FontRes gFontRes[] = { + { "DroidSans", SkTypeface::kNormal, kSans_FontDesign }, + { "DroidSans", SkTypeface::kBold, kSans_FontDesign }, + { "DroidSerif-Regular", SkTypeface::kNormal, kSerif_FontDesign }, + { "DroidSerif-Bold", SkTypeface::kBold, kSerif_FontDesign }, +// { "PescaderoPro", SkTypeface::kNormal, kSerif_FontDesign }, +// { "PescaderoPro-Bold", SkTypeface::kBold, kSerif_FontDesign }, +}; +#define FONTRES_COUNT SK_ARRAY_COUNT(gFontRes) + +#define DEFAULT_INDEX_REGULAR 1 +#define DEFAULT_INDEX_BOLD 2 + +/////////////////////////////////////////////////////////////////////////////// + +class SkTypeface_Stream : public SkTypeface { +public: + SkTypeface_Stream(SkStream* stream, Style style); + virtual ~SkTypeface_Stream(); + + SkStream* refStream() { + fStream->ref(); + return fStream; + } + +private: + SkStream* fStream; +}; + +static int32_t gUniqueFontID; + +SkTypeface_Stream::SkTypeface_Stream(SkStream* stream, Style style) +: SkTypeface(style, sk_atomic_inc(&gUniqueFontID) + 1) { + fStream = stream; + fStream->ref(); +} + +SkTypeface_Stream::~SkTypeface_Stream() { + fStream->unref(); +} + +static SkTypeface_Stream* create_from_fontres(const FontRes& res) { + SkStream* stream = SkStream_NSData::CreateFromResource(res.fName, "ttf"); + SkAutoUnref aur(stream); + + return SkNEW_ARGS(SkTypeface_Stream, (stream, res.fStyle)); +} + +/////////////////////////////////////////////////////////////////////////////// + +static int compute_style_distance(SkTypeface::Style a, SkTypeface::Style b) { + int dist = 0; + int diff = a ^ b; + if (diff & SkTypeface::kBold) { + dist += 2; + } + if (diff & SkTypeface::kItalic) { + dist += 1; + } + return dist; +} + +static SkTypeface_Stream* gFonts[FONTRES_COUNT]; + +static void assure_init_fonts() { + static bool gOnce; + if (!gOnce) { + for (size_t i = 0; i < FONTRES_COUNT; i++) { + gFonts[i] = create_from_fontres(gFontRes[i]); + gOnce = true; + } + } +} + +static SkTypeface_Stream* get_default_font(SkTypeface::Style style) { + assure_init_fonts(); + + if (style & SkTypeface::kBold) { + return gFonts[DEFAULT_INDEX_BOLD]; + } else { + return gFonts[DEFAULT_INDEX_REGULAR]; + } +} + +static SkTypeface_Stream* find_by_id(SkFontID fontID) { + assure_init_fonts(); + + for (size_t i = 0; i < FONTRES_COUNT; i++) { + if (gFonts[i]->uniqueID() == fontID) { + return gFonts[i]; + } + } + return NULL; +} + +/////////////////////////////////////////////////////////////////////////////// + +template T* ref_and_return(T* obj) { + obj->ref(); + return obj; +} + +SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace, + const char familyName[], + const void* data, size_t bytelength, + SkTypeface::Style style) { + assure_init_fonts(); + + if (familyName) { + FontDesign design = find_design_from_name(familyName); + if (kIllegal_FontDesign != design) { + familyName = "$#@*&%*#$@ never match any name"; + } + + int bestDistance = 999; + int bestIndex = -1; + for (size_t i = 0; i < FONTRES_COUNT; i++) { + if (design == gFontRes[i].fDesign || !strcmp(gFontRes[i].fName, familyName)) { + int dist = compute_style_distance(style, gFontRes[i].fStyle); + if (dist < bestDistance) { + bestDistance = dist; + bestIndex = i; + } + } + } + if (bestIndex >= 0) { + return ref_and_return(gFonts[bestIndex]); + } + } + + return ref_and_return(get_default_font(style)); +} + +SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) { + SkDEBUGFAIL("SkFontHost::CreateTypeface unimplemented"); + return NULL; +} + +SkTypeface* SkFontHost::CreateTypefaceFromFile(char const*) { +// SkDEBUGFAIL("SkFontHost::CreateTypefaceFromFile unimplemented"); + return NULL; +} + +/////////////////////////////////////////////////////////////////////////////// + +SkStream* SkFontHost::OpenStream(uint32_t uniqueID) { + SkTypeface_Stream* tf = find_by_id(uniqueID); + SkASSERT(tf); + return tf->refStream(); +} + +size_t SkFontHost::GetFileName(SkFontID fontID, char path[], size_t length, + int32_t* index) { + SkDebugf("SkFontHost::GetFileName unimplemented\n"); + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// + +void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) { + SkDEBUGFAIL("SkFontHost::Serialize unimplemented"); +} + +SkTypeface* SkFontHost::Deserialize(SkStream* stream) { + int style = stream->readU8(); + int len = stream->readPackedUInt(); + const char* name = NULL; + if (len > 0) { + SkString str; + str.resize(len); + stream->read(str.writable_str(), len); + + if (str.startsWith("DroidSans")) { + name = "sans-serif"; + } else if (str.startsWith("DroidSerif")) { + name = "serif"; + } + SkDebugf("---- deserialize typeface <%s> %d %s\n", str.c_str(), style, name); + } +// name = NULL; style = 0; + return SkFontHost::CreateTypeface(NULL, name, NULL, NULL, + (SkTypeface::Style)style); +} + +SkFontID SkFontHost::NextLogicalFont(SkFontID currFontID, SkFontID origFontID) { + return 0; +} + +#define FONT_CACHE_MEMORY_BUDGET 1 * 1024 * 1024 + +size_t SkFontHost::ShouldPurgeFontCache(size_t sizeAllocatedSoFar) { + if (sizeAllocatedSoFar > FONT_CACHE_MEMORY_BUDGET) + return sizeAllocatedSoFar - FONT_CACHE_MEMORY_BUDGET; + else + return 0; // nothing to do +} + +/////////////////////////////////////////////////////////////////////////////// +int SkFontHost::ComputeGammaFlag(const SkPaint& paint) { + return 0; +} + +void SkFontHost::GetGammaTables(const uint8_t* tables[2]) { + tables[0] = NULL; // black gamma (e.g. exp=1.4) + tables[1] = NULL; // white gamma (e.g. exp= 1/1.4) +} + +// static +SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics( + uint32_t fontID, + SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) { + SkDEBUGFAIL("SkFontHost::GetAdvancedTypefaceMetrics unimplemented"); + return NULL; +} + +void SkFontHost::FilterRec(SkScalerContext::Rec* rec, SkTypeface*) { +} + +SkScalerContext* SkFontHost::CreateScalerContext(const SkDescriptor* desc) { + SkDEBUGFAIL("SkFontHost::CreateScalarContext unimplemented"); + return NULL; +} \ No newline at end of file