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