aboutsummaryrefslogtreecommitdiffstats
path: root/src/ports/SkFontHost_mac_coretext.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ports/SkFontHost_mac_coretext.cpp')
-rw-r--r--src/ports/SkFontHost_mac_coretext.cpp292
1 files changed, 163 insertions, 129 deletions
diff --git a/src/ports/SkFontHost_mac_coretext.cpp b/src/ports/SkFontHost_mac_coretext.cpp
index ae39361..2def427 100644
--- a/src/ports/SkFontHost_mac_coretext.cpp
+++ b/src/ports/SkFontHost_mac_coretext.cpp
@@ -18,28 +18,18 @@
#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 char FONT_DEFAULT_NAME[] = "Lucida Sans";
-static const float FONT_CANONICAL_POINTSIZE = 1.0f;
-
-
-//============================================================================
-// Types
-//----------------------------------------------------------------------------
-// Native font info
typedef struct {
SkString name;
SkTypeface::Style style;
@@ -47,13 +37,8 @@ typedef struct {
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
@@ -73,7 +58,21 @@ typedef SkNativeFontInfoList::const_iterator SkNativeFont
#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;
+}
//============================================================================
@@ -82,34 +81,24 @@ typedef SkNativeFontInfoList::const_iterator SkNativeFont
#pragma mark -
class SkNativeFontCache {
public:
- SkNativeFontCache(void);
- virtual ~SkNativeFontCache(void);
-
-
- // Is a font ID valid?
- bool IsValid(SkFontID fontID);
-
+ SkNativeFontCache(void);
+ virtual ~SkNativeFontCache(void);
- // 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);
+ 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);
+ 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)
@@ -168,64 +157,76 @@ CTFontRef SkNativeFontCache::GetFont(SkFontID fontID)
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;
@@ -246,31 +247,25 @@ CTFontRef SkNativeFontCache::CreateNativeFont(const SkString &theName, SkTypefac
// 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);
// Create the font
- //
- // 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)
- ctFont = CTFontCreateWithFontDescriptor(ctFontDesc, FONT_CANONICAL_POINTSIZE, NULL);
-
+ if (ctFontDesc != NULL) {
+ ctFont = CTFontCreateWithFontDescriptor(ctFontDesc, 0, NULL);
}
+ }
-
- // Clean up
CFSafeRelease(cfFontName);
CFSafeRelease(cfFontTraits);
CFSafeRelease(cfAttributes);
@@ -280,28 +275,27 @@ CTFontRef SkNativeFontCache::CreateNativeFont(const SkString &theName, SkTypefac
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
@@ -358,15 +352,15 @@ SkScalerContext_Mac::SkScalerContext_Mac(const SkDescriptor* desc)
mColorSpaceRGB = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGBLinear);
mColorSpaceGray = CGColorSpaceCreateDeviceGray();
- const float inv = 1.0f / FONT_CANONICAL_POINTSIZE;
- mTransform = CGAffineTransformMake(SkScalarToFloat(skMatrix[SkMatrix::kMScaleX]) * inv,
- -SkScalarToFloat(skMatrix[SkMatrix::kMSkewY]) * inv,
- -SkScalarToFloat(skMatrix[SkMatrix::kMSkewX]) * inv,
- SkScalarToFloat(skMatrix[SkMatrix::kMScaleY]) * inv,
- SkScalarToFloat(skMatrix[SkMatrix::kMTransX]) * inv,
- SkScalarToFloat(skMatrix[SkMatrix::kMTransY]) * inv);
+ mTransform = CGAffineTransformMake(SkScalarToFloat(skMatrix[SkMatrix::kMScaleX]),
+ -SkScalarToFloat(skMatrix[SkMatrix::kMSkewY]),
+ -SkScalarToFloat(skMatrix[SkMatrix::kMSkewX]),
+ SkScalarToFloat(skMatrix[SkMatrix::kMScaleY]),
+ SkScalarToFloat(skMatrix[SkMatrix::kMTransX]),
+ SkScalarToFloat(skMatrix[SkMatrix::kMTransY]));
- mFont = CTFontCreateCopyWithAttributes(ctFont, 0.0, &mTransform, NULL);
+ // since our matrix includes everything, we pass 1 for pointSize
+ mFont = CTFontCreateCopyWithAttributes(ctFont, 1, &mTransform, NULL);
mGlyphCount = (uint16_t) numGlyphs;
}
@@ -445,6 +439,19 @@ void SkScalerContext_Mac::generateMetrics(SkGlyph* glyph)
#include "SkColorPriv.h"
+static void bytes_to_bits(uint8_t dst[], const uint8_t src[], int count) {
+ while (count > 0) {
+ uint8_t mask = 0;
+ for (int i = 7; i >= 0; --i) {
+ mask |= (*src++ >> 7) << i;
+ if (0 == --count) {
+ break;
+ }
+ }
+ *dst++ = mask;
+ }
+}
+
static inline uint16_t rgb_to_lcd16(uint32_t rgb) {
int r = (rgb >> 16) & 0xFF;
int g = (rgb >> 8) & 0xFF;
@@ -480,6 +487,7 @@ void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) {
void* image = glyph.fImage;
size_t rowBytes = glyph.rowBytes();
float grayColor = 1; // white
+ bool doAA = true;
/* For LCD16, we first create a temp offscreen cg-context in 32bit,
* erase to white, and then draw a black glyph into it. Then we can
@@ -496,6 +504,12 @@ void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) {
// we draw black-on-white (and invert in rgb_to_lcd16)
sk_memset32((uint32_t*)image, 0xFFFFFFFF, size >> 2);
grayColor = 0; // black
+ } else if (SkMask::kBW_Format == glyph.fMaskFormat) {
+ rowBytes = SkAlign4(glyph.fWidth);
+ size_t size = glyph.fHeight * rowBytes;
+ image = storage.realloc(size);
+ sk_bzero(image, size);
+ doAA = false;
}
cgContext = CGBitmapContextCreate(image, glyph.fWidth, glyph.fHeight, 8,
@@ -503,13 +517,15 @@ void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) {
// Draw the glyph
if (cgFont != NULL && cgContext != NULL) {
+#ifdef WE_ARE_RUNNING_ON_10_6_OR_LATER
CGContextSetAllowsFontSubpixelQuantization(cgContext, true);
CGContextSetShouldSubpixelQuantizeFonts(cgContext, true);
-
+#endif
+ CGContextSetShouldAntialias(cgContext, doAA);
CGContextSetGrayFillColor( cgContext, grayColor, 1.0);
CGContextSetTextDrawingMode(cgContext, kCGTextFill);
CGContextSetFont( cgContext, cgFont);
- CGContextSetFontSize( cgContext, FONT_CANONICAL_POINTSIZE);
+ CGContextSetFontSize( cgContext, 1); // cgFont know's its size
CGContextSetTextMatrix( cgContext, mTransform);
CGContextShowGlyphsAtPoint( cgContext, -glyph.fLeft, glyph.fTop + glyph.fHeight, &cgGlyph, 1);
@@ -526,6 +542,16 @@ void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) {
src = (const uint32_t*)((const char*)src + rowBytes);
dst = (uint16_t*)((char*)dst + dstRB);
}
+ } else if (SkMask::kBW_Format == glyph.fMaskFormat) {
+ // downsample from A8 to A1
+ const uint8_t* src = (const uint8_t*)image;
+ uint8_t* dst = (uint8_t*)glyph.fImage;
+ size_t dstRB = glyph.rowBytes();
+ for (int y = 0; y < glyph.fHeight; y++) {
+ bytes_to_bits(dst, src, glyph.fWidth);
+ src += rowBytes;
+ dst += dstRB;
+ }
}
}
@@ -616,48 +642,55 @@ void SkScalerContext_Mac::CTPathElement(void *info, const CGPathElement *element
}
+static const char* map_css_names(const char* name) {
+ static const struct {
+ const char* fFrom;
+ const char* fTo;
+ } gPairs[] = {
+ { "sans-serif", "Helvetica" },
+ { "serif", "Times" },
+ { "monospace", "Courier" }
+ };
-
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) {
+ if (strcmp(name, gPairs[i].fFrom) == 0) {
+ return gPairs[i].fTo;
+ }
+ }
+ return name; // no change
+}
///////////////////////////////////////////////////////////////////////////
#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;
-
-
- // Get the state we need
- fontName = SkString(familyName);
- fontTable = SkNativeFontCache::Get();
+ const char familyName[],
+ const void* data, size_t bytelength,
+ SkTypeface::Style style) {
+ if (familyName) {
+ familyName = map_css_names(familyName);
+ }
+ 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)
@@ -674,7 +707,8 @@ SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[])
// static
SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
- uint32_t fontID, bool perGlyphInfo) {
+ uint32_t fontID,
+ SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) {
SkASSERT(!"SkFontHost::GetAdvancedTypefaceMetrics unimplemented");
return NULL;
}