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)