aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/ports/SkFontHost_mac.cpp
diff options
context:
space:
mode:
authorGravatar reed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2009-03-09 15:25:11 +0000
committerGravatar reed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2009-03-09 15:25:11 +0000
commitea446b9bc594f9ca1cb894d5c3fa05358bfebba3 (patch)
tree1690d234f4719abf4b7788659e0688527748eb03 /src/ports/SkFontHost_mac.cpp
parent60dfdbc1aef8d8df1c35a1b8ef0ce0a81a20a8b7 (diff)
check-point (2) on mac fonts
- simplify typeface factories git-svn-id: http://skia.googlecode.com/svn/trunk@115 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/ports/SkFontHost_mac.cpp')
-rwxr-xr-xsrc/ports/SkFontHost_mac.cpp329
1 files changed, 51 insertions, 278 deletions
diff --git a/src/ports/SkFontHost_mac.cpp b/src/ports/SkFontHost_mac.cpp
index 15a987ebdb..0f509f1e22 100755
--- a/src/ports/SkFontHost_mac.cpp
+++ b/src/ports/SkFontHost_mac.cpp
@@ -34,217 +34,46 @@ static inline uint32_t _rotl(uint32_t v, uint32_t r) {
return (v << r | v >> (32 - r));
}
-// This will generate a unique ID based on the fontname + fontstyle
-// and also used by upper layer
-uint32_t FontFaceChecksum(const char *name,SkTypeface::Style style)
-{
- if (!name) return style;
-
- char* q = (char*)name;
-
- // From "Performance in Practice of String Hashing Functions"
- // Ramakrishna & Zobel
- const uint32_t L = 5;
- const uint32_t R = 2;
-
- uint32_t h = 0x12345678;
- while (*q) {
- uint32_t ql = tolower(*q);
- h ^= ((h << L) + (h >> R) + ql);
- q ++;
- }
-
- // add style
- h = _rotl(h, 3) ^ style;
-
- return h;
-}
-
-#pragma mark -
-struct SkFaceRec {
- SkFaceRec* fNext;
- uint32_t fRefCnt;
- ATSUFontID fFontID;
- ATSUStyle fStyle;
-
- SkFaceRec() : fFontID(0), fRefCnt(0), fStyle(NULL) {};
-
- ~SkFaceRec() {
- if (fStyle) {
- ::ATSUDisposeStyle(fStyle);
- fStyle = NULL;
- }
- }
-
- uint32_t ref() {
- return ++fRefCnt;
- }
-};
-
-// Font Face list
-static SkFaceRec* gFaceRecHead = NULL;
-
-static SkFaceRec* find_ft_face(const ATSUFontID fontID) {
- SkFaceRec* rec = gFaceRecHead;
- while (rec) {
- if (rec->fFontID == fontID) {
- return rec;
- }
- rec = rec->fNext;
- }
-
- return NULL;
-}
-
-static SkFaceRec* insert_ft_face(const ATSUFontID afontID, const ATSUStyle atsuStyle) {
- SkFaceRec* rec = find_ft_face(afontID);
- if (rec) {
- return rec; // found?
- }
-
- rec = SkNEW(SkFaceRec);
- rec->fFontID = afontID;
- rec->fStyle = atsuStyle;
- rec->fNext = gFaceRecHead;
- gFaceRecHead = rec;
-
- return rec;
-}
-
-static void unref_ft_face(const ATSUFontID fontID) {
-
- SkFaceRec* rec = gFaceRecHead;
- SkFaceRec* prev = NULL;
- while (rec) {
- SkFaceRec* next = rec->fNext;
- if (rec->fFontID == fontID) {
- if (--rec->fRefCnt == 0) {
- if (prev)
- prev->fNext = next;
- else
- gFaceRecHead = next;
-
- SkDELETE(rec);
- }
- return;
- }
- prev = rec;
- rec = next;
- }
- SkASSERT("shouldn't get here, face not in list");
-}
-
-#pragma mark -
-
-// have to do this because SkTypeface::SkTypeface() is protected
class SkTypeface_Mac : public SkTypeface {
public:
- SkTypeface_Mac(SkTypeface::Style style, uint32_t id) : SkTypeface(style, id) {}
-
- ~SkTypeface_Mac() {}
+ SkTypeface_Mac(SkTypeface::Style style, uint32_t id)
+ : SkTypeface(style, id) {}
};
#pragma mark -
-static SkTypeface* CreateTypeface_(const char *name, const SkTypeface::Style style) {
-
- OSStatus err;
- ATSUStyle atsuStyle;
- ::ATSUCreateStyle(&atsuStyle);
- if (name != NULL) {
- static const ATSUAttributeTag fontTag = kATSUFontTag;
- static const ByteCount fontTagSize = sizeof(ATSUFontID);
-
- ATSUFontID fontID = 0;
-#if 1
- err = ::ATSUFindFontFromName(
- name,strlen(name),kFontNoNameCode, /* instead of regular, kFontFamilyName returns bold and/or italic sometimes, but why this works?? */
- kFontMacintoshPlatform,kFontNoScriptCode,kFontNoLanguageCode,&fontID);
-#else
- CFStringRef cfontName = CFStringCreateWithCString(NULL, name, kCFStringEncodingASCII);
- ATSFontRef fontRef = ::ATSFontFindFromName(cfontName,kATSOptionFlagsDefault);
- fontID = ::FMGetFontFromATSFontRef(fontRef);
- CFRelease(cfontName);
-#endif
- if (0 != fontID) {
- const ATSUAttributeValuePtr values[] = { &fontID };
- err = ::ATSUSetAttributes(atsuStyle,1,&fontTag,&fontTagSize,values);
- }
- else {
- }
- }
- if (style != SkTypeface::kNormal) {
- Boolean fontItalic = ((style & SkTypeface::kItalic) != 0);
- Boolean fontBold = ((style & SkTypeface::kBold) != 0);
- const ATSUAttributeTag tags[2] = { kATSUQDBoldfaceTag, kATSUQDItalicTag };
- const ATSUAttributeValuePtr values[2] = { &fontBold, &fontItalic };
- const ByteCount sizes[2] = { sizeof(Boolean), sizeof(Boolean) };
- err = ::ATSUSetAttributes(atsuStyle,2,tags,sizes,values);
- }
-
- uint32_t cs = FontFaceChecksum(name,style);
- SkTypeface_Mac* ptypeface = new SkTypeface_Mac(style,cs);
-
- if (NULL == ptypeface) {
- SkASSERT(false);
- return NULL;
- }
-
- SkFaceRec* rec = insert_ft_face(cs, atsuStyle);
- SkASSERT(rec);
-
- return ptypeface;
+static uint32_t find_from_name(const char name[]) {
+ CFStringRef str = CFStringCreateWithCString(NULL, name,
+ kCFStringEncodingUTF8);
+ uint32_t fontID = ::ATSFontFindFromName(str, kATSOptionFlagsDefault);
+ CFRelease(str);
+ return fontID;
}
-static SkTypeface* CreateTypeface_(const SkFaceRec* rec, const SkTypeface::Style style) {
+static uint32_t find_default_fontID() {
+ static const char* gDefaultNames[] = { "Arial", "Tahoma", "Helvetica" };
- OSStatus err;
- ATSUStyle atsuStyle;
- err = ::ATSUCreateAndCopyStyle(rec->fStyle, &atsuStyle);
-
- Boolean fontItalic = ((style & SkTypeface::kItalic) != 0);
- Boolean fontBold = ((style & SkTypeface::kBold) != 0);
- const ATSUAttributeTag tags[2] = { kATSUQDBoldfaceTag, kATSUQDItalicTag };
- const ATSUAttributeValuePtr values[2] = { &fontBold, &fontItalic };
- const ByteCount sizes[2] = { sizeof(Boolean), sizeof(Boolean) };
- err = ::ATSUSetAttributes(atsuStyle,2,tags,sizes,values);
-
- // get old font id and name
- ATSUFontID fontID = 0;
- ByteCount actual = 0;
- err = ::ATSUGetAttribute(rec->fStyle,kATSUFontTag,sizeof(ATSUFontID),&fontID,&actual);
-
- ByteCount actualLength = 0;
- char *fontname = NULL;
- err = ::ATSUFindFontName(fontID , kFontFamilyName, kFontUnicodePlatform, kFontNoScriptCode,
- kFontNoLanguageCode , 0 , NULL , &actualLength , NULL );
- if ( err == noErr)
- {
- actualLength += 1 ;
- fontname = (char*)malloc( actualLength );
- err = ::ATSUFindFontName(fontID, kFontFamilyName, kFontUnicodePlatform, kFontNoScriptCode,
- kFontNoLanguageCode, actualLength, fontname , NULL, NULL);
+ uint32_t fontID;
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gDefaultNames); i++) {
+ fontID = find_from_name(gDefaultNames[i]);
+ if (fontID) {
+ return fontID;
+ }
}
+ sk_throw();
+ return 0;
+}
- SkTypeface_Mac* ptypeface = NULL;
- if (fontname == NULL) {
- ptypeface = new SkTypeface_Mac(style,rec->fFontID);
- return ptypeface;
+static SkTypeface* CreateTypeface_(const char name[], SkTypeface::Style style) {
+ uint32_t fontID = 0;
+ if (NULL != name) {
+ fontID = find_from_name(name);
}
- else {
- uint32_t cs = FontFaceChecksum(fontname,style);
- ptypeface = new SkTypeface_Mac(style, cs);
-
- if (NULL == ptypeface) {
- SkASSERT(false);
- return NULL;
- }
-
- free(fontname);
-
- insert_ft_face(cs,atsuStyle);
+ if (0 == fontID) {
+ fontID = find_default_fontID();
}
- return ptypeface;
+ // we lie (for now) and report that we found the exact style bits
+ return new SkTypeface_Mac(style, fontID);
}
#pragma mark -
@@ -277,46 +106,33 @@ private:
};
SkScalerContext_Mac::SkScalerContext_Mac(const SkDescriptor* desc)
- : SkScalerContext(desc), fLayout(0), fStyle(0)
-{
+ : SkScalerContext(desc), fLayout(0), fStyle(0) {
SkAutoMutexAcquire ac(gFTMutex);
OSStatus err;
- SkFaceRec* rec = find_ft_face(fRec.fFontID);
- if (rec) {
- rec->ref();
- err = ::ATSUCreateAndCopyStyle(rec->fStyle, &fStyle);
- }
- else {
- SkASSERT(false);
- // create a default
- err = ::ATSUCreateStyle(&fStyle);
- }
+ err = ::ATSUCreateStyle(&fStyle);
+ SkASSERT(0 == err);
- uint32_t size = SkScalarFloor(fRec.fTextSize);
- Fixed fixedSize = IntToFixed(size);
+ Fixed fixedSize = SkScalarToFixed(fRec.fTextSize);
static const ATSUAttributeTag sizeTag = kATSUSizeTag;
static const ByteCount sizeTagSize = sizeof(Fixed);
const ATSUAttributeValuePtr values[] = { &fixedSize };
err = ::ATSUSetAttributes(fStyle,1,&sizeTag,&sizeTagSize,values);
+ SkASSERT(0 == err);
err = ::ATSUCreateTextLayout(&fLayout);
+ SkASSERT(0 == err);
fGrayColorSpace = ::CGColorSpaceCreateDeviceGray();
}
-SkScalerContext_Mac::~SkScalerContext_Mac()
-{
+SkScalerContext_Mac::~SkScalerContext_Mac() {
::CGColorSpaceRelease(fGrayColorSpace);
-
- unref_ft_face(fRec.fFontID);
-
::ATSUDisposeTextLayout(fLayout);
::ATSUDisposeStyle(fStyle);
}
-unsigned SkScalerContext_Mac::generateGlyphCount() const
-{
+unsigned SkScalerContext_Mac::generateGlyphCount() const {
return 0xFFFF;
}
@@ -407,24 +223,13 @@ void SkScalerContext_Mac::generateImage(const SkGlyph& glyph)
::CGContextSetGrayFillColor(contextRef, 1.0, 1.0);
::CGContextSetTextDrawingMode(contextRef, kCGTextFill);
-#if 1
- ATSUAttributeTag tag = kATSUCGContextTag;
- ByteCount size = sizeof(CGContextRef);
- ATSUAttributeValuePtr value = &contextRef;
- OSStatus err = ::ATSUSetLayoutControls(fLayout, 1, &tag, &size, &value);
- SkASSERT(!err);
- err = ::ATSUDrawText(fLayout, kATSUFromTextBeginning, kATSUToTextEnd,
- SkIntToFixed(-glyph.fLeft),
- SkIntToFixed(glyph.fTop + glyph.fHeight));
- SkASSERT(!err);
-#else
CGGlyph glyphID = glyph.getGlyphID();
CGFontRef fontRef = CGFontCreateWithPlatformFont(&fRec.fFontID);
CGContextSetFont(contextRef, fontRef);
CGContextSetFontSize(contextRef, SkScalarToFloat(fRec.fTextSize));
CGContextShowGlyphsAtPoint(contextRef, -glyph.fLeft,
glyph.fTop + glyph.fHeight, &glyphID, 1);
-#endif
+
::CGContextRelease(contextRef);
}
@@ -493,73 +298,41 @@ SkTypeface* SkFontHost::Deserialize(SkStream* stream) {
}
SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
-
- //Should not be used on Mac, keep linker happy
- SkASSERT(false);
- return CreateTypeface_(gDefaultfont,SkTypeface::kNormal);
+ return NULL;
}
SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
- // TODO
- return CreateTypeface_(gDefaultfont,SkTypeface::kNormal);
+ return NULL;
}
-SkScalerContext* SkFontHost::CreateScalerContext(const SkDescriptor* desc)
-{
+SkScalerContext* SkFontHost::CreateScalerContext(const SkDescriptor* desc) {
return new SkScalerContext_Mac(desc);
}
SkScalerContext* SkFontHost::CreateFallbackScalerContext(const SkScalerContext::Rec& rec)
{
- SkAutoDescriptor ad(sizeof(rec) + sizeof(gDefaultfont) + SkDescriptor::ComputeOverhead(2));
+ SkAutoDescriptor ad(sizeof(rec) + SkDescriptor::ComputeOverhead(1));
SkDescriptor* desc = ad.getDesc();
-
+
desc->init();
SkScalerContext::Rec* newRec =
- (SkScalerContext::Rec*)desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
-
- CreateTypeface_(gDefaultfont,SkTypeface::kNormal);
- newRec->fFontID = FontFaceChecksum(gDefaultfont,SkTypeface::kNormal);
+ (SkScalerContext::Rec*)desc->addEntry(kRec_SkDescriptorTag,
+ sizeof(rec), &rec);
+ newRec->fFontID = find_default_fontID();
desc->computeChecksum();
-
+
return SkFontHost::CreateScalerContext(desc);
}
SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
const char familyName[], SkTypeface::Style style) {
-
- SkAutoMutexAcquire ac(gFTMutex);
-
- // clip to legal style bits
- style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic);
-
- SkTypeface* tf = NULL;
-
- if (NULL == familyFace && NULL == familyName) {
- tf = CreateTypeface_(gDefaultfont,style);
- }
- else {
- if (NULL != familyFace) {
- uint32_t id = familyFace->uniqueID();
- SkFaceRec* rec = find_ft_face(id);
- if (!rec) {
- SkASSERT(false);
- tf = CreateTypeface_(gDefaultfont,style);
- }
- else {
- tf = CreateTypeface_(rec,style);
- }
- }
- else {
- tf = CreateTypeface_(familyName,style);
- }
- }
-
- if (NULL == tf) {
- tf = CreateTypeface_(gDefaultfont,style);
+ // todo: we don't know how to respect style bits
+ if (NULL == familyName && NULL != familyFace) {
+ familyFace->ref();
+ return const_cast<SkTypeface*>(familyFace);
+ } else {
+ return CreateTypeface_(familyName, style);
}
- return tf;
-
}
size_t SkFontHost::ShouldPurgeFontCache(size_t sizeAllocatedSoFar) {