зеркало из 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:
|
||||
virtual SkString onShortName() {
|
||||
return SkString("fontmgr");
|
||||
return SkString("fontmgr_iter");
|
||||
}
|
||||
|
||||
virtual SkISize onISize() {
|
||||
|
@ -53,6 +53,7 @@ protected:
|
|||
(void)drawString(canvas, fname, 20, y, paint);
|
||||
|
||||
SkScalar x = 220;
|
||||
|
||||
SkAutoTUnref<SkFontStyleSet> set(fm->createStyleSet(i));
|
||||
for (int j = 0; j < set->count(); ++j) {
|
||||
SkString sname;
|
||||
|
@ -76,6 +77,102 @@ private:
|
|||
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(FontMgrMatchGM); )
|
||||
|
|
|
@ -20,6 +20,9 @@ public:
|
|||
virtual int count() = 0;
|
||||
virtual void getStyle(int index, SkFontStyle*, SkString* style) = 0;
|
||||
virtual SkTypeface* createTypeface(int index) = 0;
|
||||
virtual SkTypeface* matchStyle(const SkFontStyle& pattern) = 0;
|
||||
|
||||
static SkFontStyleSet* CreateEmpty();
|
||||
};
|
||||
|
||||
class SkFontMgr : public SkRefCnt {
|
||||
|
@ -28,6 +31,8 @@ public:
|
|||
void getFamilyName(int index, SkString* familyName);
|
||||
SkFontStyleSet* createStyleSet(int index);
|
||||
|
||||
SkFontStyleSet* matchFamily(const char familyName[]);
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
@ -71,6 +76,8 @@ protected:
|
|||
virtual void onGetFamilyName(int index, SkString* familyName) = 0;
|
||||
virtual SkFontStyleSet* onCreateStyleSet(int index) = 0;
|
||||
|
||||
virtual SkFontStyleSet* onMatchFamily(const char familyName[]) = 0;
|
||||
|
||||
virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
|
||||
const SkFontStyle&) = 0;
|
||||
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"
|
||||
|
||||
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 {
|
||||
protected:
|
||||
virtual int onCountFamilies() SK_OVERRIDE {
|
||||
|
@ -64,6 +101,10 @@ protected:
|
|||
SkASSERT(!"onCreateStyleSet called with bad index");
|
||||
return NULL;
|
||||
}
|
||||
virtual SkFontStyleSet* onMatchFamily(const char[]) SK_OVERRIDE {
|
||||
return SkFontStyleSet::CreateEmpty();
|
||||
}
|
||||
|
||||
virtual SkTypeface* onMatchFamilyStyle(const char[],
|
||||
const SkFontStyle&) SK_OVERRIDE {
|
||||
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() {
|
||||
return this->onCountFamilies();
|
||||
}
|
||||
|
@ -109,6 +136,10 @@ SkFontStyleSet* SkFontMgr::createStyleSet(int index) {
|
|||
return this->onCreateStyleSet(index);
|
||||
}
|
||||
|
||||
SkFontStyleSet* SkFontMgr::matchFamily(const char familyName[]) {
|
||||
return this->onMatchFamily(familyName);
|
||||
}
|
||||
|
||||
SkTypeface* SkFontMgr::matchFamilyStyle(const char familyName[],
|
||||
const SkFontStyle& fs) {
|
||||
return this->onMatchFamilyStyle(familyName, fs);
|
||||
|
|
|
@ -96,6 +96,10 @@ private:
|
|||
CFRef fCFRef;
|
||||
};
|
||||
|
||||
static CFStringRef make_CFString(const char str[]) {
|
||||
return CFStringCreateWithCString(NULL, str, kCFStringEncodingUTF8);
|
||||
}
|
||||
|
||||
template<typename T> class AutoCGTable : SkNoncopyable {
|
||||
public:
|
||||
AutoCGTable(CGFontRef font)
|
||||
|
@ -498,8 +502,7 @@ static SkTypeface* NewFromName(const char familyName[], SkTypeface::Style theSty
|
|||
}
|
||||
|
||||
// Create the font info
|
||||
AutoCFRelease<CFStringRef> cfFontName(
|
||||
CFStringCreateWithCString(NULL, familyName, kCFStringEncodingUTF8));
|
||||
AutoCFRelease<CFStringRef> cfFontName(make_CFString(familyName));
|
||||
|
||||
AutoCFRelease<CFNumberRef> cfFontTraits(
|
||||
CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &ctFontTraits));
|
||||
|
@ -1913,6 +1916,18 @@ static int unit_width_to_fontstyle(float unit) {
|
|||
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) {
|
||||
AutoCFRelease<CFDictionaryRef> dict(
|
||||
(CFDictionaryRef)CTFontDescriptorCopyAttribute(desc,
|
||||
|
@ -2026,10 +2041,36 @@ public:
|
|||
return createFromDesc(fFamilyName, desc);
|
||||
}
|
||||
|
||||
virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE {
|
||||
if (0 == fCount) {
|
||||
return NULL;
|
||||
}
|
||||
return createFromDesc(fFamilyName, findMatchingDesc(pattern));
|
||||
}
|
||||
|
||||
private:
|
||||
CFArrayRef fArray;
|
||||
CFStringRef fFamilyName;
|
||||
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 {
|
||||
|
@ -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:
|
||||
SkFontMgr_Mac() : fCount(0), fNames(NULL) {}
|
||||
|
||||
|
@ -2075,20 +2129,14 @@ protected:
|
|||
if ((unsigned)index >= (unsigned)fCount) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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));
|
||||
return CreateSet(this->stringAt(index));
|
||||
}
|
||||
|
||||
|
||||
virtual SkFontStyleSet* onMatchFamily(const char familyName[]) SK_OVERRIDE {
|
||||
AutoCFRelease<CFStringRef> cfName(make_CFString(familyName));
|
||||
return CreateSet(cfName);
|
||||
}
|
||||
|
||||
virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
|
||||
const SkFontStyle&) SK_OVERRIDE {
|
||||
return NULL;
|
||||
|
|
Загрузка…
Ссылка в новой задаче