add SkCreateTypefaceFromCTFont() to create a typeface directly from a CTFontRef
Compute the actual style from the returned CTFontRef, rather than assuming the
request will always be met.
git-svn-id: http://skia.googlecode.com/svn/trunk@979 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/Makefile b/Makefile
index c37f4c7..b4aa02e 100644
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,8 @@
# setup our defaults
CC := gcc
GPP := g++
-C_INCLUDES := -Iinclude/config -Iinclude/core -Iinclude/effects -Iinclude/images -Iinclude/gpu -Iinclude/utils -Igpu/include
+C_INCLUDES := -Iinclude/config -Iinclude/core -Iinclude/effects -Iinclude/images -Iinclude/ports
+C_INCLUDES += -Iinclude/gpu -Iinclude/utils -Igpu/include
CFLAGS := -Wall -fstrict-aliasing
#CFLAGS += -W -Wextra -Wcast-align -Wchar-subscripts -Wformat -Wformat-security -Wno-format-y2k -Wno-parentheses -Wno-unused-parameter -Wpointer-arith -Wreturn-type -Wundef -Wwrite-strings
diff --git a/include/ports/SkTypeface_mac.h b/include/ports/SkTypeface_mac.h
new file mode 100644
index 0000000..61b226b
--- /dev/null
+++ b/include/ports/SkTypeface_mac.h
@@ -0,0 +1,32 @@
+/*
+ Copyright 2011 Google Inc.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+
+#ifndef SkTypeface_mac_DEFINED
+#define SkTypeface_mac_DEFINED
+
+#include "SkTypeface.h"
+#include <Carbon/Carbon.h>
+
+/**
+ * Like the other Typeface create methods, this returns a new reference to the
+ * corresponding typeface for the specified CTFontRef. The caller must call
+ * unref() when it is finished.
+ */
+SK_API extern SkTypeface* SkCreateTypefaceFromCTFont(CTFontRef);
+
+#endif
+
diff --git a/samplecode/SampleTypeface.cpp b/samplecode/SampleTypeface.cpp
index ed5e788..b9426b0 100644
--- a/samplecode/SampleTypeface.cpp
+++ b/samplecode/SampleTypeface.cpp
@@ -48,10 +48,10 @@
const char* fName;
SkTypeface::Style fStyle;
} gFaces[] = {
- { NULL, SkTypeface::kNormal },
- { NULL, SkTypeface::kBold },
- { NULL, SkTypeface::kItalic },
- { NULL, SkTypeface::kBoldItalic },
+ { "sans-serif", SkTypeface::kNormal },
+ { "sans-serif", SkTypeface::kBold },
+ { "sans-serif", SkTypeface::kItalic },
+ { "sans-serif", SkTypeface::kBoldItalic },
{ "serif", SkTypeface::kNormal },
{ "serif", SkTypeface::kBold },
{ "serif", SkTypeface::kItalic },
diff --git a/src/ports/SkFontHost_mac_coretext.cpp b/src/ports/SkFontHost_mac_coretext.cpp
index 1a6bf43..c38d2fd 100644
--- a/src/ports/SkFontHost_mac_coretext.cpp
+++ b/src/ports/SkFontHost_mac_coretext.cpp
@@ -18,16 +18,13 @@
#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;
@@ -36,10 +33,6 @@
static const float FONT_CANONICAL_POINTSIZE = 1.0f;
-//============================================================================
-// Types
-//----------------------------------------------------------------------------
-// Native font info
typedef struct {
SkString name;
SkTypeface::Style style;
@@ -47,13 +40,8 @@
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 +61,21 @@
#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 +84,24 @@
#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);
+ static SkNativeFontCache* Get(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);
+private:
+ CTFontRef CreateNativeFont(const char familyName[], SkTypeface::Style style);
private:
- CTFontRef CreateNativeFont(const SkString &name, SkTypeface::Style style);
-
-
-private:
- SkNativeFontInfoList mFonts;
- SkMutex mMutex;
+ SkNativeFontInfoList mFonts;
+ SkMutex mMutex;
};
SkNativeFontCache::SkNativeFontCache(void)
@@ -168,64 +160,76 @@
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,7 +250,7 @@
// 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);
@@ -256,21 +260,18 @@
//
// 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);
@@ -280,28 +281,27 @@
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
@@ -621,9 +621,9 @@
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++) {
@@ -638,43 +638,33 @@
#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));
- }
-
- if (fontName.isEmpty()) {
- fontName.set(FONT_DEFAULT_NAME);
+ return const_cast<SkTypeface*>(familyFace);
}
+
+ 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);
+ 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)