зеркало из https://github.com/mozilla/moz-skia.git
add matcher to fontstyleset
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:
Родитель
fc2f0d0e6e
Коммит
964988f0e9
|
@ -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;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче