update to latest api (need a test for this port!)
git-svn-id: http://skia.googlecode.com/svn/trunk@225 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
5c44d321d0
commit
90e764e3d9
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
** Copyright 2006, The Android Open Source Project
|
** Copyright 2006, The Android Open Source Project
|
||||||
**
|
**
|
||||||
** Licensed under the Apache License, Version 2.0 (the "License");
|
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
** you may not use this file except in compliance with the License.
|
** you may not use this file except in compliance with the License.
|
||||||
** You may obtain a copy of the License at
|
** You may obtain a copy of the License at
|
||||||
**
|
**
|
||||||
** http://www.apache.org/licenses/LICENSE-2.0
|
** http://www.apache.org/licenses/LICENSE-2.0
|
||||||
**
|
**
|
||||||
** Unless required by applicable law or agreed to in writing, software
|
** Unless required by applicable law or agreed to in writing, software
|
||||||
** distributed under the License is distributed on an "AS IS" BASIS,
|
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
** See the License for the specific language governing permissions and
|
** See the License for the specific language governing permissions and
|
||||||
** limitations under the License.
|
** limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ static SkMutex gFTMutex;
|
|||||||
static LOGFONT gDefaultFont = {0};
|
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];
|
||||||
|
|
||||||
// Give 1MB font cache budget
|
// Give 1MB font cache budget
|
||||||
#define FONT_CACHE_MEMORY_BUDGET (1024 * 1024)
|
#define FONT_CACHE_MEMORY_BUDGET (1024 * 1024)
|
||||||
@ -52,32 +52,32 @@ static inline FIXED SkScalarToFIXED(SkScalar x) {
|
|||||||
uint32_t FontFaceChecksum(const TCHAR *q, SkTypeface::Style style)
|
uint32_t FontFaceChecksum(const TCHAR *q, SkTypeface::Style style)
|
||||||
{
|
{
|
||||||
if (!q) return style;
|
if (!q) return style;
|
||||||
|
|
||||||
// From "Performance in Practice of String Hashing Functions"
|
// From "Performance in Practice of String Hashing Functions"
|
||||||
// Ramakrishna & Zobel
|
// Ramakrishna & Zobel
|
||||||
const uint32_t L = 5;
|
const uint32_t L = 5;
|
||||||
const uint32_t R = 2;
|
const uint32_t R = 2;
|
||||||
|
|
||||||
uint32_t h = 0x12345678;
|
uint32_t h = 0x12345678;
|
||||||
while (*q) {
|
while (*q) {
|
||||||
//uint32_t ql = tolower(*q);
|
//uint32_t ql = tolower(*q);
|
||||||
h ^= ((h << L) + (h >> R) + *q);
|
h ^= ((h << L) + (h >> R) + *q);
|
||||||
q ++;
|
q ++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// add style
|
// add style
|
||||||
h = _rotl(h, 3) ^ style;
|
h = _rotl(h, 3) ^ style;
|
||||||
|
|
||||||
return h;
|
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)
|
||||||
style |= SkTypeface::kBold;
|
style |= SkTypeface::kBold;
|
||||||
if (lf.lfItalic)
|
if (lf.lfItalic)
|
||||||
style |= SkTypeface::kItalic;
|
style |= SkTypeface::kItalic;
|
||||||
|
|
||||||
return (SkTypeface::Style)style;
|
return (SkTypeface::Style)style;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,12 +86,12 @@ struct SkFaceRec {
|
|||||||
uint32_t fRefCnt;
|
uint32_t fRefCnt;
|
||||||
uint32_t fFontID; // checksum of fFace
|
uint32_t fFontID; // checksum of fFace
|
||||||
LOGFONT fFace;
|
LOGFONT fFace;
|
||||||
|
|
||||||
SkFaceRec() : fFontID(-1), fRefCnt(0) {
|
SkFaceRec() : fFontID(-1), fRefCnt(0) {
|
||||||
memset(&fFace, 0, sizeof(LOGFONT));
|
memset(&fFace, 0, sizeof(LOGFONT));
|
||||||
}
|
}
|
||||||
~SkFaceRec() {}
|
~SkFaceRec() {}
|
||||||
|
|
||||||
uint32_t ref() {
|
uint32_t ref() {
|
||||||
return ++fRefCnt;
|
return ++fRefCnt;
|
||||||
}
|
}
|
||||||
@ -108,7 +108,7 @@ static SkFaceRec* find_ft_face(uint32_t fontID) {
|
|||||||
}
|
}
|
||||||
rec = rec->fNext;
|
rec = rec->fNext;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,18 +119,18 @@ static SkFaceRec* insert_ft_face(const LOGFONT& lf) {
|
|||||||
if (rec) {
|
if (rec) {
|
||||||
return rec; // found?
|
return rec; // found?
|
||||||
}
|
}
|
||||||
|
|
||||||
rec = SkNEW(SkFaceRec);
|
rec = SkNEW(SkFaceRec);
|
||||||
rec->fFontID = id;
|
rec->fFontID = id;
|
||||||
memcpy(&(rec->fFace), &lf, sizeof(LOGFONT));
|
memcpy(&(rec->fFace), &lf, sizeof(LOGFONT));
|
||||||
rec->fNext = gFaceRecHead;
|
rec->fNext = gFaceRecHead;
|
||||||
gFaceRecHead = rec;
|
gFaceRecHead = rec;
|
||||||
|
|
||||||
return rec;
|
return rec;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void unref_ft_face(uint32_t fontID) {
|
static void unref_ft_face(uint32_t fontID) {
|
||||||
|
|
||||||
SkFaceRec* rec = gFaceRecHead;
|
SkFaceRec* rec = gFaceRecHead;
|
||||||
SkFaceRec* prev = NULL;
|
SkFaceRec* prev = NULL;
|
||||||
while (rec) {
|
while (rec) {
|
||||||
@ -141,7 +141,7 @@ static void unref_ft_face(uint32_t fontID) {
|
|||||||
prev->fNext = next;
|
prev->fNext = next;
|
||||||
else
|
else
|
||||||
gFaceRecHead = next;
|
gFaceRecHead = next;
|
||||||
|
|
||||||
SkDELETE(rec);
|
SkDELETE(rec);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -155,50 +155,57 @@ static void unref_ft_face(uint32_t fontID) {
|
|||||||
// have to do this because SkTypeface::SkTypeface() is protected
|
// have to do this because SkTypeface::SkTypeface() is protected
|
||||||
class FontFaceRec_Typeface : public SkTypeface {
|
class FontFaceRec_Typeface : public SkTypeface {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
FontFaceRec_Typeface(Style style, uint32_t id) : SkTypeface(style, id) {};
|
FontFaceRec_Typeface(Style style, uint32_t id) : SkTypeface(style, id) {};
|
||||||
|
|
||||||
virtual ~FontFaceRec_Typeface() {};
|
virtual ~FontFaceRec_Typeface() {};
|
||||||
};
|
};
|
||||||
|
|
||||||
static const LOGFONT* get_default_font() {
|
static const LOGFONT* get_default_font() {
|
||||||
// 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
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
memcpy(&gDefaultFont, &(ncm.lfMessageFont), sizeof(LOGFONT));
|
memcpy(&gDefaultFont, &(ncm.lfMessageFont), sizeof(LOGFONT));
|
||||||
|
|
||||||
return &gDefaultFont;
|
return &gDefaultFont;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SkTypeface* CreateTypeface_(const LOGFONT& lf) {
|
static SkTypeface* CreateTypeface_(const LOGFONT& lf) {
|
||||||
|
|
||||||
SkTypeface::Style style = GetFontStyle(lf);
|
SkTypeface::Style style = GetFontStyle(lf);
|
||||||
FontFaceRec_Typeface* ptypeface = new FontFaceRec_Typeface(style, FontFaceChecksum(lf.lfFaceName, style));
|
FontFaceRec_Typeface* ptypeface = new FontFaceRec_Typeface(style, FontFaceChecksum(lf.lfFaceName, style));
|
||||||
|
|
||||||
if (NULL == ptypeface) {
|
if (NULL == ptypeface) {
|
||||||
SkASSERT(false);
|
SkASSERT(false);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SkFaceRec* rec = insert_ft_face(lf);
|
SkFaceRec* rec = insert_ft_face(lf);
|
||||||
SkASSERT(rec);
|
SkASSERT(rec);
|
||||||
|
|
||||||
return ptypeface;
|
return ptypeface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t SkFontHost::NextLogicalFont(uint32_t fontID) {
|
||||||
|
// Zero means that we don't have any fallback fonts for this fontID.
|
||||||
|
// This function is implemented on Android, but doesn't have much
|
||||||
|
// meaning here.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
class SkScalerContext_Windows : public SkScalerContext {
|
class SkScalerContext_Windows : public SkScalerContext {
|
||||||
public:
|
public:
|
||||||
SkScalerContext_Windows(const SkDescriptor* desc);
|
SkScalerContext_Windows(const SkDescriptor* desc);
|
||||||
virtual ~SkScalerContext_Windows();
|
virtual ~SkScalerContext_Windows();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual unsigned generateGlyphCount() const;
|
virtual unsigned generateGlyphCount() const;
|
||||||
virtual uint16_t generateCharToGlyph(SkUnichar uni);
|
virtual uint16_t generateCharToGlyph(SkUnichar uni);
|
||||||
@ -211,7 +218,7 @@ protected:
|
|||||||
//virtual SkDeviceContext getDC() {return ddc;}
|
//virtual SkDeviceContext getDC() {return ddc;}
|
||||||
private:
|
private:
|
||||||
uint32_t fFontID;
|
uint32_t fFontID;
|
||||||
LOGFONT lf;
|
LOGFONT lf;
|
||||||
MAT2 mat22;
|
MAT2 mat22;
|
||||||
HDC ddc;
|
HDC ddc;
|
||||||
HFONT savefont;
|
HFONT savefont;
|
||||||
@ -220,7 +227,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;
|
fFontID = fRec.fFontID;
|
||||||
SkFaceRec* rec = find_ft_face(fRec.fFontID);
|
SkFaceRec* rec = find_ft_face(fRec.fFontID);
|
||||||
if (rec) {
|
if (rec) {
|
||||||
@ -231,23 +238,25 @@ SkScalerContext_Windows::SkScalerContext_Windows(const SkDescriptor* desc) : SkS
|
|||||||
SkASSERT(false);
|
SkASSERT(false);
|
||||||
memcpy(&lf, &gDefaultFont, sizeof(LOGFONT));
|
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]);
|
||||||
mat22.eM21 = SkScalarToFIXED(fRec.fPost2x2[1][0]);
|
mat22.eM21 = SkScalarToFIXED(-fRec.fPost2x2[1][0]);
|
||||||
mat22.eM22 = SkScalarToFIXED(-fRec.fPost2x2[1][1]);
|
mat22.eM22 = SkScalarToFIXED(-fRec.fPost2x2[1][1]);
|
||||||
|
|
||||||
ddc = ::CreateCompatibleDC(NULL);
|
ddc = ::CreateCompatibleDC(NULL);
|
||||||
SetBkMode(ddc, TRANSPARENT);
|
SetBkMode(ddc, TRANSPARENT);
|
||||||
|
|
||||||
lf.lfHeight = SkScalarFloor(fRec.fTextSize);
|
// Perform the dpi adjustment.
|
||||||
|
LONG lfHeight = -(fRec.fTextSize * GetDeviceCaps(ddc, LOGPIXELSY) / 72);
|
||||||
|
lf.lfHeight = lfHeight;
|
||||||
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);
|
unref_ft_face(fFontID);
|
||||||
|
|
||||||
if (ddc) {
|
if (ddc) {
|
||||||
::SelectObject(ddc, savefont);
|
::SelectObject(ddc, savefont);
|
||||||
::DeleteDC(ddc);
|
::DeleteDC(ddc);
|
||||||
@ -264,11 +273,11 @@ unsigned SkScalerContext_Windows::generateGlyphCount() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint16_t SkScalerContext_Windows::generateCharToGlyph(SkUnichar uni) {
|
uint16_t SkScalerContext_Windows::generateCharToGlyph(SkUnichar uni) {
|
||||||
|
|
||||||
//uint16_t index = 0;
|
//uint16_t index = 0;
|
||||||
//GetGlyphIndicesW(ddc, &(uint16_t&)uni, 1, &index, 0);
|
//GetGlyphIndicesW(ddc, &(uint16_t&)uni, 1, &index, 0);
|
||||||
//return index;
|
//return index;
|
||||||
|
|
||||||
// let's just use the uni as index on Windows
|
// let's just use the uni as index on Windows
|
||||||
return SkToU16(uni);
|
return SkToU16(uni);
|
||||||
}
|
}
|
||||||
@ -278,21 +287,21 @@ void SkScalerContext_Windows::generateAdvance(SkGlyph* glyph) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SkScalerContext_Windows::generateMetrics(SkGlyph* glyph) {
|
void SkScalerContext_Windows::generateMetrics(SkGlyph* glyph) {
|
||||||
|
|
||||||
SkASSERT(ddc);
|
SkASSERT(ddc);
|
||||||
|
|
||||||
GLYPHMETRICS gm;
|
GLYPHMETRICS gm;
|
||||||
memset(&gm, 0, sizeof(gm));
|
memset(&gm, 0, sizeof(gm));
|
||||||
|
|
||||||
glyph->fRsbDelta = 0;
|
glyph->fRsbDelta = 0;
|
||||||
glyph->fLsbDelta = 0;
|
glyph->fLsbDelta = 0;
|
||||||
|
|
||||||
UINT glyphIndexFlag = 0; //glyph->fIsCodePoint ? 0 : GGO_GLYPH_INDEX;
|
UINT glyphIndexFlag = 0; //glyph->fIsCodePoint ? 0 : GGO_GLYPH_INDEX;
|
||||||
// UINT glyphIndexFlag = GGO_GLYPH_INDEX;
|
// UINT glyphIndexFlag = GGO_GLYPH_INDEX;
|
||||||
// Note: need to use GGO_GRAY8_BITMAP instead of GGO_METRICS because GGO_METRICS returns a smaller
|
// Note: need to use GGO_GRAY8_BITMAP instead of GGO_METRICS because GGO_METRICS returns a smaller
|
||||||
// BlackBlox; we need the bigger one in case we need the image. fAdvance is the same.
|
// BlackBlox; we need the bigger one in case we need the image. fAdvance is the same.
|
||||||
uint32_t ret = GetGlyphOutlineW(ddc, glyph->getGlyphID(0), GGO_GRAY8_BITMAP | glyphIndexFlag, &gm, 0, NULL, &mat22);
|
uint32_t ret = GetGlyphOutlineW(ddc, glyph->getGlyphID(0), GGO_GRAY8_BITMAP | glyphIndexFlag, &gm, 0, NULL, &mat22);
|
||||||
|
|
||||||
if (GDI_ERROR != ret) {
|
if (GDI_ERROR != ret) {
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
// for white space, ret is zero and gmBlackBoxX, gmBlackBoxY are 1 incorrectly!
|
// for white space, ret is zero and gmBlackBoxX, gmBlackBoxY are 1 incorrectly!
|
||||||
@ -307,7 +316,7 @@ void SkScalerContext_Windows::generateMetrics(SkGlyph* glyph) {
|
|||||||
} else {
|
} else {
|
||||||
glyph->fWidth = 0;
|
glyph->fWidth = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
sprintf(buf, "generateMetrics: id:%d, w=%d, h=%d, font:%s, fh:%d\n", glyph->fID, glyph->fWidth, glyph->fHeight, lf.lfFaceName, lf.lfHeight);
|
sprintf(buf, "generateMetrics: id:%d, w=%d, h=%d, font:%s, fh:%d\n", glyph->fID, glyph->fWidth, glyph->fHeight, lf.lfFaceName, lf.lfHeight);
|
||||||
@ -316,29 +325,54 @@ void SkScalerContext_Windows::generateMetrics(SkGlyph* glyph) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SkScalerContext_Windows::generateFontMetrics(SkPaint::FontMetrics* mx, SkPaint::FontMetrics* my) {
|
void SkScalerContext_Windows::generateFontMetrics(SkPaint::FontMetrics* mx, SkPaint::FontMetrics* my) {
|
||||||
//SkASSERT(false);
|
// Note: This code was borrowed from generateLineHeight, which has a note
|
||||||
if (mx)
|
// stating that it may be incorrect.
|
||||||
memset(mx, 0, sizeof(SkPaint::FontMetrics));
|
if (!(mx || my))
|
||||||
if (my)
|
return;
|
||||||
memset(my, 0, sizeof(SkPaint::FontMetrics));
|
|
||||||
return;
|
SkASSERT(ddc);
|
||||||
|
|
||||||
|
OUTLINETEXTMETRIC otm;
|
||||||
|
|
||||||
|
uint32_t ret = GetOutlineTextMetrics(ddc, sizeof(otm), &otm);
|
||||||
|
if (sizeof(otm) != ret) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mx) {
|
||||||
|
mx->fTop = -SkIntToScalar(otm.otmTextMetrics.tmAscent); // Actually a long.
|
||||||
|
mx->fAscent = -SkIntToScalar(otm.otmAscent);
|
||||||
|
mx->fDescent = -SkIntToScalar(otm.otmDescent);
|
||||||
|
mx->fBottom = SkIntToScalar(otm.otmTextMetrics.tmDescent); // Long
|
||||||
|
mx->fLeading = SkIntToScalar(otm.otmTextMetrics.tmInternalLeading
|
||||||
|
+ otm.otmTextMetrics.tmExternalLeading); // Long
|
||||||
|
}
|
||||||
|
|
||||||
|
if (my) {
|
||||||
|
my->fTop = -SkIntToScalar(otm.otmTextMetrics.tmAscent); // Actually a long.
|
||||||
|
my->fAscent = -SkIntToScalar(otm.otmAscent);
|
||||||
|
my->fDescent = -SkIntToScalar(otm.otmDescent);
|
||||||
|
my->fBottom = SkIntToScalar(otm.otmTextMetrics.tmDescent); // Long
|
||||||
|
my->fLeading = SkIntToScalar(otm.otmTextMetrics.tmInternalLeading
|
||||||
|
+ otm.otmTextMetrics.tmExternalLeading); // Long
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkScalerContext_Windows::generateImage(const SkGlyph& glyph) {
|
void SkScalerContext_Windows::generateImage(const SkGlyph& glyph) {
|
||||||
|
|
||||||
SkAutoMutexAcquire ac(gFTMutex);
|
SkAutoMutexAcquire ac(gFTMutex);
|
||||||
|
|
||||||
SkASSERT(ddc);
|
SkASSERT(ddc);
|
||||||
|
|
||||||
GLYPHMETRICS gm;
|
GLYPHMETRICS gm;
|
||||||
memset(&gm, 0, sizeof(gm));
|
memset(&gm, 0, sizeof(gm));
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
sprintf(buf, "generateImage: id:%d, w=%d, h=%d, font:%s,fh:%d\n", glyph.fID, glyph.fWidth, glyph.fHeight, lf.lfFaceName, lf.lfHeight);
|
sprintf(buf, "generateImage: id:%d, w=%d, h=%d, font:%s,fh:%d\n", glyph.fID, glyph.fWidth, glyph.fHeight, lf.lfFaceName, lf.lfHeight);
|
||||||
OutputDebugString(buf);
|
OutputDebugString(buf);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint32_t bytecount = 0;
|
uint32_t bytecount = 0;
|
||||||
UINT glyphIndexFlag = 0; //glyph.fIsCodePoint ? 0 : GGO_GLYPH_INDEX;
|
UINT glyphIndexFlag = 0; //glyph.fIsCodePoint ? 0 : GGO_GLYPH_INDEX;
|
||||||
// UINT glyphIndexFlag = GGO_GLYPH_INDEX;
|
// UINT glyphIndexFlag = GGO_GLYPH_INDEX;
|
||||||
@ -347,21 +381,21 @@ void SkScalerContext_Windows::generateImage(const SkGlyph& glyph) {
|
|||||||
uint8_t *pBuff = new uint8_t[total_size];
|
uint8_t *pBuff = new uint8_t[total_size];
|
||||||
if (NULL != pBuff) {
|
if (NULL != pBuff) {
|
||||||
total_size = GetGlyphOutlineW(ddc, glyph.fID, GGO_GRAY8_BITMAP | glyphIndexFlag, &gm, total_size, pBuff, &mat22);
|
total_size = GetGlyphOutlineW(ddc, glyph.fID, GGO_GRAY8_BITMAP | glyphIndexFlag, &gm, total_size, pBuff, &mat22);
|
||||||
|
|
||||||
SkASSERT(total_size != GDI_ERROR);
|
SkASSERT(total_size != GDI_ERROR);
|
||||||
|
|
||||||
SkASSERT(glyph.fWidth == gm.gmBlackBoxX);
|
SkASSERT(glyph.fWidth == gm.gmBlackBoxX);
|
||||||
SkASSERT(glyph.fHeight == gm.gmBlackBoxY);
|
SkASSERT(glyph.fHeight == gm.gmBlackBoxY);
|
||||||
|
|
||||||
uint8_t* dst = (uint8_t*)glyph.fImage;
|
uint8_t* dst = (uint8_t*)glyph.fImage;
|
||||||
uint32_t pitch = (gm.gmBlackBoxX + 3) & ~0x3;
|
uint32_t pitch = (gm.gmBlackBoxX + 3) & ~0x3;
|
||||||
if (pitch != glyph.rowBytes()) {
|
if (pitch != glyph.rowBytes()) {
|
||||||
SkASSERT(false); // glyph.fImage has different rowsize!?
|
SkASSERT(false); // glyph.fImage has different rowsize!?
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int32_t y = gm.gmBlackBoxY - 1; y >= 0; y--) {
|
for (int32_t y = gm.gmBlackBoxY - 1; y >= 0; y--) {
|
||||||
uint8_t* src = pBuff + pitch * y;
|
uint8_t* src = pBuff + pitch * y;
|
||||||
|
|
||||||
for (uint32_t x = 0; x < gm.gmBlackBoxX; x++) {
|
for (uint32_t x = 0; x < gm.gmBlackBoxX; x++) {
|
||||||
if (*src > 63) {
|
if (*src > 63) {
|
||||||
*dst = 0xFF;
|
*dst = 0xFF;
|
||||||
@ -376,66 +410,66 @@ void SkScalerContext_Windows::generateImage(const SkGlyph& glyph) {
|
|||||||
memset(dst, 0, glyph.rowBytes() - glyph.fWidth);
|
memset(dst, 0, glyph.rowBytes() - glyph.fWidth);
|
||||||
dst += glyph.rowBytes() - glyph.fWidth;
|
dst += glyph.rowBytes() - glyph.fWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete[] pBuff;
|
delete[] pBuff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SkASSERT(GDI_ERROR != total_size && total_size >= 0);
|
SkASSERT(GDI_ERROR != total_size && total_size >= 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkScalerContext_Windows::generatePath(const SkGlyph& glyph, SkPath* path) {
|
void SkScalerContext_Windows::generatePath(const SkGlyph& glyph, SkPath* path) {
|
||||||
|
|
||||||
SkAutoMutexAcquire ac(gFTMutex);
|
SkAutoMutexAcquire ac(gFTMutex);
|
||||||
|
|
||||||
SkASSERT(&glyph && path);
|
SkASSERT(&glyph && path);
|
||||||
SkASSERT(ddc);
|
SkASSERT(ddc);
|
||||||
|
|
||||||
path->reset();
|
path->reset();
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
sprintf(buf, "generatePath: id:%d, w=%d, h=%d, font:%s,fh:%d\n", glyph.fID, glyph.fWidth, glyph.fHeight, lf.lfFaceName, lf.lfHeight);
|
sprintf(buf, "generatePath: id:%d, w=%d, h=%d, font:%s,fh:%d\n", glyph.fID, glyph.fWidth, glyph.fHeight, lf.lfFaceName, lf.lfHeight);
|
||||||
OutputDebugString(buf);
|
OutputDebugString(buf);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
GLYPHMETRICS gm;
|
GLYPHMETRICS gm;
|
||||||
UINT glyphIndexFlag = 0; //glyph.fIsCodePoint ? 0 : GGO_GLYPH_INDEX;
|
UINT glyphIndexFlag = 0; //glyph.fIsCodePoint ? 0 : GGO_GLYPH_INDEX;
|
||||||
uint32_t total_size = GetGlyphOutlineW(ddc, glyph.fID, GGO_NATIVE | glyphIndexFlag, &gm, BUFFERSIZE, glyphbuf, &mat22);
|
uint32_t total_size = GetGlyphOutlineW(ddc, glyph.fID, GGO_NATIVE | glyphIndexFlag, &gm, BUFFERSIZE, glyphbuf, &mat22);
|
||||||
|
|
||||||
if (GDI_ERROR != total_size) {
|
if (GDI_ERROR != total_size) {
|
||||||
|
|
||||||
const uint8_t* cur_glyph = glyphbuf;
|
const uint8_t* cur_glyph = glyphbuf;
|
||||||
const uint8_t* end_glyph = glyphbuf + total_size;
|
const uint8_t* end_glyph = glyphbuf + total_size;
|
||||||
|
|
||||||
while(cur_glyph < end_glyph) {
|
while(cur_glyph < end_glyph) {
|
||||||
const TTPOLYGONHEADER* th = (TTPOLYGONHEADER*)cur_glyph;
|
const TTPOLYGONHEADER* th = (TTPOLYGONHEADER*)cur_glyph;
|
||||||
|
|
||||||
const uint8_t* end_poly = cur_glyph + th->cb;
|
const uint8_t* end_poly = cur_glyph + th->cb;
|
||||||
const uint8_t* cur_poly = cur_glyph + sizeof(TTPOLYGONHEADER);
|
const uint8_t* cur_poly = cur_glyph + sizeof(TTPOLYGONHEADER);
|
||||||
|
|
||||||
path->moveTo(SkFixedToScalar(*(SkFixed*)(&th->pfxStart.x)), SkFixedToScalar(*(SkFixed*)(&th->pfxStart.y)));
|
path->moveTo(SkFixedToScalar(*(SkFixed*)(&th->pfxStart.x)), SkFixedToScalar(*(SkFixed*)(&th->pfxStart.y)));
|
||||||
|
|
||||||
while(cur_poly < end_poly) {
|
while(cur_poly < end_poly) {
|
||||||
const TTPOLYCURVE* pc = (const TTPOLYCURVE*)cur_poly;
|
const TTPOLYCURVE* pc = (const TTPOLYCURVE*)cur_poly;
|
||||||
|
|
||||||
if (pc->wType == TT_PRIM_LINE) {
|
if (pc->wType == TT_PRIM_LINE) {
|
||||||
for (uint16_t i = 0; i < pc->cpfx; i++) {
|
for (uint16_t i = 0; i < pc->cpfx; i++) {
|
||||||
path->lineTo(SkFixedToScalar(*(SkFixed*)(&pc->apfx[i].x)), SkFixedToScalar(*(SkFixed*)(&pc->apfx[i].y)));
|
path->lineTo(SkFixedToScalar(*(SkFixed*)(&pc->apfx[i].x)), SkFixedToScalar(*(SkFixed*)(&pc->apfx[i].y)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pc->wType == TT_PRIM_QSPLINE) {
|
if (pc->wType == TT_PRIM_QSPLINE) {
|
||||||
for (uint16_t u = 0; u < pc->cpfx - 1; u++) { // Walk through points in spline
|
for (uint16_t u = 0; u < pc->cpfx - 1; u++) { // Walk through points in spline
|
||||||
POINTFX pnt_b = pc->apfx[u]; // B is always the current point
|
POINTFX pnt_b = pc->apfx[u]; // B is always the current point
|
||||||
POINTFX pnt_c = pc->apfx[u+1];
|
POINTFX pnt_c = pc->apfx[u+1];
|
||||||
|
|
||||||
if (u < pc->cpfx - 2) { // If not on last spline, compute C
|
if (u < pc->cpfx - 2) { // If not on last spline, compute C
|
||||||
pnt_c.x = SkFixedToFIXED(SkFixedAve(*(SkFixed*)(&pnt_b.x), *(SkFixed*)(&pnt_c.x)));
|
pnt_c.x = SkFixedToFIXED(SkFixedAve(*(SkFixed*)(&pnt_b.x), *(SkFixed*)(&pnt_c.x)));
|
||||||
pnt_c.y = SkFixedToFIXED(SkFixedAve(*(SkFixed*)(&pnt_b.y), *(SkFixed*)(&pnt_c.y)));
|
pnt_c.y = SkFixedToFIXED(SkFixedAve(*(SkFixed*)(&pnt_b.y), *(SkFixed*)(&pnt_c.y)));
|
||||||
}
|
}
|
||||||
|
|
||||||
path->quadTo(SkFixedToScalar(*(SkFixed*)(&pnt_b.x)), SkFixedToScalar(*(SkFixed*)(&pnt_b.y)), SkFixedToScalar(*(SkFixed*)(&pnt_c.x)), SkFixedToScalar(*(SkFixed*)(&pnt_c.y)));
|
path->quadTo(SkFixedToScalar(*(SkFixed*)(&pnt_b.x)), SkFixedToScalar(*(SkFixed*)(&pnt_b.y)), SkFixedToScalar(*(SkFixed*)(&pnt_c.x)), SkFixedToScalar(*(SkFixed*)(&pnt_c.y)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -456,20 +490,20 @@ void SkScalerContext_Windows::generatePath(const SkGlyph& glyph, SkPath* path) {
|
|||||||
|
|
||||||
// Note: not sure this is the correct implementation
|
// Note: not sure this is the correct implementation
|
||||||
void SkScalerContext_Windows::generateLineHeight(SkPoint* ascent, SkPoint* descent) {
|
void SkScalerContext_Windows::generateLineHeight(SkPoint* ascent, SkPoint* descent) {
|
||||||
|
|
||||||
SkASSERT(ddc);
|
SkASSERT(ddc);
|
||||||
|
|
||||||
OUTLINETEXTMETRIC otm;
|
OUTLINETEXTMETRIC otm;
|
||||||
|
|
||||||
uint32_t ret = GetOutlineTextMetrics(ddc, sizeof(otm), &otm);
|
uint32_t ret = GetOutlineTextMetrics(ddc, sizeof(otm), &otm);
|
||||||
|
|
||||||
if (sizeof(otm) == ret) {
|
if (sizeof(otm) == ret) {
|
||||||
if (ascent)
|
if (ascent)
|
||||||
ascent->iset(0, otm.otmAscent);
|
ascent->iset(0, otm.otmAscent);
|
||||||
if (descent)
|
if (descent)
|
||||||
descent->iset(0, otm.otmDescent);
|
descent->iset(0, otm.otmDescent);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -483,7 +517,7 @@ 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();
|
get_default_font();
|
||||||
@ -494,24 +528,6 @@ SkScalerContext* SkFontHost::CreateScalerContext(const SkDescriptor* desc) {
|
|||||||
return SkNEW_ARGS(SkScalerContext_Windows, (desc));
|
return SkNEW_ARGS(SkScalerContext_Windows, (desc));
|
||||||
}
|
}
|
||||||
|
|
||||||
SkScalerContext* SkFontHost::CreateFallbackScalerContext(const SkScalerContext::Rec& rec) {
|
|
||||||
get_default_font();
|
|
||||||
|
|
||||||
SkAutoDescriptor ad(sizeof(rec) + sizeof(gDefaultFont) + SkDescriptor::ComputeOverhead(2));
|
|
||||||
SkDescriptor* desc = ad.getDesc();
|
|
||||||
|
|
||||||
desc->init();
|
|
||||||
SkScalerContext::Rec* newRec =
|
|
||||||
(SkScalerContext::Rec*)desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
|
|
||||||
|
|
||||||
get_default_font();
|
|
||||||
CreateTypeface_(gDefaultFont);
|
|
||||||
newRec->fFontID = FontFaceChecksum(gDefaultFont.lfFaceName, GetFontStyle(gDefaultFont));
|
|
||||||
desc->computeChecksum();
|
|
||||||
|
|
||||||
return SkFontHost::CreateScalerContext(desc);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Return the closest matching typeface given either an existing family
|
/** Return the closest matching typeface given either an existing family
|
||||||
(specified by a typeface in that family) or by a familyName, and a
|
(specified by a typeface in that family) or by a familyName, and a
|
||||||
requested style.
|
requested style.
|
||||||
@ -522,8 +538,9 @@ SkScalerContext* SkFontHost::CreateFallbackScalerContext(const SkScalerContext::
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
|
SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
|
||||||
const char familyName[], SkTypeface::Style style) {
|
const char familyName[],
|
||||||
|
SkTypeface::Style style) {
|
||||||
|
|
||||||
SkAutoMutexAcquire ac(gFTMutex);
|
SkAutoMutexAcquire ac(gFTMutex);
|
||||||
|
|
||||||
#ifndef CAN_USE_LOGFONT_NAME
|
#ifndef CAN_USE_LOGFONT_NAME
|
||||||
@ -533,13 +550,13 @@ SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
|
|||||||
|
|
||||||
// clip to legal style bits
|
// clip to legal style bits
|
||||||
style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic);
|
style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic);
|
||||||
|
|
||||||
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));
|
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);
|
tf = CreateTypeface_(lf);
|
||||||
} else {
|
} else {
|
||||||
@ -559,17 +576,31 @@ SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
memset(&lf, 0, sizeof(LOGFONT));
|
memset(&lf, 0, sizeof(LOGFONT));
|
||||||
|
|
||||||
lf.lfHeight = -11; // default
|
lf.lfHeight = -11; // default
|
||||||
lf.lfQuality = PROOF_QUALITY;
|
lf.lfQuality = PROOF_QUALITY;
|
||||||
lf.lfCharSet = DEFAULT_CHARSET;
|
lf.lfCharSet = DEFAULT_CHARSET;
|
||||||
|
|
||||||
_tcsncpy(lf.lfFaceName, familyName, LF_FACESIZE);
|
#ifdef UNICODE
|
||||||
|
// Get the buffer size needed first.
|
||||||
|
size_t str_len = ::MultiByteToWideChar(CP_UTF8, 0, familyName,
|
||||||
|
-1, NULL, 0);
|
||||||
|
// Allocate a buffer (str_len already has terminating null
|
||||||
|
// accounted for).
|
||||||
|
wchar_t *wideFamilyName = new wchar_t[str_len];
|
||||||
|
// Now actually convert the string.
|
||||||
|
::MultiByteToWideChar(CP_UTF8, 0, familyName, -1,
|
||||||
|
wideFamilyName, str_len);
|
||||||
|
::wcsncpy(lf.lfFaceName, wideFamilyName, LF_FACESIZE);
|
||||||
|
delete [] wideFamilyName;
|
||||||
|
#else
|
||||||
|
::strncpy(lf.lfFaceName, familyName, LF_FACESIZE);
|
||||||
|
#endif
|
||||||
lf.lfFaceName[LF_FACESIZE-1] = '\0';
|
lf.lfFaceName[LF_FACESIZE-1] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
// use the style desired
|
// use the style desired
|
||||||
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);
|
tf = CreateTypeface_(lf);
|
||||||
#endif
|
#endif
|
||||||
@ -598,5 +629,9 @@ void SkFontHost::GetGammaTables(const uint8_t* tables[2]) {
|
|||||||
tables[1] = NULL; // white gamma (e.g. exp= 1/1.4)
|
tables[1] = NULL; // white gamma (e.g. exp= 1/1.4)
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // WIN32
|
SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
|
||||||
|
SkASSERT(!"SkFontHost::CreateTypefaceFromFile unimplemented");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // WIN32
|
||||||
|
Loading…
Reference in New Issue
Block a user