diff --git a/include/core/SkTypeface.h b/include/core/SkTypeface.h index 7fb6b810d0..79b821f99b 100644 --- a/include/core/SkTypeface.h +++ b/include/core/SkTypeface.h @@ -13,6 +13,10 @@ #include "SkAdvancedTypefaceMetrics.h" #include "SkWeakRefCnt.h" +class SkDescriptor; +class SkFontDescriptor; +class SkScalerContext; +struct SkScalerContextRec; class SkStream; class SkAdvancedTypefaceMetrics; class SkWStream; @@ -184,7 +188,7 @@ public: int getUnitsPerEm() const; protected: - /** uniqueID must be unique (please!) and non-zero + /** uniqueID must be unique and non-zero */ SkTypeface(Style style, SkFontID uniqueID, bool isFixedWidth = false); virtual ~SkTypeface(); @@ -192,11 +196,22 @@ protected: friend class SkScalerContext; static SkTypeface* GetDefaultTypeface(); + virtual int onGetUPEM() const; + virtual int onGetTableTags(SkFontTableTag tags[]) const; + virtual size_t onGetTableData(SkFontTableTag, size_t offset, + size_t length, void* data) const; + virtual SkScalerContext* onCreateScalerContext(const SkDescriptor*) const; + virtual void onFilterRec(SkScalerContextRec*) const; + virtual void onGetFontDescriptor(SkFontDescriptor*) const; + private: SkFontID fUniqueID; Style fStyle; bool fIsFixedWidth; + // just so deprecated fonthost can call protected methods + friend class SkFontHost; + typedef SkWeakRefCnt INHERITED; }; diff --git a/src/core/SkTypeface.cpp b/src/core/SkTypeface.cpp index c30e5a9f6d..e7004502bd 100644 --- a/src/core/SkTypeface.cpp +++ b/src/core/SkTypeface.cpp @@ -134,3 +134,21 @@ int SkTypeface::getUnitsPerEm() const { #endif return upem; } + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +#include "SkFontDescriptor.h" + +int SkTypeface::onGetUPEM() const { return 0; } +int SkTypeface::onGetTableTags(SkFontTableTag tags[]) const { return 0; } +size_t SkTypeface::onGetTableData(SkFontTableTag, size_t offset, + size_t length, void* data) const { return 0; } +SkScalerContext* SkTypeface::onCreateScalerContext(const SkDescriptor*) const { + return NULL; +} +void SkTypeface::onFilterRec(SkScalerContextRec*) const {} +void SkTypeface::onGetFontDescriptor(SkFontDescriptor* desc) const { + desc->setStyle(this->style()); +} + diff --git a/src/ports/SkFontHost_mac_coretext.cpp b/src/ports/SkFontHost_mac_coretext.cpp index ceb9a040c8..74ff3e165e 100644 --- a/src/ports/SkFontHost_mac_coretext.cpp +++ b/src/ports/SkFontHost_mac_coretext.cpp @@ -407,12 +407,21 @@ public: SkString fName; AutoCFRelease fFontRef; -}; -static CTFontRef typeface_to_fontref(const SkTypeface* face) { - const SkTypeface_Mac* macface = reinterpret_cast(face); - return macface->fFontRef; -} +protected: + friend class SkFontHost; // to access our protected members for deprecated methods + + virtual int onGetUPEM() const SK_OVERRIDE; + virtual int onGetTableTags(SkFontTableTag tags[]) const SK_OVERRIDE; + virtual size_t onGetTableData(SkFontTableTag, size_t offset, + size_t length, void* data) const SK_OVERRIDE; + virtual SkScalerContext* onCreateScalerContext(const SkDescriptor*) const SK_OVERRIDE; + virtual void onFilterRec(SkScalerContextRec*) const SK_OVERRIDE; + virtual void onGetFontDescriptor(SkFontDescriptor*) const SK_OVERRIDE; + +private: + typedef SkTypeface INHERITED; +}; static SkTypeface* NewFromFontRef(CTFontRef fontRef, const char name[]) { SkASSERT(fontRef); @@ -1683,21 +1692,9 @@ size_t SkFontHost::GetFileName(SkFontID fontID, char path[], size_t length, int3 #include "SkStream.h" -// we take ownership of the ref -static const char* get_str(CFStringRef ref, SkString* str) { - CFStringToSkString(ref, str); - CFSafeRelease(ref); - return str->c_str(); -} - void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) { - CTFontRef ctFont = typeface_to_fontref(face); - SkFontDescriptor desc(face->style()); - SkString tmpStr; - - desc.setFamilyName(get_str(CTFontCopyFamilyName(ctFont), &tmpStr)); - desc.setFullName(get_str(CTFontCopyFullName(ctFont), &tmpStr)); - desc.setPostscriptName(get_str(CTFontCopyPostScriptName(ctFont), &tmpStr)); + SkFontDescriptor desc; + face->onGetFontDescriptor(&desc); desc.serialize(stream); @@ -1719,10 +1716,12 @@ SkTypeface* SkFontHost::Deserialize(SkStream* stream) { /////////////////////////////////////////////////////////////////////////////// +// DEPRECATED SkScalerContext* SkFontHost::CreateScalerContext(const SkDescriptor* desc) { return new SkScalerContext_Mac(desc); } +// DEPRECATED SkFontID SkFontHost::NextLogicalFont(SkFontID currFontID, SkFontID origFontID) { SkFontID nextFontID = 0; SkTypeface* face = GetDefaultFace(); @@ -1732,14 +1731,105 @@ SkFontID SkFontHost::NextLogicalFont(SkFontID currFontID, SkFontID origFontID) { return nextFontID; } -void SkFontHost::FilterRec(SkScalerContext::Rec* rec, SkTypeface*) { +// DEPRECATED +void SkFontHost::FilterRec(SkScalerContext::Rec* rec, SkTypeface* face) { + face->onFilterRec(rec); +} + +// DEPRECATED +int SkFontHost::CountTables(SkFontID fontID) { + SkTypeface* face = SkTypefaceCache::FindByID(fontID); + return face ? face->onGetTableTags(NULL) : 0; +} + +// DEPRECATED +int SkFontHost::GetTableTags(SkFontID fontID, SkFontTableTag tags[]) { + SkTypeface* face = SkTypefaceCache::FindByID(fontID); + return face ? face->onGetTableTags(tags) : 0; +} + +// DEPRECATED +size_t SkFontHost::GetTableSize(SkFontID fontID, SkFontTableTag tag) { + SkTypeface* face = SkTypefaceCache::FindByID(fontID); + return face ? face->onGetTableData(tag, 0, 0, NULL) : 0; +} + +// DEPRECATED +size_t SkFontHost::GetTableData(SkFontID fontID, SkFontTableTag tag, + size_t offset, size_t length, void* dst) { + SkTypeface* face = SkTypefaceCache::FindByID(fontID); + return face ? face->onGetTableData(tag, offset, length, dst) : 0; +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +int SkTypeface_Mac::onGetUPEM() const { + AutoCFRelease cgFont(CTFontCopyGraphicsFont(fFontRef, NULL)); + return CGFontGetUnitsPerEm(cgFont); +} + +// If, as is the case with web fonts, the CTFont data isn't available, +// the CGFont data may work. While the CGFont may always provide the +// right result, leave the CTFont code path to minimize disruption. +static CFDataRef copyTableFromFont(CTFontRef ctFont, SkFontTableTag tag) { + CFDataRef data = CTFontCopyTable(ctFont, (CTFontTableTag) tag, + kCTFontTableOptionNoOptions); + if (NULL == data) { + AutoCFRelease cgFont(CTFontCopyGraphicsFont(ctFont, NULL)); + data = CGFontCopyTableForTag(cgFont, tag); + } + return data; +} + +int SkTypeface_Mac::onGetTableTags(SkFontTableTag tags[]) const { + AutoCFRelease cfArray(CTFontCopyAvailableTables(fFontRef, + kCTFontTableOptionNoOptions)); + if (NULL == cfArray) { + return 0; + } + int count = CFArrayGetCount(cfArray); + if (tags) { + for (int i = 0; i < count; ++i) { + uintptr_t fontTag = reinterpret_cast(CFArrayGetValueAtIndex(cfArray, i)); + tags[i] = static_cast(fontTag); + } + } + return count; +} + +size_t SkTypeface_Mac::onGetTableData(SkFontTableTag tag, size_t offset, + size_t length, void* dstData) const { + AutoCFRelease srcData(copyTableFromFont(fFontRef, tag)); + if (NULL == srcData) { + return 0; + } + + size_t srcSize = CFDataGetLength(srcData); + if (offset >= srcSize) { + return 0; + } + if (length > srcSize - offset) { + length = srcSize - offset; + } + if (dstData) { + memcpy(dstData, CFDataGetBytePtr(srcData) + offset, length); + } + return length; +} + +SkScalerContext* SkTypeface_Mac::onCreateScalerContext(const SkDescriptor* desc) const { + return new SkScalerContext_Mac(desc); +} + +void SkTypeface_Mac::onFilterRec(SkScalerContextRec* rec) const { unsigned flagsWeDontSupport = SkScalerContext::kDevKernText_Flag | SkScalerContext::kAutohinting_Flag; - + rec->fFlags &= ~flagsWeDontSupport; - + bool lcdSupport = supports_LCD(); - + // Only two levels of hinting are supported. // kNo_Hinting means avoid CoreGraphics outline dilation. // kNormal_Hinting means CoreGraphics outline dilation is allowed. @@ -1751,18 +1841,18 @@ void SkFontHost::FilterRec(SkScalerContext::Rec* rec, SkTypeface*) { hinting = SkPaint::kNormal_Hinting; } rec->setHinting(hinting); - + // FIXME: lcd smoothed un-hinted rasterization unsupported. // Tracked by http://code.google.com/p/skia/issues/detail?id=915 . // There is no current means to honor a request for unhinted lcd, // so arbitrarilly ignore the hinting request and honor lcd. - + // Hinting and smoothing should be orthogonal, but currently they are not. // CoreGraphics has no API to influence hinting. However, its lcd smoothed // output is drawn from auto-dilated outlines (the amount of which is // determined by AppleFontSmoothing). Its regular anti-aliased output is // drawn from un-dilated outlines. - + // The behavior of Skia is as follows: // [AA][no-hint]: generate AA using CoreGraphic's AA output. // [AA][yes-hint]: use CoreGraphic's LCD output and reduce it to a single @@ -1770,7 +1860,7 @@ void SkFontHost::FilterRec(SkScalerContext::Rec* rec, SkTypeface*) { // [LCD][no-hint]: curently unable to honor, and must pick which to respect. // Currenly side with LCD, effectively ignoring the hinting setting. // [LCD][yes-hint]: generate LCD using CoreGraphic's LCD output. - + if (isLCDFormat(rec->fMaskFormat)) { if (lcdSupport) { //CoreGraphics creates 555 masks for smoothed text anyway. @@ -1780,7 +1870,7 @@ void SkFontHost::FilterRec(SkScalerContext::Rec* rec, SkTypeface*) { rec->fMaskFormat = SkMask::kA8_Format; } } - + // Unhinted A8 masks (those not derived from LCD masks) must respect SK_GAMMA_APPLY_TO_A8. // All other masks can use regular gamma. if (SkMask::kA8_Format == rec->fMaskFormat && SkPaint::kNo_Hinting == hinting) { @@ -1793,76 +1883,19 @@ void SkFontHost::FilterRec(SkScalerContext::Rec* rec, SkTypeface*) { } } -/////////////////////////////////////////////////////////////////////////// - -int SkFontHost::CountTables(SkFontID fontID) { - CTFontRef ctFont = GetFontRefFromFontID(fontID); - AutoCFRelease cfArray(CTFontCopyAvailableTables(ctFont, - kCTFontTableOptionNoOptions)); - if (NULL == cfArray) { - return 0; - } - return CFArrayGetCount(cfArray); +// we take ownership of the ref +static const char* get_str(CFStringRef ref, SkString* str) { + CFStringToSkString(ref, str); + CFSafeRelease(ref); + return str->c_str(); } -int SkFontHost::GetTableTags(SkFontID fontID, SkFontTableTag tags[]) { - CTFontRef ctFont = GetFontRefFromFontID(fontID); - AutoCFRelease cfArray(CTFontCopyAvailableTables(ctFont, - kCTFontTableOptionNoOptions)); - if (NULL == cfArray) { - return 0; - } - - int count = CFArrayGetCount(cfArray); - if (tags) { - for (int i = 0; i < count; ++i) { - uintptr_t fontTag = reinterpret_cast(CFArrayGetValueAtIndex(cfArray, i)); - tags[i] = static_cast(fontTag); - } - } - return count; +void SkTypeface_Mac::onGetFontDescriptor(SkFontDescriptor* desc) const { + this->INHERITED::onGetFontDescriptor(desc); + SkString tmpStr; + + desc->setFamilyName(get_str(CTFontCopyFamilyName(fFontRef), &tmpStr)); + desc->setFullName(get_str(CTFontCopyFullName(fFontRef), &tmpStr)); + desc->setPostscriptName(get_str(CTFontCopyPostScriptName(fFontRef), &tmpStr)); } -// If, as is the case with web fonts, the CTFont data isn't available, -// the CGFont data may work. While the CGFont may always provide the -// right result, leave the CTFont code path to minimize disruption. -static CFDataRef copyTableFromFont(CTFontRef ctFont, SkFontTableTag tag) { - CFDataRef data = CTFontCopyTable(ctFont, (CTFontTableTag) tag, kCTFontTableOptionNoOptions); - if (NULL == data) { - AutoCFRelease cgFont(CTFontCopyGraphicsFont(ctFont, NULL)); - data = CGFontCopyTableForTag(cgFont, tag); - } - return data; -} - -size_t SkFontHost::GetTableSize(SkFontID fontID, SkFontTableTag tag) { - CTFontRef ctFont = GetFontRefFromFontID(fontID); - AutoCFRelease srcData(copyTableFromFont(ctFont, tag)); - if (NULL == srcData) { - return 0; - } - return CFDataGetLength(srcData); -} - -size_t SkFontHost::GetTableData(SkFontID fontID, SkFontTableTag tag, - size_t offset, size_t length, void* dst) { - CTFontRef ctFont = GetFontRefFromFontID(fontID); - AutoCFRelease srcData(copyTableFromFont(ctFont, tag)); - if (NULL == srcData) { - return 0; - } - - size_t srcSize = CFDataGetLength(srcData); - if (offset >= srcSize) { - return 0; - } - - if ((offset + length) > srcSize) { - length = srcSize - offset; - } - - if (dst) { - memcpy(dst, CFDataGetBytePtr(srcData) + offset, length); - } - return length; -}