зеркало из https://github.com/mozilla/moz-skia.git
Add FontMgr to DirectWrite.
https://codereview.chromium.org/14314008/ git-svn-id: http://skia.googlecode.com/svn/trunk@8934 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
Родитель
a0eca26ac0
Коммит
7103344b64
|
@ -71,7 +71,11 @@ protected:
|
||||||
virtual uint32_t onGetFlags() const SK_OVERRIDE {
|
virtual uint32_t onGetFlags() const SK_OVERRIDE {
|
||||||
// fontdescriptors (and therefore serialization) don't yet understand
|
// fontdescriptors (and therefore serialization) don't yet understand
|
||||||
// these new styles, so skip tests that exercise that for now.
|
// these new styles, so skip tests that exercise that for now.
|
||||||
return kSkipPicture_Flag | kSkipPipe_Flag;
|
|
||||||
|
// If certain fonts are picked up (e.g. Microsoft Jhenghei 20MB for Regular, 12MB for Bold),
|
||||||
|
// the resulting pdf can be ~700MB and crashes Chrome's PDF viewer.
|
||||||
|
|
||||||
|
return kSkipPicture_Flag | kSkipPipe_Flag | kSkipPDF_Flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -295,11 +295,17 @@ private:
|
||||||
|
|
||||||
template <size_t N, typename T> class SK_API SkAutoSTMalloc : SkNoncopyable {
|
template <size_t N, typename T> class SK_API SkAutoSTMalloc : SkNoncopyable {
|
||||||
public:
|
public:
|
||||||
|
SkAutoSTMalloc() {
|
||||||
|
fPtr = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
SkAutoSTMalloc(size_t count) {
|
SkAutoSTMalloc(size_t count) {
|
||||||
if (count <= N) {
|
if (count > N) {
|
||||||
|
fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP);
|
||||||
|
} else if (count) {
|
||||||
fPtr = fTStorage;
|
fPtr = fTStorage;
|
||||||
} else {
|
} else {
|
||||||
fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP);
|
fPtr = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -314,10 +320,12 @@ public:
|
||||||
if (fPtr != fTStorage) {
|
if (fPtr != fTStorage) {
|
||||||
sk_free(fPtr);
|
sk_free(fPtr);
|
||||||
}
|
}
|
||||||
if (count <= N) {
|
if (count > N) {
|
||||||
|
fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP);
|
||||||
|
} else if (count) {
|
||||||
fPtr = fTStorage;
|
fPtr = fTStorage;
|
||||||
} else {
|
} else {
|
||||||
fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP);
|
fPtr = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,11 @@ private:
|
||||||
virtual ULONG STDMETHODCALLTYPE Release(void) = 0;
|
virtual ULONG STDMETHODCALLTYPE Release(void) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T> T* SkRefComPtr(T* ptr) {
|
||||||
|
ptr->AddRef();
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class SkTScopedComPtr : SkNoncopyable {
|
class SkTScopedComPtr : SkNoncopyable {
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -219,12 +219,14 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
|
||||||
|
|
||||||
GrGLint numFormats;
|
GrGLint numFormats;
|
||||||
GR_GL_GetIntegerv(gli, GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats);
|
GR_GL_GetIntegerv(gli, GR_GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats);
|
||||||
SkAutoSTMalloc<10, GrGLint> formats(numFormats);
|
if (numFormats) {
|
||||||
GR_GL_GetIntegerv(gli, GR_GL_COMPRESSED_TEXTURE_FORMATS, formats);
|
SkAutoSTMalloc<10, GrGLint> formats(numFormats);
|
||||||
for (int i = 0; i < numFormats; ++i) {
|
GR_GL_GetIntegerv(gli, GR_GL_COMPRESSED_TEXTURE_FORMATS, formats);
|
||||||
if (formats[i] == GR_GL_PALETTE8_RGBA8) {
|
for (int i = 0; i < numFormats; ++i) {
|
||||||
f8BitPaletteSupport = true;
|
if (formats[i] == GR_GL_PALETTE8_RGBA8) {
|
||||||
break;
|
f8BitPaletteSupport = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,37 @@ static bool isLCD(const SkScalerContext::Rec& rec) {
|
||||||
SkMask::kLCD32_Format == rec.fMaskFormat;
|
SkMask::kLCD32_Format == rec.fMaskFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Prefer to use this type to prevent template proliferation. */
|
||||||
|
typedef SkAutoSTMalloc<16, WCHAR> SkSMallocWCHAR;
|
||||||
|
|
||||||
|
static HRESULT cstring_to_wchar(const char* skname, SkSMallocWCHAR* name) {
|
||||||
|
int wlen = MultiByteToWideChar(CP_UTF8, 0, skname, -1, NULL, 0);
|
||||||
|
if (0 == wlen) {
|
||||||
|
HRM(HRESULT_FROM_WIN32(GetLastError()),
|
||||||
|
"Could not get length for wchar to utf-8 conversion.");
|
||||||
|
}
|
||||||
|
name->reset(wlen);
|
||||||
|
wlen = MultiByteToWideChar(CP_UTF8, 0, skname, -1, name->get(), wlen);
|
||||||
|
if (0 == wlen) {
|
||||||
|
HRM(HRESULT_FROM_WIN32(GetLastError()), "Could not convert wchar to utf-8.");
|
||||||
|
}
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT wchar_to_skstring(WCHAR* name, SkString* skname) {
|
||||||
|
int len = WideCharToMultiByte(CP_UTF8, 0, name, -1, NULL, 0, NULL, NULL);
|
||||||
|
if (0 == len) {
|
||||||
|
HRM(HRESULT_FROM_WIN32(GetLastError()),
|
||||||
|
"Could not get length for utf-8 to wchar conversion.");
|
||||||
|
}
|
||||||
|
skname->resize(len - 1);
|
||||||
|
len = WideCharToMultiByte(CP_UTF8, 0, name, -1, skname->writable_str(), len, NULL, NULL);
|
||||||
|
if (0 == len) {
|
||||||
|
HRM(HRESULT_FROM_WIN32(GetLastError()), "Could not convert utf-8 to wchar.");
|
||||||
|
}
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
class DWriteOffscreen {
|
class DWriteOffscreen {
|
||||||
|
@ -669,18 +700,18 @@ static bool FindByDWriteFont(SkTypeface* face, SkTypeface::Style requestedStyle,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SkTDArray<wchar_t> dwFaceFontFamilyNameChar(new wchar_t[dwFaceFontFamilyNameLength+1], dwFaceFontFamilyNameLength+1);
|
SkSMallocWCHAR dwFaceFontFamilyNameChar(dwFaceFontFamilyNameLength+1);
|
||||||
SkTDArray<wchar_t> dwFaceFontNameChar(new wchar_t[dwFaceFontNameLength+1], dwFaceFontNameLength+1);
|
SkSMallocWCHAR dwFaceFontNameChar(dwFaceFontNameLength+1);
|
||||||
HRB(dwFaceFontFamilyNames->GetString(0, dwFaceFontFamilyNameChar.begin(), dwFaceFontFamilyNameChar.count()));
|
HRB(dwFaceFontFamilyNames->GetString(0, dwFaceFontFamilyNameChar.get(), dwFaceFontFamilyNameLength+1));
|
||||||
HRB(dwFaceFontNames->GetString(0, dwFaceFontNameChar.begin(), dwFaceFontNameChar.count()));
|
HRB(dwFaceFontNames->GetString(0, dwFaceFontNameChar.get(), dwFaceFontNameLength+1));
|
||||||
|
|
||||||
SkTDArray<wchar_t> dwFontFamilyNameChar(new wchar_t[dwFontFamilyNameLength+1], dwFontFamilyNameLength+1);
|
SkSMallocWCHAR dwFontFamilyNameChar(dwFontFamilyNameLength+1);
|
||||||
SkTDArray<wchar_t> dwFontNameChar(new wchar_t[dwFontNameLength+1], dwFontNameLength+1);
|
SkSMallocWCHAR dwFontNameChar(dwFontNameLength+1);
|
||||||
HRB(dwFontFamilyNames->GetString(0, dwFontFamilyNameChar.begin(), dwFontFamilyNameChar.count()));
|
HRB(dwFontFamilyNames->GetString(0, dwFontFamilyNameChar.get(), dwFontFamilyNameLength+1));
|
||||||
HRB(dwFontNames->GetString(0, dwFontNameChar.begin(), dwFontNameChar.count()));
|
HRB(dwFontNames->GetString(0, dwFontNameChar.get(), dwFontNameLength+1));
|
||||||
|
|
||||||
return wcscmp(dwFaceFontFamilyNameChar.begin(), dwFontFamilyNameChar.begin()) == 0 &&
|
return wcscmp(dwFaceFontFamilyNameChar.get(), dwFontFamilyNameChar.get()) == 0 &&
|
||||||
wcscmp(dwFaceFontNameChar.begin(), dwFontNameChar.begin()) == 0;
|
wcscmp(dwFaceFontNameChar.get(), dwFontNameChar.get()) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SkTypeface* SkCreateTypefaceFromDWriteFont(IDWriteFontFace* fontFace,
|
SkTypeface* SkCreateTypefaceFromDWriteFont(IDWriteFontFace* fontFace,
|
||||||
|
@ -1049,24 +1080,17 @@ void DWriteFontTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
|
||||||
UINT32 dwFamilyNamesLength;
|
UINT32 dwFamilyNamesLength;
|
||||||
HRV(dwFamilyNames->GetStringLength(0, &dwFamilyNamesLength));
|
HRV(dwFamilyNames->GetStringLength(0, &dwFamilyNamesLength));
|
||||||
|
|
||||||
SkTDArray<wchar_t> dwFamilyNameChar(new wchar_t[dwFamilyNamesLength+1], dwFamilyNamesLength+1);
|
SkSMallocWCHAR dwFamilyNameChar(dwFamilyNamesLength+1);
|
||||||
HRV(dwFamilyNames->GetString(0, dwFamilyNameChar.begin(), dwFamilyNameChar.count()));
|
HRV(dwFamilyNames->GetString(0, dwFamilyNameChar.get(), dwFamilyNamesLength+1));
|
||||||
|
|
||||||
// Convert the family name to utf8.
|
SkString utf8FamilyName;
|
||||||
// Get the buffer size needed first.
|
HRV(wchar_to_skstring(dwFamilyNameChar.get(), &utf8FamilyName));
|
||||||
int str_len = WideCharToMultiByte(CP_UTF8, 0, dwFamilyNameChar.begin(), -1,
|
|
||||||
NULL, 0, NULL, NULL);
|
|
||||||
// Allocate a buffer (str_len already has terminating null accounted for).
|
|
||||||
SkTDArray<char> utf8FamilyName(new char[str_len], str_len);
|
|
||||||
// Now actually convert the string.
|
|
||||||
str_len = WideCharToMultiByte(CP_UTF8, 0, dwFamilyNameChar.begin(), -1,
|
|
||||||
utf8FamilyName.begin(), str_len, NULL, NULL);
|
|
||||||
|
|
||||||
desc->setFamilyName(utf8FamilyName.begin());
|
desc->setFamilyName(utf8FamilyName.c_str());
|
||||||
*isLocalStream = SkToBool(fDWriteFontFileLoader.get());
|
*isLocalStream = SkToBool(fDWriteFontFileLoader.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
|
static SkTypeface* create_from_stream(SkStream* stream) {
|
||||||
IDWriteFactory* factory;
|
IDWriteFactory* factory;
|
||||||
HRN(get_dwrite_factory(&factory));
|
HRN(get_dwrite_factory(&factory));
|
||||||
|
|
||||||
|
@ -1095,6 +1119,10 @@ SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
|
||||||
fontFileLoader.get(), streamFontCollectionLoader.get());
|
fontFileLoader.get(), streamFontCollectionLoader.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
|
||||||
|
return create_from_stream(stream);
|
||||||
|
}
|
||||||
|
|
||||||
SkStream* DWriteFontTypeface::onOpenStream(int* ttcIndex) const {
|
SkStream* DWriteFontTypeface::onOpenStream(int* ttcIndex) const {
|
||||||
*ttcIndex = 0;
|
*ttcIndex = 0;
|
||||||
|
|
||||||
|
@ -1135,23 +1163,12 @@ static HRESULT get_by_family_name(const char familyName[], IDWriteFontFamily** f
|
||||||
SkTScopedComPtr<IDWriteFontCollection> sysFontCollection;
|
SkTScopedComPtr<IDWriteFontCollection> sysFontCollection;
|
||||||
HR(factory->GetSystemFontCollection(&sysFontCollection, FALSE));
|
HR(factory->GetSystemFontCollection(&sysFontCollection, FALSE));
|
||||||
|
|
||||||
// Get the buffer size needed first.
|
SkSMallocWCHAR wideFamilyName;
|
||||||
int wlen = ::MultiByteToWideChar(CP_UTF8, 0, familyName,-1, NULL, 0);
|
HR(cstring_to_wchar(familyName, &wideFamilyName));
|
||||||
if (0 == wlen) {
|
|
||||||
return HRESULT_FROM_WIN32(GetLastError());
|
|
||||||
}
|
|
||||||
// Allocate a buffer
|
|
||||||
SkTDArray<wchar_t> wideFamilyName(new wchar_t[wlen], wlen);
|
|
||||||
// Now actually convert the string.
|
|
||||||
wlen = ::MultiByteToWideChar(CP_UTF8, 0, familyName, -1,
|
|
||||||
wideFamilyName.begin(), wlen);
|
|
||||||
if (0 == wlen) {
|
|
||||||
return HRESULT_FROM_WIN32(GetLastError());
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT32 index;
|
UINT32 index;
|
||||||
BOOL exists;
|
BOOL exists;
|
||||||
HR(sysFontCollection->FindFamilyName(wideFamilyName.begin(), &index, &exists));
|
HR(sysFontCollection->FindFamilyName(wideFamilyName.get(), &index, &exists));
|
||||||
|
|
||||||
if (exists) {
|
if (exists) {
|
||||||
HR(sysFontCollection->GetFontFamily(index, fontFamily));
|
HR(sysFontCollection->GetFontFamily(index, fontFamily));
|
||||||
|
@ -1389,22 +1406,13 @@ SkAdvancedTypefaceMetrics* DWriteFontTypeface::onGetAdvancedTypefaceMetrics(
|
||||||
UINT32 faceNameLength;
|
UINT32 faceNameLength;
|
||||||
hr = faceNames->GetStringLength(0, &faceNameLength);
|
hr = faceNames->GetStringLength(0, &faceNameLength);
|
||||||
|
|
||||||
size_t size = familyNameLength+1+faceNameLength+1;
|
UINT32 size = familyNameLength+1+faceNameLength+1;
|
||||||
SkTDArray<wchar_t> wFamilyName(new wchar_t[size], size);
|
SkSMallocWCHAR wFamilyName(size);
|
||||||
hr = familyNames->GetString(0, wFamilyName.begin(), size);
|
hr = familyNames->GetString(0, wFamilyName.get(), size);
|
||||||
wFamilyName[familyNameLength] = L' ';
|
wFamilyName[familyNameLength] = L' ';
|
||||||
hr = faceNames->GetString(0, &wFamilyName[familyNameLength+1], size - faceNameLength + 1);
|
hr = faceNames->GetString(0, &wFamilyName[familyNameLength+1], size - faceNameLength + 1);
|
||||||
|
|
||||||
size_t str_len = WideCharToMultiByte(CP_UTF8, 0, wFamilyName.begin(), -1, NULL, 0, NULL, NULL);
|
hr = wchar_to_skstring(wFamilyName.get(), &info->fFontName);
|
||||||
if (0 == str_len) {
|
|
||||||
//TODO: error
|
|
||||||
}
|
|
||||||
SkTDArray<char> familyName(new char[str_len], str_len);
|
|
||||||
str_len = WideCharToMultiByte(CP_UTF8, 0, wFamilyName.begin(), -1, familyName.begin(), str_len, NULL, NULL);
|
|
||||||
if (0 == str_len) {
|
|
||||||
//TODO: error
|
|
||||||
}
|
|
||||||
info->fFontName.set(familyName.begin(), str_len);
|
|
||||||
|
|
||||||
if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo) {
|
if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo) {
|
||||||
populate_glyph_to_unicode(fDWriteFontFace.get(), glyphCount, &(info->fGlyphToUnicode));
|
populate_glyph_to_unicode(fDWriteFontFace.get(), glyphCount, &(info->fGlyphToUnicode));
|
||||||
|
@ -1523,7 +1531,202 @@ SkAdvancedTypefaceMetrics* DWriteFontTypeface::onGetAdvancedTypefaceMetrics(
|
||||||
|
|
||||||
#include "SkFontMgr.h"
|
#include "SkFontMgr.h"
|
||||||
|
|
||||||
SkFontMgr* SkFontMgr::Factory() {
|
static void get_locale_string(IDWriteLocalizedStrings* names, const WCHAR* preferedLocale,
|
||||||
// todo
|
SkString* skname) {
|
||||||
return NULL;
|
UINT32 nameIndex = 0;
|
||||||
|
if (preferedLocale) {
|
||||||
|
// Ignore any errors and continue with index 0 if there is a problem.
|
||||||
|
BOOL nameExists;
|
||||||
|
names->FindLocaleName(preferedLocale, &nameIndex, &nameExists);
|
||||||
|
if (!nameExists) {
|
||||||
|
nameIndex = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT32 nameLength;
|
||||||
|
HRVM(names->GetStringLength(nameIndex, &nameLength), "Could not get name length.");
|
||||||
|
nameLength += 1;
|
||||||
|
|
||||||
|
SkSMallocWCHAR name(nameLength);
|
||||||
|
HRVM(names->GetString(nameIndex, name.get(), nameLength), "Could not get string.");
|
||||||
|
|
||||||
|
HRV(wchar_to_skstring(name.get(), skname));
|
||||||
|
}
|
||||||
|
|
||||||
|
class SkFontMgr_DirectWrite;
|
||||||
|
|
||||||
|
class SkFontStyleSet_DirectWrite : public SkFontStyleSet {
|
||||||
|
public:
|
||||||
|
SkFontStyleSet_DirectWrite(const SkFontMgr_DirectWrite* fontMgr, IDWriteFontFamily* fontFamily)
|
||||||
|
: fFontMgr(SkRef(fontMgr))
|
||||||
|
, fFontFamily(SkRefComPtr(fontFamily))
|
||||||
|
{ }
|
||||||
|
|
||||||
|
virtual int count() SK_OVERRIDE {
|
||||||
|
return fFontFamily->GetFontCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void getStyle(int index, SkFontStyle* fs, SkString* styleName);
|
||||||
|
|
||||||
|
virtual SkTypeface* createTypeface(int index) SK_OVERRIDE {
|
||||||
|
SkTScopedComPtr<IDWriteFont> font;
|
||||||
|
HRNM(fFontFamily->GetFont(index, &font), "Could not get font.");
|
||||||
|
|
||||||
|
SkTScopedComPtr<IDWriteFontFace> fontFace;
|
||||||
|
HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
|
||||||
|
|
||||||
|
return SkCreateTypefaceFromDWriteFont(fontFace.get(), font.get(), fFontFamily.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE {
|
||||||
|
DWRITE_FONT_STYLE slant;
|
||||||
|
switch (pattern.slant()) {
|
||||||
|
case SkFontStyle::kUpright_Slant:
|
||||||
|
slant = DWRITE_FONT_STYLE_NORMAL;
|
||||||
|
break;
|
||||||
|
case SkFontStyle::kItalic_Slant:
|
||||||
|
slant = DWRITE_FONT_STYLE_ITALIC;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
SkASSERT(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
DWRITE_FONT_WEIGHT weight = (DWRITE_FONT_WEIGHT)pattern.weight();
|
||||||
|
DWRITE_FONT_STRETCH width = (DWRITE_FONT_STRETCH)pattern.width();
|
||||||
|
|
||||||
|
SkTScopedComPtr<IDWriteFont> font;
|
||||||
|
HRNM(fFontFamily->GetFirstMatchingFont(weight, width, slant, &font),
|
||||||
|
"Could not match font in family.");
|
||||||
|
|
||||||
|
SkTScopedComPtr<IDWriteFontFace> fontFace;
|
||||||
|
HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
|
||||||
|
|
||||||
|
return SkCreateTypefaceFromDWriteFont(fontFace.get(), font.get(), fFontFamily.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
SkAutoTUnref<const SkFontMgr_DirectWrite> fFontMgr;
|
||||||
|
SkTScopedComPtr<IDWriteFontFamily> fFontFamily;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SkFontMgr_DirectWrite : public SkFontMgr {
|
||||||
|
public:
|
||||||
|
/** localeNameLength must include the null terminator. */
|
||||||
|
SkFontMgr_DirectWrite(IDWriteFontCollection* fontCollection,
|
||||||
|
WCHAR* localeName, int localeNameLength)
|
||||||
|
: fFontCollection(SkRefComPtr(fontCollection))
|
||||||
|
, fLocaleName(localeNameLength)
|
||||||
|
{
|
||||||
|
memcpy(fLocaleName.get(), localeName, localeNameLength * sizeof(WCHAR));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class SkFontStyleSet_DirectWrite;
|
||||||
|
SkTScopedComPtr<IDWriteFontCollection> fFontCollection;
|
||||||
|
SkSMallocWCHAR fLocaleName;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual int onCountFamilies() SK_OVERRIDE {
|
||||||
|
return fFontCollection->GetFontFamilyCount();
|
||||||
|
}
|
||||||
|
virtual void onGetFamilyName(int index, SkString* familyName) SK_OVERRIDE {
|
||||||
|
SkTScopedComPtr<IDWriteFontFamily> fontFamily;
|
||||||
|
HRVM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requested family.");
|
||||||
|
|
||||||
|
SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
|
||||||
|
HRVM(fontFamily->GetFamilyNames(&familyNames), "Could not get family names.");
|
||||||
|
|
||||||
|
get_locale_string(familyNames.get(), fLocaleName.get(), familyName);
|
||||||
|
}
|
||||||
|
virtual SkFontStyleSet* onCreateStyleSet(int index) SK_OVERRIDE {
|
||||||
|
SkTScopedComPtr<IDWriteFontFamily> fontFamily;
|
||||||
|
HRNM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requested family.");
|
||||||
|
|
||||||
|
return SkNEW_ARGS(SkFontStyleSet_DirectWrite, (this, fontFamily.get()));
|
||||||
|
}
|
||||||
|
virtual SkFontStyleSet* onMatchFamily(const char familyName[]) SK_OVERRIDE {
|
||||||
|
SkSMallocWCHAR dwFamilyName;
|
||||||
|
HRN(cstring_to_wchar(familyName, &dwFamilyName));
|
||||||
|
|
||||||
|
UINT32 index;
|
||||||
|
BOOL exists;
|
||||||
|
HRNM(fFontCollection->FindFamilyName(dwFamilyName.get(), &index, &exists),
|
||||||
|
"Failed while finding family by name.");
|
||||||
|
if (!exists) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this->onCreateStyleSet(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
|
||||||
|
const SkFontStyle& fontstyle) SK_OVERRIDE {
|
||||||
|
SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
|
||||||
|
return sset->matchStyle(fontstyle);
|
||||||
|
}
|
||||||
|
virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
|
||||||
|
const SkFontStyle& fontstyle) SK_OVERRIDE {
|
||||||
|
SkString familyName;
|
||||||
|
SkFontStyleSet_DirectWrite sset(
|
||||||
|
this, ((DWriteFontTypeface*)familyMember)->fDWriteFontFamily.get()
|
||||||
|
);
|
||||||
|
return sset.matchStyle(fontstyle);
|
||||||
|
}
|
||||||
|
virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) SK_OVERRIDE {
|
||||||
|
return create_from_stream(stream);
|
||||||
|
}
|
||||||
|
virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) SK_OVERRIDE {
|
||||||
|
SkAutoTUnref<SkStream> stream(SkNEW_ARGS(SkMemoryStream, (data)));
|
||||||
|
return this->createFromStream(stream, ttcIndex);
|
||||||
|
}
|
||||||
|
virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) SK_OVERRIDE {
|
||||||
|
SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
|
||||||
|
return this->createFromStream(stream, ttcIndex);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void SkFontStyleSet_DirectWrite::getStyle(int index, SkFontStyle* fs, SkString* styleName) {
|
||||||
|
SkTScopedComPtr<IDWriteFont> font;
|
||||||
|
HRVM(fFontFamily->GetFont(index, &font), "Could not get font.");
|
||||||
|
|
||||||
|
SkFontStyle::Slant slant;
|
||||||
|
switch (font->GetStyle()) {
|
||||||
|
case DWRITE_FONT_STYLE_NORMAL:
|
||||||
|
slant = SkFontStyle::kUpright_Slant;
|
||||||
|
break;
|
||||||
|
case DWRITE_FONT_STYLE_OBLIQUE:
|
||||||
|
case DWRITE_FONT_STYLE_ITALIC:
|
||||||
|
slant = SkFontStyle::kItalic_Slant;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
SkASSERT(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
int weight = font->GetWeight();
|
||||||
|
int width = font->GetStretch();
|
||||||
|
|
||||||
|
*fs = SkFontStyle(weight, width, slant);
|
||||||
|
|
||||||
|
SkTScopedComPtr<IDWriteLocalizedStrings> faceNames;
|
||||||
|
if (SUCCEEDED(font->GetFaceNames(&faceNames))) {
|
||||||
|
get_locale_string(faceNames.get(), fFontMgr->fLocaleName.get(), styleName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SkFontMgr* SkFontMgr::Factory() {
|
||||||
|
IDWriteFactory* factory;
|
||||||
|
HRNM(get_dwrite_factory(&factory), "Could not get factory.");
|
||||||
|
|
||||||
|
SkTScopedComPtr<IDWriteFontCollection> sysFontCollection;
|
||||||
|
HRNM(factory->GetSystemFontCollection(&sysFontCollection, FALSE),
|
||||||
|
"Could not get system font collection.");
|
||||||
|
|
||||||
|
WCHAR localeNameStorage[LOCALE_NAME_MAX_LENGTH];
|
||||||
|
WCHAR* localeName = NULL;
|
||||||
|
int localeNameLen = GetUserDefaultLocaleName(localeNameStorage, LOCALE_NAME_MAX_LENGTH);
|
||||||
|
if (localeNameLen) {
|
||||||
|
localeName = localeNameStorage;
|
||||||
|
};
|
||||||
|
|
||||||
|
return SkNEW_ARGS(SkFontMgr_DirectWrite, (sysFontCollection.get(), localeName, localeNameLen));
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,9 @@ static void test_fontiter(skiatest::Reporter* reporter, bool verbose) {
|
||||||
fm->getFamilyName(i, &fname);
|
fm->getFamilyName(i, &fname);
|
||||||
REPORTER_ASSERT(reporter, fname.size() > 0);
|
REPORTER_ASSERT(reporter, fname.size() > 0);
|
||||||
|
|
||||||
|
SkAutoTUnref<SkFontStyleSet> fnset(fm->matchFamily(fname.c_str()));
|
||||||
SkAutoTUnref<SkFontStyleSet> set(fm->createStyleSet(i));
|
SkAutoTUnref<SkFontStyleSet> set(fm->createStyleSet(i));
|
||||||
|
REPORTER_ASSERT(reporter, fnset->count() == set->count());
|
||||||
|
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
SkDebugf("[%2d] %s\n", i, fname.c_str());
|
SkDebugf("[%2d] %s\n", i, fname.c_str());
|
||||||
|
|
Загрузка…
Ссылка в новой задаче