check-point for linux fontmgr impl

Review URL: https://codereview.chromium.org/14305007

git-svn-id: http://skia.googlecode.com/svn/trunk@8808 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
reed@google.com 2013-04-22 18:48:45 +00:00
parent 750a24bb3d
commit f55061fd84
3 changed files with 224 additions and 17 deletions

View File

@ -49,11 +49,21 @@ public:
fTTCIndex == other.fTTCIndex &&
fString == other.fString;
}
bool operator!=(const FontIdentity& other) const {
return !(*this == other);
}
uint32_t fID;
int32_t fTTCIndex;
SkString fString;
SkFontStyle fStyle;
// If buffer is NULL, just return the number of bytes that would have
// been written. Will pad contents to a multiple of 4.
size_t writeToMemory(void* buffer = NULL) const;
// Recreate from a flattened buffer, returning the number of bytes read.
size_t readFromMemory(const void* buffer, size_t length);
};
/**

View File

@ -50,6 +50,7 @@ public:
int weight() const { return fUnion.fR.fWeight; }
int width() const { return fUnion.fR.fWidth; }
Slant slant() const { return (Slant)fUnion.fR.fSlant; }
bool isItalic() const {
return kItalic_Slant == fUnion.fR.fSlant;

View File

@ -13,9 +13,91 @@
#include <fontconfig/fontconfig.h>
#include "SkBuffer.h"
#include "SkFontConfigInterface.h"
#include "SkStream.h"
size_t SkFontConfigInterface::FontIdentity::writeToMemory(void* addr) const {
size_t size = sizeof(fID) + sizeof(fTTCIndex);
size += sizeof(int32_t) + sizeof(int32_t) + sizeof(uint8_t); // weight, width, italic
size += sizeof(int32_t) + fString.size(); // store length+data
if (addr) {
SkWBuffer buffer(addr, size);
buffer.write32(fID);
buffer.write32(fTTCIndex);
buffer.write32(fString.size());
buffer.write32(fStyle.weight());
buffer.write32(fStyle.width());
buffer.write8(fStyle.slant());
buffer.write(fString.c_str(), fString.size());
buffer.padToAlign4();
SkASSERT(buffer.pos() == size);
}
return size;
}
size_t SkFontConfigInterface::FontIdentity::readFromMemory(const void* addr,
size_t size) {
SkRBuffer buffer(addr, size);
fID = buffer.readU32();
fTTCIndex = buffer.readU32();
size_t strLen = buffer.readU32();
int weight = buffer.readU32();
int width = buffer.readU32();
SkFontStyle::Slant slant = (SkFontStyle::Slant)buffer.readU8();
fStyle = SkFontStyle(weight, width, slant);
fString.resize(strLen);
buffer.read(fString.writable_str(), strLen);
buffer.skipToAlign4();
return buffer.pos(); // the actual number of bytes read
}
#ifdef SK_DEBUG
static void make_iden(SkFontConfigInterface::FontIdentity* iden) {
iden->fID = 10;
iden->fTTCIndex = 2;
iden->fString.set("Hello world");
iden->fStyle = SkFontStyle(300, 6, SkFontStyle::kItalic_Slant);
}
static void test_writeToMemory(const SkFontConfigInterface::FontIdentity& iden0,
int initValue) {
SkFontConfigInterface::FontIdentity iden1;
size_t size0 = iden0.writeToMemory(NULL);
SkAutoMalloc storage(size0);
memset(storage.get(), initValue, size0);
size_t size1 = iden0.writeToMemory(storage.get());
SkASSERT(size0 == size1);
SkASSERT(iden0 != iden1);
size_t size2 = iden1.readFromMemory(storage.get(), size1);
SkASSERT(size2 == size1);
SkASSERT(iden0 == iden1);
}
static void fontconfiginterface_unittest() {
SkFontConfigInterface::FontIdentity iden0, iden1;
SkASSERT(iden0 == iden1);
make_iden(&iden0);
SkASSERT(iden0 != iden1);
make_iden(&iden1);
SkASSERT(iden0 == iden1);
test_writeToMemory(iden0, 0);
test_writeToMemory(iden0, 0);
}
#endif
class SkFontConfigInterfaceDirect : public SkFontConfigInterface {
public:
SkFontConfigInterfaceDirect();
@ -51,23 +133,6 @@ SkFontConfigInterface* SkFontConfigInterface::GetSingletonDirectInterface() {
return gDirect;
}
#if 0
int SkFontConfigInterface::countFamilies() { return 0; }
int SkFontConfigInterface::getFamilySet(int index, SkString* outFamilyName,
FontIdentity outIdentities[],
int maxCount) {
return 0;
}
int SkFontConfigInterface::matchFamilySet(const char familyName[],
SkString* outFamilyName,
FontIdentity outIdentities[],
int maxCount) {
return 0;
}
#endif
///////////////////////////////////////////////////////////////////////////////
// Returns the string from the pattern, or NULL
@ -354,7 +419,11 @@ SkTypeface::Style GetFontStyle(FcPattern* font) {
#define kMaxFontFamilyLength 2048
SkFontConfigInterfaceDirect::SkFontConfigInterfaceDirect() {
SkAutoMutexAcquire ac(mutex_);
FcInit();
SkDEBUGCODE(fontconfiginterface_unittest();)
}
SkFontConfigInterfaceDirect::~SkFontConfigInterfaceDirect() {
@ -490,6 +559,8 @@ static bool find_name(const SkTDArray<const char*>& list, const char* str) {
}
SkDataTable* SkFontConfigInterfaceDirect::getFamilyNames() {
SkAutoMutexAcquire ac(mutex_);
FcPattern* pat = FcPatternCreate();
FcObjectSet* os = FcObjectSetBuild (FC_FAMILY, (char *) 0);
if (NULL == os) {
@ -523,5 +594,130 @@ SkDataTable* SkFontConfigInterfaceDirect::getFamilyNames() {
bool SkFontConfigInterfaceDirect::matchFamilySet(const char inFamilyName[],
SkString* outFamilyName,
SkTArray<FontIdentity>* ids) {
SkAutoMutexAcquire ac(mutex_);
#if 0
std::string familyStr(familyName ? familyName : "");
if (familyStr.length() > kMaxFontFamilyLength) {
return false;
}
SkAutoMutexAcquire ac(mutex_);
FcPattern* pattern = FcPatternCreate();
if (familyName) {
FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName);
}
FcPatternAddBool(pattern, FC_SCALABLE, FcTrue);
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().
const char* post_config_family = get_name(pattern, FC_FAMILY);
FcResult result;
FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result);
if (!font_set) {
FcPatternDestroy(pattern);
return false;
}
FcPattern* match = MatchFont(font_set, post_config_family, familyStr);
if (!match) {
FcPatternDestroy(pattern);
FcFontSetDestroy(font_set);
return false;
}
FcPatternDestroy(pattern);
// From here out we just extract our results from 'match'
if (FcPatternGetString(match, FC_FAMILY, 0, &post_config_family) != FcResultMatch) {
FcFontSetDestroy(font_set);
return false;
}
FcChar8* c_filename;
if (FcPatternGetString(match, FC_FILE, 0, &c_filename) != FcResultMatch) {
FcFontSetDestroy(font_set);
return false;
}
int face_index;
if (FcPatternGetInteger(match, FC_INDEX, 0, &face_index) != FcResultMatch) {
FcFontSetDestroy(font_set);
return false;
}
FcFontSetDestroy(font_set);
if (outIdentity) {
outIdentity->fTTCIndex = face_index;
outIdentity->fString.set((const char*)c_filename);
}
if (outFamilyName) {
outFamilyName->set((const char*)post_config_family);
}
if (outStyle) {
*outStyle = GetFontStyle(match);
}
return true;
////////////////////
int count;
FcPattern** match = MatchFont(font_set, post_config_family, &count);
if (!match) {
FcPatternDestroy(pattern);
FcFontSetDestroy(font_set);
return NULL;
}
FcPatternDestroy(pattern);
SkTDArray<FcPattern*> trimmedMatches;
for (int i = 0; i < count; ++i) {
const char* justName = find_just_name(get_name(match[i], FC_FILE));
if (!is_lower(*justName)) {
*trimmedMatches.append() = match[i];
}
}
SkFontStyleSet_FC* sset = SkNEW_ARGS(SkFontStyleSet_FC,
(trimmedMatches.begin(),
trimmedMatches.count()));
#endif
return false;
}