#include "SkFontHost.h"
#include "SkDescriptor.h"
-#include "SkString.h"
-#include "SkPaint.h"
#include "SkFloatingPoint.h"
+#include "SkPaint.h"
+#include "SkString.h"
+#include "SkTypeface_mac.h"
#include "SkUtils.h"
-
-//============================================================================
-// Constants
-//----------------------------------------------------------------------------
static const SkFontID kSkInvalidFontID = 0;
static const size_t FONT_CACHE_MEMORY_BUDGET = 1024 * 1024;
static const float FONT_CANONICAL_POINTSIZE = 1.0f;
-//============================================================================
-// Types
-//----------------------------------------------------------------------------
-// Native font info
typedef struct {
SkString name;
SkTypeface::Style style;
CTFontRef fontRef;
} SkNativeFontInfo;
-typedef std::vector<SkNativeFontInfo> SkNativeFontInfoList;
-typedef SkNativeFontInfoList::iterator SkNativeFontInfoListIterator;
-typedef SkNativeFontInfoList::const_iterator SkNativeFontInfoListConstIterator;
-
-
-
-
+typedef std::vector<SkNativeFontInfo> SkNativeFontInfoList;
+typedef SkNativeFontInfoList::iterator SkNativeFontInfoListIterator;
//============================================================================
// Macros
#endif
+static SkTypeface::Style computeStyleBits(CTFontRef font, bool* isMonospace) {
+ unsigned style = SkTypeface::kNormal;
+ CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(font);
+ if (traits & kCTFontBoldTrait) {
+ style |= SkTypeface::kBold;
+ }
+ if (traits & kCTFontItalicTrait) {
+ style |= SkTypeface::kItalic;
+ }
+ if (isMonospace) {
+ *isMonospace = (traits & kCTFontMonoSpaceTrait) != 0;
+ }
+ return (SkTypeface::Style)style;
+}
//============================================================================
#pragma mark -
class SkNativeFontCache {
public:
- SkNativeFontCache(void);
- virtual ~SkNativeFontCache(void);
+ SkNativeFontCache(void);
+ virtual ~SkNativeFontCache(void);
+ bool IsValid(SkFontID fontID);
+ CTFontRef GetFont(SkFontID fontID);
+ SkNativeFontInfo GetFontInfo(const char familyName[], SkTypeface::Style);
+ SkNativeFontInfo CreateFont(const char familyName[], SkTypeface::Style);
+ SkNativeFontInfo CreateFromCTFont(CTFontRef);
- // Is a font ID valid?
- bool IsValid(SkFontID fontID);
-
-
- // Get a font
- CTFontRef GetFont(SkFontID fontID);
- SkNativeFontInfo GetFontInfo(const SkString &theName, SkTypeface::Style theStyle);
-
-
- // Create a font
- SkNativeFontInfo CreateFont(const SkString &theName, SkTypeface::Style theStyle);
-
-
- // Get the font table
- static SkNativeFontCache *Get(void);
-
+ static SkNativeFontCache* Get(void);
private:
- CTFontRef CreateNativeFont(const SkString &name, SkTypeface::Style style);
+ CTFontRef CreateNativeFont(const char familyName[], SkTypeface::Style style);
private:
- SkNativeFontInfoList mFonts;
- SkMutex mMutex;
+ SkNativeFontInfoList mFonts;
+ SkMutex mMutex;
};
SkNativeFontCache::SkNativeFontCache(void)
return(mFonts.at(fontID).fontRef);
}
-SkNativeFontInfo SkNativeFontCache::GetFontInfo(const SkString &theName, SkTypeface::Style theStyle)
+SkNativeFontInfo SkNativeFontCache::GetFontInfo(const char familyName[],
+ SkTypeface::Style theStyle)
{ SkAutoMutexAcquire acquireLock(mMutex);
SkNativeFontInfo fontInfo;
SkNativeFontInfoListIterator theIter;
-
// Validate our parameters
- SkASSERT(!theName.isEmpty());
-
+ SkASSERT(familyName && *familyName);
// Get the state we need
fontInfo.style = SkTypeface::kNormal;
fontInfo.fontID = kSkInvalidFontID;
fontInfo.fontRef = NULL;
-
// Get the font
- for (theIter = mFonts.begin(); theIter != mFonts.end(); theIter++)
- {
- if (theIter->name == theName && theIter->style == theStyle)
- return(*theIter);
+ for (theIter = mFonts.begin(); theIter != mFonts.end(); theIter++) {
+ if (theIter->style == theStyle && theIter->name.equals(familyName)) {
+ return *theIter;
}
+ }
- return(fontInfo);
+ return fontInfo;
}
-SkNativeFontInfo SkNativeFontCache::CreateFont(const SkString &theName, SkTypeface::Style theStyle)
-{ SkAutoMutexAcquire acquireLock(mMutex);
+SkNativeFontInfo SkNativeFontCache::CreateFont(const char familyName[],
+ SkTypeface::Style theStyle) {
+ SkAutoMutexAcquire acquireLock(mMutex);
SkNativeFontInfo fontInfo;
-
-
+
+
// Validate our parameters
- SkASSERT(!theName.isEmpty());
-
-
+ SkASSERT(familyName && *familyName);
+
+
// Create the font
- fontInfo.name = theName;
- fontInfo.style = theStyle;
- fontInfo.fontID = mFonts.size();
- fontInfo.fontRef = CreateNativeFont(theName, theStyle);
-
+ fontInfo.name.set(familyName);
+ fontInfo.fontID = mFonts.size();
+ fontInfo.fontRef = CreateNativeFont(familyName, theStyle);
+ fontInfo.style = computeStyleBits(fontInfo.fontRef, NULL);
+
mFonts.push_back(fontInfo);
return(fontInfo);
}
-SkNativeFontCache *SkNativeFontCache::Get(void)
-{ static SkNativeFontCache sInstance;
-
+SkNativeFontInfo SkNativeFontCache::CreateFromCTFont(CTFontRef font) {
+ SkAutoMutexAcquire acquireLock(mMutex);
+ SkNativeFontInfo fontInfo;
+
+ // TODO: need to query the font's name
+// fontInfo.name.set(familyName);
+ fontInfo.fontID = mFonts.size();
+ fontInfo.fontRef = font;
+ CFRetain(font);
+ fontInfo.style = computeStyleBits(font, NULL);
+
+ mFonts.push_back(fontInfo);
+ return(fontInfo);
+}
- // Get the instance
- //
+SkNativeFontCache *SkNativeFontCache::Get(void) {
+ static SkNativeFontCache sInstance;
// We use a local static for well-defined static initialisation order.
- return(&sInstance);
+ return &sInstance;
}
///////////////////////////////////////////////////////////////////////////
-CTFontRef SkNativeFontCache::CreateNativeFont(const SkString &theName, SkTypeface::Style theStyle)
-{ CFMutableDictionaryRef cfAttributes, cfTraits;
+
+CTFontRef SkNativeFontCache::CreateNativeFont(const char familyName[],
+ SkTypeface::Style theStyle) {
+ CFMutableDictionaryRef cfAttributes, cfTraits;
CFNumberRef cfFontTraits;
CTFontSymbolicTraits ctFontTraits;
CTFontDescriptorRef ctFontDesc;
// Create the font info
- cfFontName = CFStringCreateWithCString(NULL, theName.c_str(), kCFStringEncodingUTF8);
+ cfFontName = CFStringCreateWithCString(NULL, familyName, kCFStringEncodingUTF8);
cfFontTraits = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &ctFontTraits);
cfAttributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
cfTraits = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
//
// Fonts are scaled using the Sk matrix, so we always request a font
// at a canonical size FONT_CANONICAL_POINTSIZE
- if (cfFontName != NULL && cfFontTraits != NULL && cfAttributes != NULL && cfTraits != NULL)
- {
+ if (cfFontName != NULL && cfFontTraits != NULL && cfAttributes != NULL && cfTraits != NULL) {
CFDictionaryAddValue(cfTraits, kCTFontSymbolicTrait, cfFontTraits);
CFDictionaryAddValue(cfAttributes, kCTFontFamilyNameAttribute, cfFontName);
CFDictionaryAddValue(cfAttributes, kCTFontTraitsAttribute, cfTraits);
ctFontDesc = CTFontDescriptorCreateWithAttributes(cfAttributes);
- if (ctFontDesc != NULL)
+ if (ctFontDesc != NULL) {
ctFont = CTFontCreateWithFontDescriptor(ctFontDesc, FONT_CANONICAL_POINTSIZE, NULL);
-
}
+ }
-
- // Clean up
CFSafeRelease(cfFontName);
CFSafeRelease(cfFontTraits);
CFSafeRelease(cfAttributes);
return(ctFont);
}
-
-
-
-
//============================================================================
// SkTypeface_Mac
//----------------------------------------------------------------------------
#pragma mark -
class SkTypeface_Mac : public SkTypeface {
public:
- SkTypeface_Mac(SkTypeface::Style style, uint32_t fontID);
+ SkTypeface_Mac(SkTypeface::Style style, uint32_t fontID);
};
SkTypeface_Mac::SkTypeface_Mac(SkTypeface::Style style, uint32_t fontID)
- : SkTypeface(style, fontID)
-{
+ : SkTypeface(style, fontID) {
}
-
-
+SkTypeface* SkCreateTypefaceFromCTFont(CTFontRef font) {
+ SkNativeFontInfo info;
+
+ info = SkNativeFontCache::Get()->CreateFromCTFont(font);
+ return new SkTypeface_Mac(info.style, info.fontID);
+}
//============================================================================
// SkScalerContext_Mac
const char* fFrom;
const char* fTo;
} gPairs[] = {
- { "sans-serif", FONT_DEFAULT_NAME },
- { "serif", "Times" },
- { "monospace", "Courier" }
+ { "sans-serif", "Helvetica" },
+ { "serif", "Times" },
+ { "monospace", "Courier" }
};
for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) {
#pragma mark -
SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
- const char familyName[],
- const void* data, size_t bytelength,
- SkTypeface::Style style)
-{ SkTypeface *theTypeface;
- SkNativeFontCache *fontTable;
- SkNativeFontInfo fontInfo;
- SkString fontName;
-
+ const char familyName[],
+ const void* data, size_t bytelength,
+ SkTypeface::Style style) {
if (familyName) {
familyName = map_css_names(familyName);
}
- // Get the state we need
- fontName = SkString(familyName);
- fontTable = SkNativeFontCache::Get();
-
+ SkNativeFontCache* fontTable = SkNativeFontCache::Get();
// Clone an existing typeface
// TODO: only clone if style matches the familyFace's style...
- if (familyName == NULL && familyFace != NULL)
- {
+ if (familyName == NULL && familyFace != NULL) {
familyFace->ref();
- return(const_cast<SkTypeface*>(familyFace));
- }
+ return const_cast<SkTypeface*>(familyFace);
+ }
- if (fontName.isEmpty()) {
- fontName.set(FONT_DEFAULT_NAME);
+ if (!familyName || !*familyName) {
+ familyName = FONT_DEFAULT_NAME;
}
- // Get the native font
- fontInfo = fontTable->GetFontInfo(fontName, style);
- if (fontInfo.fontID == kSkInvalidFontID)
- fontInfo = fontTable->CreateFont(fontName, style);
+ // Get the native font
+ SkNativeFontInfo fontInfo = fontTable->GetFontInfo(familyName, style);
+ if (fontInfo.fontID == kSkInvalidFontID) {
+ fontInfo = fontTable->CreateFont(familyName, style);
+ }
- // Create the typeface
- theTypeface = new SkTypeface_Mac(fontInfo.style, fontInfo.fontID);
- return(theTypeface);
+ return new SkTypeface_Mac(fontInfo.style, fontInfo.fontID);
}
SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream)