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:
reed@android.com 2009-06-19 20:35:36 +00:00
parent 5c44d321d0
commit 90e764e3d9

View File

@ -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