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:
parent
750a24bb3d
commit
f55061fd84
@ -49,11 +49,21 @@ public:
|
|||||||
fTTCIndex == other.fTTCIndex &&
|
fTTCIndex == other.fTTCIndex &&
|
||||||
fString == other.fString;
|
fString == other.fString;
|
||||||
}
|
}
|
||||||
|
bool operator!=(const FontIdentity& other) const {
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t fID;
|
uint32_t fID;
|
||||||
int32_t fTTCIndex;
|
int32_t fTTCIndex;
|
||||||
SkString fString;
|
SkString fString;
|
||||||
SkFontStyle fStyle;
|
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);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -50,6 +50,7 @@ public:
|
|||||||
|
|
||||||
int weight() const { return fUnion.fR.fWeight; }
|
int weight() const { return fUnion.fR.fWeight; }
|
||||||
int width() const { return fUnion.fR.fWidth; }
|
int width() const { return fUnion.fR.fWidth; }
|
||||||
|
Slant slant() const { return (Slant)fUnion.fR.fSlant; }
|
||||||
|
|
||||||
bool isItalic() const {
|
bool isItalic() const {
|
||||||
return kItalic_Slant == fUnion.fR.fSlant;
|
return kItalic_Slant == fUnion.fR.fSlant;
|
||||||
|
@ -13,9 +13,91 @@
|
|||||||
|
|
||||||
#include <fontconfig/fontconfig.h>
|
#include <fontconfig/fontconfig.h>
|
||||||
|
|
||||||
|
#include "SkBuffer.h"
|
||||||
#include "SkFontConfigInterface.h"
|
#include "SkFontConfigInterface.h"
|
||||||
#include "SkStream.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 {
|
class SkFontConfigInterfaceDirect : public SkFontConfigInterface {
|
||||||
public:
|
public:
|
||||||
SkFontConfigInterfaceDirect();
|
SkFontConfigInterfaceDirect();
|
||||||
@ -51,23 +133,6 @@ SkFontConfigInterface* SkFontConfigInterface::GetSingletonDirectInterface() {
|
|||||||
return gDirect;
|
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
|
// Returns the string from the pattern, or NULL
|
||||||
@ -354,7 +419,11 @@ SkTypeface::Style GetFontStyle(FcPattern* font) {
|
|||||||
#define kMaxFontFamilyLength 2048
|
#define kMaxFontFamilyLength 2048
|
||||||
|
|
||||||
SkFontConfigInterfaceDirect::SkFontConfigInterfaceDirect() {
|
SkFontConfigInterfaceDirect::SkFontConfigInterfaceDirect() {
|
||||||
|
SkAutoMutexAcquire ac(mutex_);
|
||||||
|
|
||||||
FcInit();
|
FcInit();
|
||||||
|
|
||||||
|
SkDEBUGCODE(fontconfiginterface_unittest();)
|
||||||
}
|
}
|
||||||
|
|
||||||
SkFontConfigInterfaceDirect::~SkFontConfigInterfaceDirect() {
|
SkFontConfigInterfaceDirect::~SkFontConfigInterfaceDirect() {
|
||||||
@ -490,6 +559,8 @@ static bool find_name(const SkTDArray<const char*>& list, const char* str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SkDataTable* SkFontConfigInterfaceDirect::getFamilyNames() {
|
SkDataTable* SkFontConfigInterfaceDirect::getFamilyNames() {
|
||||||
|
SkAutoMutexAcquire ac(mutex_);
|
||||||
|
|
||||||
FcPattern* pat = FcPatternCreate();
|
FcPattern* pat = FcPatternCreate();
|
||||||
FcObjectSet* os = FcObjectSetBuild (FC_FAMILY, (char *) 0);
|
FcObjectSet* os = FcObjectSetBuild (FC_FAMILY, (char *) 0);
|
||||||
if (NULL == os) {
|
if (NULL == os) {
|
||||||
@ -523,5 +594,130 @@ SkDataTable* SkFontConfigInterfaceDirect::getFamilyNames() {
|
|||||||
bool SkFontConfigInterfaceDirect::matchFamilySet(const char inFamilyName[],
|
bool SkFontConfigInterfaceDirect::matchFamilySet(const char inFamilyName[],
|
||||||
SkString* outFamilyName,
|
SkString* outFamilyName,
|
||||||
SkTArray<FontIdentity>* ids) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user