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
This commit is contained in:
reed@google.com 2011-03-22 14:07:59 +00:00
Родитель 08526c07f4
Коммит df49991eb3
4 изменённых файлов: 142 добавлений и 119 удалений

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -48,10 +48,10 @@ static const struct {
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 },

Просмотреть файл

@ -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 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 +40,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 +61,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 +84,24 @@ typedef SkNativeFontInfoList::const_iterator SkNativeFont
#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 @@ 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,7 +250,7 @@ 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);
@ -256,21 +260,18 @@ CTFontRef SkNativeFontCache::CreateNativeFont(const SkString &theName, SkTypefac
//
// 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 @@ 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
@ -621,9 +621,9 @@ static const char* map_css_names(const char* name) {
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 @@ static const char* map_css_names(const char* name) {
#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)