зеркало из https://github.com/mozilla/moz-skia.git
fix getFamilyName by calling FcFreeTypeQuery
git-svn-id: http://skia.googlecode.com/svn/trunk@7874 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
Родитель
8d38d516c0
Коммит
ee619a059a
|
@ -347,11 +347,8 @@ bool SkFontConfigInterfaceDirect::match(const char familyName[],
|
|||
SkTypeface::Style style,
|
||||
unsigned* result_filefaceid,
|
||||
SkTypeface::Style* result_style) {
|
||||
if (NULL == familyName) {
|
||||
familyName = "sans-serif";
|
||||
}
|
||||
size_t familyLen = strlen(familyName);
|
||||
if (familyLen > kMaxFontFamilyLength) {
|
||||
std::string familyStr(familyName ? familyName : "");
|
||||
if (familyStr.length() > kMaxFontFamilyLength) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -359,7 +356,7 @@ bool SkFontConfigInterfaceDirect::match(const char familyName[],
|
|||
|
||||
// search our cache
|
||||
{
|
||||
FontMatchKey key = FontMatchKey(familyName, style);
|
||||
FontMatchKey key = FontMatchKey(familyStr, style);
|
||||
const std::map<FontMatchKey, FontMatch>::const_iterator i =
|
||||
font_match_cache_.find(key);
|
||||
if (i != font_match_cache_.end()) {
|
||||
|
@ -371,7 +368,9 @@ bool SkFontConfigInterfaceDirect::match(const char familyName[],
|
|||
|
||||
FcPattern* pattern = FcPatternCreate();
|
||||
|
||||
FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName);
|
||||
if (familyName) {
|
||||
FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName);
|
||||
}
|
||||
FcPatternAddInteger(pattern, FC_WEIGHT,
|
||||
(style & SkTypeface::kBold) ? FC_WEIGHT_BOLD
|
||||
: FC_WEIGHT_NORMAL);
|
||||
|
@ -421,7 +420,7 @@ bool SkFontConfigInterfaceDirect::match(const char familyName[],
|
|||
return false;
|
||||
}
|
||||
|
||||
FcPattern* match = MatchFont(font_set, post_config_family, familyName);
|
||||
FcPattern* match = MatchFont(font_set, post_config_family, familyStr);
|
||||
if (!match) {
|
||||
FcPatternDestroy(pattern);
|
||||
FcFontSetDestroy(font_set);
|
||||
|
@ -467,7 +466,7 @@ bool SkFontConfigInterfaceDirect::match(const char familyName[],
|
|||
FcFontSetDestroy(font_set);
|
||||
|
||||
if (success) {
|
||||
font_match_cache_[FontMatchKey(familyName, style)] = font_match;
|
||||
font_match_cache_[FontMatchKey(familyStr, style)] = font_match;
|
||||
*result_filefaceid = font_match.filefaceid;
|
||||
*result_style = font_match.style;
|
||||
}
|
||||
|
@ -475,11 +474,15 @@ bool SkFontConfigInterfaceDirect::match(const char familyName[],
|
|||
return success;
|
||||
}
|
||||
|
||||
#include <fontconfig/fcfreetype.h>
|
||||
|
||||
bool SkFontConfigInterfaceDirect::getFamilyName(unsigned filefaceid,
|
||||
SkString* result_family) {
|
||||
SkAutoMutexAcquire ac(mutex_);
|
||||
|
||||
#if 0
|
||||
FcPattern* pattern = FcPatternCreate();
|
||||
SkString filename;
|
||||
|
||||
{
|
||||
const std::map<unsigned, std::string>::const_iterator
|
||||
|
@ -489,11 +492,9 @@ bool SkFontConfigInterfaceDirect::getFamilyName(unsigned filefaceid,
|
|||
return false;
|
||||
}
|
||||
int face_index = filefaceid & 0xfu;
|
||||
filename.set(i->second.c_str());
|
||||
FcPatternAddString(pattern, FC_FILE,
|
||||
reinterpret_cast<const FcChar8*>(i->second.c_str()));
|
||||
// face_index is added only when family is empty because it is not
|
||||
// necessary to uniquiely identify a font if both file and
|
||||
// family are given.
|
||||
FcPatternAddInteger(pattern, FC_INDEX, face_index);
|
||||
}
|
||||
|
||||
|
@ -502,67 +503,50 @@ bool SkFontConfigInterfaceDirect::getFamilyName(unsigned filefaceid,
|
|||
FcConfigSubstitute(NULL, pattern, FcMatchPattern);
|
||||
FcDefaultSubstitute(pattern);
|
||||
|
||||
// Font matching:
|
||||
// CSS often specifies a fallback list of families:
|
||||
// font-family: a, b, c, serif;
|
||||
// However, fontconfig will always do its best to find *a* font when asked
|
||||
// for something so we need a way to tell if the match which it has found is
|
||||
// "good enough" for us. Otherwise, we can return NULL which gets piped up
|
||||
// and lets WebKit know to try the next CSS family name. However, fontconfig
|
||||
// configs allow substitutions (mapping "Arial -> Helvetica" etc) and we
|
||||
// wish to support that.
|
||||
//
|
||||
// Thus, if a specific family is requested we set @family_requested. Then we
|
||||
// record two strings: the family name after config processing and the
|
||||
// family name after resolving. If the two are equal, it's a good match.
|
||||
//
|
||||
// So consider the case where a user has mapped Arial to Helvetica in their
|
||||
// config.
|
||||
// requested family: "Arial"
|
||||
// post_config_family: "Helvetica"
|
||||
// post_match_family: "Helvetica"
|
||||
// -> good match
|
||||
//
|
||||
// and for a missing font:
|
||||
// requested family: "Monaco"
|
||||
// post_config_family: "Monaco"
|
||||
// post_match_family: "Times New Roman"
|
||||
// -> BAD match
|
||||
//
|
||||
// However, we special-case fallback fonts; see IsFallbackFontAllowed().
|
||||
FcChar8* post_config_family;
|
||||
FcPatternGetString(pattern, FC_FAMILY, 0, &post_config_family);
|
||||
SkDebugf("--- post_config_family <%s>\n", post_config_family);
|
||||
FcResult result;
|
||||
FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result);
|
||||
if (!font_set) {
|
||||
if (!font_set || font_set->nfont <= 0) {
|
||||
FcPatternDestroy(pattern);
|
||||
return false;
|
||||
}
|
||||
|
||||
FcPattern* match = MatchFont(font_set, post_config_family, (const char*)post_config_family);
|
||||
if (!match) {
|
||||
FcPatternDestroy(pattern);
|
||||
FcFontSetDestroy(font_set);
|
||||
return false;
|
||||
bool found = false;
|
||||
for (int i = 0; i < font_set->nfont; ++i) {
|
||||
FcChar8* file;
|
||||
FcPatternGetString(font_set->fonts[i], FC_FILE, 0, &file);
|
||||
if (filename.equals((const char*)file)) {
|
||||
FcChar8* family;
|
||||
FcPatternGetString(font_set->fonts[i], FC_FAMILY, 0, &family);
|
||||
result_family->set((const char*)family);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FcPatternDestroy(pattern);
|
||||
|
||||
FontMatch font_match;
|
||||
font_match.filefaceid = filefaceid;
|
||||
|
||||
bool success = GetFontProperties(match,
|
||||
&font_match.family,
|
||||
&font_match.style);
|
||||
FcFontSetDestroy(font_set);
|
||||
|
||||
if (success) {
|
||||
SkDebugf("--- font_match.family <%s>\n", font_match.family.c_str());
|
||||
result_family->set(font_match.family.c_str());
|
||||
return found;
|
||||
#else
|
||||
const std::map<unsigned, std::string>::const_iterator
|
||||
i = fileid_to_filename_.find(FileFaceIdToFileId(filefaceid));
|
||||
if (i == fileid_to_filename_.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return success;
|
||||
int face_index = filefaceid & 0xfu;
|
||||
int count;
|
||||
FcPattern* pattern = FcFreeTypeQuery((const FcChar8*)i->second.c_str(),
|
||||
face_index, NULL, &count);
|
||||
if (!pattern || count <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FcChar8* family;
|
||||
FcPatternGetString(pattern, FC_FAMILY, 0, &family);
|
||||
|
||||
result_family->set((const char*)family);
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
SkStream* SkFontConfigInterfaceDirect::openStream(unsigned filefaceid) {
|
||||
|
|
|
@ -219,6 +219,7 @@ void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) {
|
|||
desc.setFamilyName("sans-serif");
|
||||
}
|
||||
|
||||
//SkDebugf("Serialize: <%s>\n", desc.getFamilyName());
|
||||
// would also like other names (see SkFontDescriptor.h)
|
||||
|
||||
desc.serialize(stream);
|
||||
|
@ -229,15 +230,30 @@ void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) {
|
|||
}
|
||||
|
||||
SkTypeface* SkFontHost::Deserialize(SkStream* stream) {
|
||||
SkFontDescriptor desc(stream);
|
||||
SkFontDescriptor descriptor(stream);
|
||||
const char* familyName = descriptor.getFamilyName();
|
||||
const SkTypeface::Style style = descriptor.getStyle();
|
||||
|
||||
// by convention, Serialize will have also written the actual sfnt data.
|
||||
// for now, we just want to skip it.
|
||||
size_t size = stream->readPackedUInt();
|
||||
stream->skip(size);
|
||||
const uint32_t customFontDataLength = stream->readPackedUInt();
|
||||
if (customFontDataLength > 0) {
|
||||
#if 0 // need to support inline data...
|
||||
|
||||
return SkFontHost::CreateTypeface(NULL, desc.getFamilyName(),
|
||||
desc.getStyle());
|
||||
// generate a new stream to store the custom typeface
|
||||
SkMemoryStream* fontStream = new SkMemoryStream(customFontDataLength - 1);
|
||||
stream->read((void*)fontStream->getMemoryBase(), customFontDataLength - 1);
|
||||
|
||||
SkTypeface* face = CreateTypefaceFromStream(fontStream);
|
||||
|
||||
fontStream->unref();
|
||||
return face;
|
||||
#else
|
||||
stream->skip(customFontDataLength);
|
||||
return NULL;
|
||||
#endif
|
||||
} else {
|
||||
//SkDebugf("Deserialize:<%s> %d\n", familyName, style);
|
||||
return SkFontHost::CreateTypeface(NULL, familyName, style);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
|
Загрузка…
Ссылка в новой задаче