fix reference bugs in font linklist
git-svn-id: http://skia.googlecode.com/svn/trunk@587 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
2e086190e5
commit
930056ed27
@ -30,9 +30,6 @@
|
|||||||
|
|
||||||
static SkMutex gFTMutex;
|
static SkMutex gFTMutex;
|
||||||
|
|
||||||
// these globals are loaded (once) by get_default_font()
|
|
||||||
static LOGFONT gDefaultFont = {0};
|
|
||||||
|
|
||||||
static const uint16_t BUFFERSIZE = (16384 - 32);
|
static const uint16_t BUFFERSIZE = (16384 - 32);
|
||||||
static uint8_t glyphbuf[BUFFERSIZE];
|
static uint8_t glyphbuf[BUFFERSIZE];
|
||||||
|
|
||||||
@ -47,30 +44,6 @@ static inline FIXED SkScalarToFIXED(SkScalar x) {
|
|||||||
return SkFixedToFIXED(SkScalarToFixed(x));
|
return SkFixedToFIXED(SkScalarToFixed(x));
|
||||||
}
|
}
|
||||||
|
|
||||||
// This will generate a unique ID based on the fontname + fontstyle
|
|
||||||
// and also used by upper layer
|
|
||||||
uint32_t FontFaceChecksum(const TCHAR *q, SkTypeface::Style style)
|
|
||||||
{
|
|
||||||
if (!q) return style;
|
|
||||||
|
|
||||||
// From "Performance in Practice of String Hashing Functions"
|
|
||||||
// Ramakrishna & Zobel
|
|
||||||
const uint32_t L = 5;
|
|
||||||
const uint32_t R = 2;
|
|
||||||
|
|
||||||
uint32_t h = 0x12345678;
|
|
||||||
while (*q) {
|
|
||||||
//uint32_t ql = tolower(*q);
|
|
||||||
h ^= ((h << L) + (h >> R) + *q);
|
|
||||||
q ++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// add style
|
|
||||||
h = _rotl(h, 3) ^ style;
|
|
||||||
|
|
||||||
return h;
|
|
||||||
}
|
|
||||||
|
|
||||||
static SkTypeface::Style GetFontStyle(const LOGFONT& lf) {
|
static SkTypeface::Style GetFontStyle(const LOGFONT& lf) {
|
||||||
int style = SkTypeface::kNormal;
|
int style = SkTypeface::kNormal;
|
||||||
if (lf.lfWeight == FW_SEMIBOLD || lf.lfWeight == FW_DEMIBOLD || lf.lfWeight == FW_BOLD)
|
if (lf.lfWeight == FW_SEMIBOLD || lf.lfWeight == FW_DEMIBOLD || lf.lfWeight == FW_BOLD)
|
||||||
@ -81,117 +54,101 @@ static SkTypeface::Style GetFontStyle(const LOGFONT& lf) {
|
|||||||
return (SkTypeface::Style)style;
|
return (SkTypeface::Style)style;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SkFaceRec {
|
|
||||||
SkFaceRec* fNext;
|
|
||||||
uint32_t fRefCnt;
|
|
||||||
uint32_t fFontID; // checksum of fFace
|
|
||||||
LOGFONT fFace;
|
|
||||||
|
|
||||||
SkFaceRec() : fFontID(-1), fRefCnt(0) {
|
|
||||||
memset(&fFace, 0, sizeof(LOGFONT));
|
|
||||||
}
|
|
||||||
~SkFaceRec() {}
|
|
||||||
|
|
||||||
uint32_t ref() {
|
|
||||||
return ++fRefCnt;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Font Face list
|
|
||||||
static SkFaceRec* gFaceRecHead = NULL;
|
|
||||||
|
|
||||||
static SkFaceRec* find_ft_face(uint32_t fontID) {
|
|
||||||
SkFaceRec* rec = gFaceRecHead;
|
|
||||||
while (rec) {
|
|
||||||
if (rec->fFontID == fontID) {
|
|
||||||
return rec;
|
|
||||||
}
|
|
||||||
rec = rec->fNext;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static SkFaceRec* insert_ft_face(const LOGFONT& lf) {
|
|
||||||
// need a const char*
|
|
||||||
uint32_t id = FontFaceChecksum(&(lf.lfFaceName[0]), GetFontStyle(lf));
|
|
||||||
SkFaceRec* rec = find_ft_face(id);
|
|
||||||
if (rec) {
|
|
||||||
return rec; // found?
|
|
||||||
}
|
|
||||||
|
|
||||||
rec = SkNEW(SkFaceRec);
|
|
||||||
rec->fFontID = id;
|
|
||||||
memcpy(&(rec->fFace), &lf, sizeof(LOGFONT));
|
|
||||||
rec->fNext = gFaceRecHead;
|
|
||||||
gFaceRecHead = rec;
|
|
||||||
|
|
||||||
return rec;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void unref_ft_face(uint32_t fontID) {
|
|
||||||
|
|
||||||
SkFaceRec* rec = gFaceRecHead;
|
|
||||||
SkFaceRec* prev = NULL;
|
|
||||||
while (rec) {
|
|
||||||
SkFaceRec* next = rec->fNext;
|
|
||||||
if (rec->fFontID == fontID) {
|
|
||||||
if (--rec->fRefCnt == 0) {
|
|
||||||
if (prev)
|
|
||||||
prev->fNext = next;
|
|
||||||
else
|
|
||||||
gFaceRecHead = next;
|
|
||||||
|
|
||||||
SkDELETE(rec);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
prev = rec;
|
|
||||||
rec = next;
|
|
||||||
}
|
|
||||||
SkASSERT("shouldn't get here, face not in list");
|
|
||||||
}
|
|
||||||
|
|
||||||
// have to do this because SkTypeface::SkTypeface() is protected
|
// have to do this because SkTypeface::SkTypeface() is protected
|
||||||
class FontFaceRec_Typeface : public SkTypeface {
|
class LogFontTypeface : public SkTypeface {
|
||||||
|
private:
|
||||||
|
static SkMutex gMutex;
|
||||||
|
static LogFontTypeface* gHead;
|
||||||
|
static int32_t gCurrId;
|
||||||
|
|
||||||
|
LogFontTypeface* fNext;
|
||||||
|
LOGFONT fLogFont;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
FontFaceRec_Typeface(Style style, uint32_t id) : SkTypeface(style, id) {};
|
LogFontTypeface(Style style, const LOGFONT& logFont) :
|
||||||
|
SkTypeface(style, sk_atomic_inc(&gCurrId)+1), // 0 id is reserved so add 1
|
||||||
|
fLogFont(logFont)
|
||||||
|
{
|
||||||
|
SkAutoMutexAcquire am(gMutex);
|
||||||
|
fNext = gHead;
|
||||||
|
gHead = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
const LOGFONT& logFont() const { return fLogFont; }
|
||||||
|
|
||||||
virtual ~FontFaceRec_Typeface() {};
|
virtual ~LogFontTypeface() {
|
||||||
|
SkAutoMutexAcquire am(gMutex);
|
||||||
|
if (gHead == this) {
|
||||||
|
gHead = fNext;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LogFontTypeface* prev = gHead;
|
||||||
|
SkASSERT(prev);
|
||||||
|
while (prev->fNext != this) {
|
||||||
|
prev = prev->fNext;
|
||||||
|
SkASSERT(prev);
|
||||||
|
}
|
||||||
|
prev->fNext = fNext;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LogFontTypeface* FindById(uint32_t id){
|
||||||
|
SkASSERT(gHead);
|
||||||
|
LogFontTypeface* curr = gHead;
|
||||||
|
while (curr->uniqueID() != id) {
|
||||||
|
curr = curr->fNext;
|
||||||
|
SkASSERT(curr);
|
||||||
|
}
|
||||||
|
return curr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LogFontTypeface* FindByLogFont(const LOGFONT& lf)
|
||||||
|
{
|
||||||
|
LogFontTypeface* curr = gHead;
|
||||||
|
while (curr && memcmp(&curr->fLogFont, &lf, sizeof(LOGFONT))) {
|
||||||
|
curr = curr->fNext;
|
||||||
|
}
|
||||||
|
return curr;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const LOGFONT* get_default_font() {
|
LogFontTypeface* LogFontTypeface::gHead;
|
||||||
|
int32_t LogFontTypeface::gCurrId;
|
||||||
|
SkMutex LogFontTypeface::gMutex;
|
||||||
|
|
||||||
|
static const LOGFONT& get_default_font() {
|
||||||
|
static LOGFONT gDefaultFont;
|
||||||
// don't hardcode on Windows, Win2000, XP, Vista, and international all have different default
|
// don't hardcode on Windows, Win2000, XP, Vista, and international all have different default
|
||||||
// and the user could change too
|
// and the user could change too
|
||||||
|
|
||||||
|
|
||||||
|
// lfMessageFont is garbage on my XP, so skip for now
|
||||||
|
#if 0
|
||||||
if (gDefaultFont.lfFaceName[0] != 0) {
|
if (gDefaultFont.lfFaceName[0] != 0) {
|
||||||
return &gDefaultFont;
|
return gDefaultFont;
|
||||||
}
|
}
|
||||||
|
|
||||||
NONCLIENTMETRICS ncm;
|
NONCLIENTMETRICS ncm;
|
||||||
ncm.cbSize = sizeof(NONCLIENTMETRICS);
|
ncm.cbSize = sizeof(NONCLIENTMETRICS);
|
||||||
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0);
|
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0);
|
||||||
|
|
||||||
// lfMessageFont is garbage on my XP, so skip for now
|
//memcpy(&gDefaultFont, &(ncm.lfMessageFont), sizeof(LOGFONT));
|
||||||
// memcpy(&gDefaultFont, &(ncm.lfMessageFont), sizeof(LOGFONT));
|
#endif
|
||||||
|
|
||||||
return &gDefaultFont;
|
return gDefaultFont;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SkTypeface* CreateTypeface_(const LOGFONT& lf) {
|
static SkTypeface* CreateTypeface_(const LOGFONT& lf) {
|
||||||
|
|
||||||
SkTypeface::Style style = GetFontStyle(lf);
|
LogFontTypeface* ptypeface = LogFontTypeface::FindByLogFont(lf);
|
||||||
FontFaceRec_Typeface* ptypeface = new FontFaceRec_Typeface(style, FontFaceChecksum(lf.lfFaceName, style));
|
|
||||||
|
|
||||||
if (NULL == ptypeface) {
|
if (NULL == ptypeface) {
|
||||||
SkASSERT(false);
|
SkTypeface::Style style = GetFontStyle(lf);
|
||||||
return NULL;
|
ptypeface = new LogFontTypeface(style, lf);
|
||||||
|
} else {
|
||||||
|
ptypeface->ref();
|
||||||
}
|
}
|
||||||
|
|
||||||
SkFaceRec* rec = insert_ft_face(lf);
|
|
||||||
SkASSERT(rec);
|
|
||||||
|
|
||||||
return ptypeface;
|
return ptypeface;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,7 +175,6 @@ protected:
|
|||||||
virtual void generateFontMetrics(SkPaint::FontMetrics* mX, SkPaint::FontMetrics* mY);
|
virtual void generateFontMetrics(SkPaint::FontMetrics* mX, SkPaint::FontMetrics* mY);
|
||||||
//virtual SkDeviceContext getDC() {return ddc;}
|
//virtual SkDeviceContext getDC() {return ddc;}
|
||||||
private:
|
private:
|
||||||
uint32_t fFontID;
|
|
||||||
LOGFONT lf;
|
LOGFONT lf;
|
||||||
MAT2 mat22;
|
MAT2 mat22;
|
||||||
HDC ddc;
|
HDC ddc;
|
||||||
@ -229,16 +185,7 @@ private:
|
|||||||
SkScalerContext_Windows::SkScalerContext_Windows(const SkDescriptor* desc) : SkScalerContext(desc), ddc(0), font(0), savefont(0) {
|
SkScalerContext_Windows::SkScalerContext_Windows(const SkDescriptor* desc) : SkScalerContext(desc), ddc(0), font(0), savefont(0) {
|
||||||
SkAutoMutexAcquire ac(gFTMutex);
|
SkAutoMutexAcquire ac(gFTMutex);
|
||||||
|
|
||||||
fFontID = fRec.fFontID;
|
lf = LogFontTypeface::FindById(fRec.fFontID)->logFont();
|
||||||
SkFaceRec* rec = find_ft_face(fRec.fFontID);
|
|
||||||
if (rec) {
|
|
||||||
rec->ref();
|
|
||||||
memcpy(&lf, &(rec->fFace), sizeof(LOGFONT));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
SkASSERT(false);
|
|
||||||
memcpy(&lf, &gDefaultFont, sizeof(LOGFONT));
|
|
||||||
}
|
|
||||||
|
|
||||||
mat22.eM11 = SkScalarToFIXED(fRec.fPost2x2[0][0]);
|
mat22.eM11 = SkScalarToFIXED(fRec.fPost2x2[0][0]);
|
||||||
mat22.eM12 = SkScalarToFIXED(-fRec.fPost2x2[0][1]);
|
mat22.eM12 = SkScalarToFIXED(-fRec.fPost2x2[0][1]);
|
||||||
@ -248,16 +195,15 @@ SkScalerContext_Windows::SkScalerContext_Windows(const SkDescriptor* desc) : SkS
|
|||||||
ddc = ::CreateCompatibleDC(NULL);
|
ddc = ::CreateCompatibleDC(NULL);
|
||||||
SetBkMode(ddc, TRANSPARENT);
|
SetBkMode(ddc, TRANSPARENT);
|
||||||
|
|
||||||
// Perform the dpi adjustment.
|
// Scaling by the DPI is inconsistent with how Skia draws elsewhere
|
||||||
SkScalar height = -(fRec.fTextSize * GetDeviceCaps(ddc, LOGPIXELSY) / 72);
|
//SkScalar height = -(fRec.fTextSize * GetDeviceCaps(ddc, LOGPIXELSY) / 72);
|
||||||
|
SkScalar height = -fRec.fTextSize;
|
||||||
lf.lfHeight = SkScalarRound(height);
|
lf.lfHeight = SkScalarRound(height);
|
||||||
font = CreateFontIndirect(&lf);
|
font = CreateFontIndirect(&lf);
|
||||||
savefont = (HFONT)SelectObject(ddc, font);
|
savefont = (HFONT)SelectObject(ddc, font);
|
||||||
}
|
}
|
||||||
|
|
||||||
SkScalerContext_Windows::~SkScalerContext_Windows() {
|
SkScalerContext_Windows::~SkScalerContext_Windows() {
|
||||||
unref_ft_face(fFontID);
|
|
||||||
|
|
||||||
if (ddc) {
|
if (ddc) {
|
||||||
::SelectObject(ddc, savefont);
|
::SelectObject(ddc, savefont);
|
||||||
::DeleteDC(ddc);
|
::DeleteDC(ddc);
|
||||||
@ -520,9 +466,8 @@ SkTypeface* SkFontHost::Deserialize(SkStream* stream) {
|
|||||||
SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
|
SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
|
||||||
|
|
||||||
//Should not be used on Windows, keep linker happy
|
//Should not be used on Windows, keep linker happy
|
||||||
SkASSERT(false);
|
SkASSERT(false);
|
||||||
get_default_font();
|
return CreateTypeface_(get_default_font());
|
||||||
return CreateTypeface_(gDefaultFont);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SkScalerContext* SkFontHost::CreateScalerContext(const SkDescriptor* desc) {
|
SkScalerContext* SkFontHost::CreateScalerContext(const SkDescriptor* desc) {
|
||||||
@ -543,6 +488,7 @@ SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
|
|||||||
const void* data, size_t bytelength,
|
const void* data, size_t bytelength,
|
||||||
SkTypeface::Style style) {
|
SkTypeface::Style style) {
|
||||||
|
|
||||||
|
static SkTypeface* gDefaultTypeface;
|
||||||
SkAutoMutexAcquire ac(gFTMutex);
|
SkAutoMutexAcquire ac(gFTMutex);
|
||||||
|
|
||||||
#ifndef CAN_USE_LOGFONT_NAME
|
#ifndef CAN_USE_LOGFONT_NAME
|
||||||
@ -555,25 +501,31 @@ SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
|
|||||||
|
|
||||||
SkTypeface* tf = NULL;
|
SkTypeface* tf = NULL;
|
||||||
if (NULL == familyFace && NULL == familyName) {
|
if (NULL == familyFace && NULL == familyName) {
|
||||||
LOGFONT lf;
|
LOGFONT lf = get_default_font();
|
||||||
get_default_font();
|
|
||||||
memcpy(&lf, &gDefaultFont, sizeof(LOGFONT));
|
|
||||||
lf.lfWeight = (style & SkTypeface::kBold) != 0 ? FW_BOLD : FW_NORMAL ;
|
lf.lfWeight = (style & SkTypeface::kBold) != 0 ? FW_BOLD : FW_NORMAL ;
|
||||||
lf.lfItalic = ((style & SkTypeface::kItalic) != 0);
|
lf.lfItalic = ((style & SkTypeface::kItalic) != 0);
|
||||||
tf = CreateTypeface_(lf);
|
// hack until we figure out if SkTypeface should cache this itself
|
||||||
|
if (style == SkTypeface::kNormal) {
|
||||||
|
if (NULL == gDefaultTypeface) {
|
||||||
|
gDefaultTypeface = CreateTypeface_(lf);
|
||||||
|
}
|
||||||
|
tf = gDefaultTypeface;
|
||||||
|
tf->ref();
|
||||||
|
} else {
|
||||||
|
tf = CreateTypeface_(lf);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
#ifdef CAN_USE_LOGFONT_NAME
|
#ifdef CAN_USE_LOGFONT_NAME
|
||||||
LOGFONT lf;
|
LOGFONT lf;
|
||||||
if (NULL != familyFace) {
|
if (NULL != familyFace) {
|
||||||
uint32_t id = familyFace->uniqueID();
|
uint32_t id = familyFace->uniqueID();
|
||||||
SkFaceRec* rec = find_ft_face(id);
|
LogFontTypeface* rec = LogFontTypeface::FindById(id);
|
||||||
if (!rec) {
|
if (!rec) {
|
||||||
SkASSERT(false);
|
SkASSERT(false);
|
||||||
get_default_font();
|
lf = get_default_font();
|
||||||
memcpy(&lf, &gDefaultFont, sizeof(LOGFONT));
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
memcpy(&lf, &(rec->fFace), sizeof(LOGFONT));
|
lf = rec->logFont();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -608,9 +560,8 @@ SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NULL == tf) {
|
if (NULL == tf) {
|
||||||
get_default_font();
|
tf = CreateTypeface_(get_default_font());
|
||||||
tf = CreateTypeface_(gDefaultFont);
|
|
||||||
}
|
}
|
||||||
return tf;
|
return tf;
|
||||||
}
|
}
|
||||||
@ -632,7 +583,7 @@ void SkFontHost::GetGammaTables(const uint8_t* tables[2]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
|
SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
|
||||||
SkASSERT(!"SkFontHost::CreateTypefaceFromFile unimplemented");
|
printf("SkFontHost::CreateTypefaceFromFile unimplemented");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user