Review URL: https://codereview.chromium.org/13312002

git-svn-id: http://skia.googlecode.com/svn/trunk@8444 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
reed@google.com 2013-03-29 14:57:22 +00:00
Родитель fc2f0d0e6e
Коммит 964988f0e9
4 изменённых файлов: 213 добавлений и 30 удалений

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

@ -28,7 +28,7 @@ public:
protected: protected:
virtual SkString onShortName() { virtual SkString onShortName() {
return SkString("fontmgr"); return SkString("fontmgr_iter");
} }
virtual SkISize onISize() { virtual SkISize onISize() {
@ -53,6 +53,7 @@ protected:
(void)drawString(canvas, fname, 20, y, paint); (void)drawString(canvas, fname, 20, y, paint);
SkScalar x = 220; SkScalar x = 220;
SkAutoTUnref<SkFontStyleSet> set(fm->createStyleSet(i)); SkAutoTUnref<SkFontStyleSet> set(fm->createStyleSet(i));
for (int j = 0; j < set->count(); ++j) { for (int j = 0; j < set->count(); ++j) {
SkString sname; SkString sname;
@ -76,6 +77,102 @@ private:
typedef GM INHERITED; typedef GM INHERITED;
}; };
class FontMgrMatchGM : public skiagm::GM {
SkAutoTUnref<SkFontMgr> fFM;
public:
FontMgrMatchGM() : fFM(SkFontMgr::RefDefault()) {
SkGraphics::SetFontCacheLimit(16 * 1024 * 1024);
}
protected:
virtual SkString onShortName() {
return SkString("fontmgr_match");
}
virtual SkISize onISize() {
return SkISize::Make(640, 1024);
}
void iterateFamily(SkCanvas* canvas, const SkPaint& paint,
SkFontStyleSet* fset) {
SkPaint p(paint);
SkScalar y = 0;
for (int j = 0; j < fset->count(); ++j) {
SkString sname;
SkFontStyle fs;
fset->getStyle(j, &fs, &sname);
sname.appendf(" [%d %d]", fs.weight(), fs.width());
SkSafeUnref(p.setTypeface(fset->createTypeface(j)));
(void)drawString(canvas, sname, 0, y, p);
y += 24;
}
}
void exploreFamily(SkCanvas* canvas, const SkPaint& paint,
SkFontStyleSet* fset) {
SkPaint p(paint);
SkScalar y = 0;
for (int weight = 100; weight <= 900; weight += 200) {
for (int width = 1; width <= 9; width += 2) {
SkFontStyle fs(weight, width, SkFontStyle::kUpright_Slant);
SkTypeface* face = fset->matchStyle(fs);
if (face) {
SkString str;
str.printf("request [%d %d]", fs.weight(), fs.width());
p.setTypeface(face)->unref();
(void)drawString(canvas, str, 0, y, p);
y += 24;
}
}
}
}
virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
SkPaint paint;
paint.setAntiAlias(true);
paint.setLCDRenderText(true);
paint.setSubpixelText(true);
paint.setTextSize(17);
static const char* gNames[] = {
"Helvetica Neue", "Arial"
};
SkFontStyleSet* fset = NULL;
for (size_t i = 0; i < SK_ARRAY_COUNT(gNames); ++i) {
fset = fFM->matchFamily(gNames[i]);
if (fset && fset->count() > 0) {
break;
}
}
if (NULL == fset) {
return;
}
SkAutoUnref aur(fset);
canvas->translate(20, 40);
this->exploreFamily(canvas, paint, fset);
canvas->translate(150, 0);
this->iterateFamily(canvas, paint, fset);
}
virtual uint32_t onGetFlags() const SK_OVERRIDE {
// fontdescriptors (and therefore serialization) don't yet understand
// these new styles, so skip tests that exercise that for now.
return kSkipPicture_Flag | kSkipPipe_Flag;
}
private:
typedef GM INHERITED;
};
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
DEF_GM( return SkNEW(FontMgrGM); ) DEF_GM( return SkNEW(FontMgrGM); )
DEF_GM( return SkNEW(FontMgrMatchGM); )

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

@ -20,6 +20,9 @@ public:
virtual int count() = 0; virtual int count() = 0;
virtual void getStyle(int index, SkFontStyle*, SkString* style) = 0; virtual void getStyle(int index, SkFontStyle*, SkString* style) = 0;
virtual SkTypeface* createTypeface(int index) = 0; virtual SkTypeface* createTypeface(int index) = 0;
virtual SkTypeface* matchStyle(const SkFontStyle& pattern) = 0;
static SkFontStyleSet* CreateEmpty();
}; };
class SkFontMgr : public SkRefCnt { class SkFontMgr : public SkRefCnt {
@ -28,6 +31,8 @@ public:
void getFamilyName(int index, SkString* familyName); void getFamilyName(int index, SkString* familyName);
SkFontStyleSet* createStyleSet(int index); SkFontStyleSet* createStyleSet(int index);
SkFontStyleSet* matchFamily(const char familyName[]);
/** /**
* Find the closest matching typeface to the specified familyName and style * Find the closest matching typeface to the specified familyName and style
* and return a ref to it. The caller must call unref() on the returned * and return a ref to it. The caller must call unref() on the returned
@ -71,6 +76,8 @@ protected:
virtual void onGetFamilyName(int index, SkString* familyName) = 0; virtual void onGetFamilyName(int index, SkString* familyName) = 0;
virtual SkFontStyleSet* onCreateStyleSet(int index) = 0; virtual SkFontStyleSet* onCreateStyleSet(int index) = 0;
virtual SkFontStyleSet* onMatchFamily(const char familyName[]) = 0;
virtual SkTypeface* onMatchFamilyStyle(const char familyName[], virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
const SkFontStyle&) = 0; const SkFontStyle&) = 0;
virtual SkTypeface* onMatchFaceStyle(const SkTypeface*, virtual SkTypeface* onMatchFaceStyle(const SkTypeface*,

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

@ -50,8 +50,45 @@ void SkFontHost::SetSubpixelOrder(LCDOrder order) {
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#include "SkFontStyle.h"
SkFontStyle::SkFontStyle() {
fUnion.fU32 = 0;
fUnion.fR.fWeight = kNormal_Weight;
fUnion.fR.fWidth = kNormal_Width;
fUnion.fR.fSlant = kUpright_Slant;
}
SkFontStyle::SkFontStyle(int weight, int width, Slant slant) {
fUnion.fU32 = 0;
fUnion.fR.fWeight = SkPin32(weight, kThin_Weight, kBlack_Weight);
fUnion.fR.fWidth = SkPin32(width, kUltraCondensed_Width, kUltaExpanded_Width);
fUnion.fR.fSlant = SkPin32(slant, kUpright_Slant, kItalic_Slant);
}
#include "SkFontMgr.h" #include "SkFontMgr.h"
class SkEmptyFontStyleSet : public SkFontStyleSet {
public:
virtual int count() SK_OVERRIDE { return 0; }
virtual void getStyle(int, SkFontStyle*, SkString*) SK_OVERRIDE {
SkASSERT(!"SkFontStyleSet::getStyle called on empty set");
}
virtual SkTypeface* createTypeface(int index) SK_OVERRIDE {
SkASSERT(!"SkFontStyleSet::createTypeface called on empty set");
return NULL;
}
virtual SkTypeface* matchStyle(const SkFontStyle&) SK_OVERRIDE {
return NULL;
}
};
SkFontStyleSet* SkFontStyleSet::CreateEmpty() {
return SkNEW(SkEmptyFontStyleSet);
}
///////////////////////////////////////////////////////////////////////////////
class SkEmptyFontMgr : public SkFontMgr { class SkEmptyFontMgr : public SkFontMgr {
protected: protected:
virtual int onCountFamilies() SK_OVERRIDE { virtual int onCountFamilies() SK_OVERRIDE {
@ -64,6 +101,10 @@ protected:
SkASSERT(!"onCreateStyleSet called with bad index"); SkASSERT(!"onCreateStyleSet called with bad index");
return NULL; return NULL;
} }
virtual SkFontStyleSet* onMatchFamily(const char[]) SK_OVERRIDE {
return SkFontStyleSet::CreateEmpty();
}
virtual SkTypeface* onMatchFamilyStyle(const char[], virtual SkTypeface* onMatchFamilyStyle(const char[],
const SkFontStyle&) SK_OVERRIDE { const SkFontStyle&) SK_OVERRIDE {
return NULL; return NULL;
@ -83,20 +124,6 @@ protected:
} }
}; };
SkFontStyle::SkFontStyle() {
fUnion.fU32 = 0;
fUnion.fR.fWeight = kNormal_Weight;
fUnion.fR.fWidth = kNormal_Width;
fUnion.fR.fSlant = kUpright_Slant;
}
SkFontStyle::SkFontStyle(int weight, int width, Slant slant) {
fUnion.fU32 = 0;
fUnion.fR.fWeight = SkPin32(weight, kThin_Weight, kBlack_Weight);
fUnion.fR.fWidth = SkPin32(width, kUltraCondensed_Width, kUltaExpanded_Width);
fUnion.fR.fSlant = SkPin32(slant, kUpright_Slant, kItalic_Slant);
}
int SkFontMgr::countFamilies() { int SkFontMgr::countFamilies() {
return this->onCountFamilies(); return this->onCountFamilies();
} }
@ -109,6 +136,10 @@ SkFontStyleSet* SkFontMgr::createStyleSet(int index) {
return this->onCreateStyleSet(index); return this->onCreateStyleSet(index);
} }
SkFontStyleSet* SkFontMgr::matchFamily(const char familyName[]) {
return this->onMatchFamily(familyName);
}
SkTypeface* SkFontMgr::matchFamilyStyle(const char familyName[], SkTypeface* SkFontMgr::matchFamilyStyle(const char familyName[],
const SkFontStyle& fs) { const SkFontStyle& fs) {
return this->onMatchFamilyStyle(familyName, fs); return this->onMatchFamilyStyle(familyName, fs);

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

@ -96,6 +96,10 @@ private:
CFRef fCFRef; CFRef fCFRef;
}; };
static CFStringRef make_CFString(const char str[]) {
return CFStringCreateWithCString(NULL, str, kCFStringEncodingUTF8);
}
template<typename T> class AutoCGTable : SkNoncopyable { template<typename T> class AutoCGTable : SkNoncopyable {
public: public:
AutoCGTable(CGFontRef font) AutoCGTable(CGFontRef font)
@ -498,8 +502,7 @@ static SkTypeface* NewFromName(const char familyName[], SkTypeface::Style theSty
} }
// Create the font info // Create the font info
AutoCFRelease<CFStringRef> cfFontName( AutoCFRelease<CFStringRef> cfFontName(make_CFString(familyName));
CFStringCreateWithCString(NULL, familyName, kCFStringEncodingUTF8));
AutoCFRelease<CFNumberRef> cfFontTraits( AutoCFRelease<CFNumberRef> cfFontTraits(
CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &ctFontTraits)); CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &ctFontTraits));
@ -1913,6 +1916,18 @@ static int unit_width_to_fontstyle(float unit) {
return sk_float_round2int(value); return sk_float_round2int(value);
} }
static inline int sqr(int value) {
SkASSERT(SkAbs32(value) < 0x7FFF); // check for overflow
return value * value;
}
// We normalize each axis (weight, width, italic) to be base-900
static int compute_metric(const SkFontStyle& a, const SkFontStyle& b) {
return sqr(a.weight() - b.weight()) +
sqr((a.width() - b.width()) * 100) +
sqr((a.isItalic() != b.isItalic()) * 900);
}
static SkFontStyle desc2fontstyle(CTFontDescriptorRef desc) { static SkFontStyle desc2fontstyle(CTFontDescriptorRef desc) {
AutoCFRelease<CFDictionaryRef> dict( AutoCFRelease<CFDictionaryRef> dict(
(CFDictionaryRef)CTFontDescriptorCopyAttribute(desc, (CFDictionaryRef)CTFontDescriptorCopyAttribute(desc,
@ -2026,10 +2041,36 @@ public:
return createFromDesc(fFamilyName, desc); return createFromDesc(fFamilyName, desc);
} }
virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE {
if (0 == fCount) {
return NULL;
}
return createFromDesc(fFamilyName, findMatchingDesc(pattern));
}
private: private:
CFArrayRef fArray; CFArrayRef fArray;
CFStringRef fFamilyName; CFStringRef fFamilyName;
int fCount; int fCount;
CTFontDescriptorRef findMatchingDesc(const SkFontStyle& pattern) const {
int bestMetric = SK_MaxS32;
CTFontDescriptorRef bestDesc = NULL;
for (int i = 0; i < fCount; ++i) {
CTFontDescriptorRef desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray, i);
int metric = compute_metric(pattern, desc2fontstyle(desc));
if (0 == metric) {
return desc;
}
if (metric < bestMetric) {
bestMetric = metric;
bestDesc = desc;
}
}
SkASSERT(bestDesc);
return bestDesc;
}
}; };
class SkFontMgr_Mac : public SkFontMgr { class SkFontMgr_Mac : public SkFontMgr {
@ -2048,6 +2089,19 @@ class SkFontMgr_Mac : public SkFontMgr {
} }
} }
static SkFontStyleSet* CreateSet(CFStringRef cfFamilyName) {
AutoCFRelease<CFMutableDictionaryRef> cfAttr(
CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks));
CFDictionaryAddValue(cfAttr, kCTFontFamilyNameAttribute, cfFamilyName);
AutoCFRelease<CTFontDescriptorRef> desc(
CTFontDescriptorCreateWithAttributes(cfAttr));
return SkNEW_ARGS(SkFontStyleSet_Mac, (cfFamilyName, desc));
}
public: public:
SkFontMgr_Mac() : fCount(0), fNames(NULL) {} SkFontMgr_Mac() : fCount(0), fNames(NULL) {}
@ -2075,20 +2129,14 @@ protected:
if ((unsigned)index >= (unsigned)fCount) { if ((unsigned)index >= (unsigned)fCount) {
return NULL; return NULL;
} }
return CreateSet(this->stringAt(index));
AutoCFRelease<CFMutableDictionaryRef> cfAttr(
CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks));
CFDictionaryAddValue(cfAttr, kCTFontFamilyNameAttribute,
this->stringAt(index));
AutoCFRelease<CTFontDescriptorRef> desc(
CTFontDescriptorCreateWithAttributes(cfAttr));
return SkNEW_ARGS(SkFontStyleSet_Mac, (this->stringAt(index), desc));
} }
virtual SkFontStyleSet* onMatchFamily(const char familyName[]) SK_OVERRIDE {
AutoCFRelease<CFStringRef> cfName(make_CFString(familyName));
return CreateSet(cfName);
}
virtual SkTypeface* onMatchFamilyStyle(const char familyName[], virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
const SkFontStyle&) SK_OVERRIDE { const SkFontStyle&) SK_OVERRIDE {
return NULL; return NULL;