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:
bungeman@google.com 2013-05-01 14:21:20 +00:00
Родитель a0eca26ac0
Коммит 7103344b64
6 изменённых файлов: 288 добавлений и 64 удалений

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

@ -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());