diff options
author | brettw@google.com <brettw@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-12-12 21:01:41 +0000 |
---|---|---|
committer | brettw@google.com <brettw@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-12-12 21:01:41 +0000 |
commit | 52e935d04c59135739c3a68fb6e19d313dc6d5ad (patch) | |
tree | 95f7ab178b045bef4456cbf92c6aa7e476becd99 /skia/ports/SkFontHost_win.cpp | |
parent | 30fab79877b4bb067944b74d98346ac9bb6bfc7e (diff) | |
download | chromium_src-52e935d04c59135739c3a68fb6e19d313dc6d5ad.zip chromium_src-52e935d04c59135739c3a68fb6e19d313dc6d5ad.tar.gz chromium_src-52e935d04c59135739c3a68fb6e19d313dc6d5ad.tar.bz2 |
New drop of Skia. This is up to CL 121320.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@6925 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'skia/ports/SkFontHost_win.cpp')
-rw-r--r-- | skia/ports/SkFontHost_win.cpp | 818 |
1 files changed, 556 insertions, 262 deletions
diff --git a/skia/ports/SkFontHost_win.cpp b/skia/ports/SkFontHost_win.cpp index d66297a..4df55c9 100644 --- a/skia/ports/SkFontHost_win.cpp +++ b/skia/ports/SkFontHost_win.cpp @@ -1,12 +1,32 @@ -/* libs/graphics/ports/SkFontHost_win.cpp +/* -** + ** Copyright 2006, The Android Open Source Project -** Copyright 2006, Google Inc. + ** -** + ** Licensed under the Apache License, Version 2.0 (the "License"); -*/ + ** you may not use this file except in compliance with the License. + + ** You may obtain a copy of the License at + + ** + + ** http://www.apache.org/licenses/LICENSE-2.0 + + ** + + ** Unless required by applicable law or agreed to in writing, software + + ** distributed under the License is distributed on an "AS IS" BASIS, + + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + + ** See the License for the specific language governing permissions and + + ** limitations under the License. + + */ @@ -32,11 +52,19 @@ -static SkMutex gFTMutex; +// client3d has to undefine this for now + +#define CAN_USE_LOGFONT_NAME + + +static SkMutex gFTMutex; -static LOGFONT gDefaultFont; + +// these globals are loaded (once) by get_default_font() + +static LOGFONT gDefaultFont = {0}; @@ -46,15 +74,13 @@ static uint8_t glyphbuf[BUFFERSIZE]; -#ifndef SK_FONTKEY +// Give 1MB font cache budget - #define SK_FONTKEY "Windows Font Key" - -#endif +#define FONT_CACHE_MEMORY_BUDGET (1024 * 1024) -inline FIXED SkFixedToFIXED(SkFixed x) { +static inline FIXED SkFixedToFIXED(SkFixed x) { return *(FIXED*)(&x); @@ -62,81 +88,257 @@ inline FIXED SkFixedToFIXED(SkFixed x) { -class FontFaceRec_Typeface : public SkTypeface { +static inline FIXED SkScalarToFIXED(SkScalar x) { + + return SkFixedToFIXED(SkScalarToFixed(x)); + +} -public: -#if 0 - FontFaceRec_Typeface(const LOGFONT& face) : fFace(face) +// This will generate a unique ID based on the fontname + fontstyle - { +// and also used by upper layer - int style = 0; +uint32_t FontFaceChecksum(const TCHAR *q, SkTypeface::Style style) - if (face.lfWeight == FW_SEMIBOLD || face.lfWeight == FW_DEMIBOLD || face.lfWeight == FW_BOLD) +{ + + if (!q) return style; - style |= SkTypeface::kBold; + - if (face.lfItalic) + // From "Performance in Practice of String Hashing Functions" - style |= SkTypeface::kItalic; + // Ramakrishna & Zobel - this->setStyle((SkTypeface::Style)style); + 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 ++; } -#endif + - ~FontFaceRec_Typeface() {}; + // add style + h = _rotl(h, 3) ^ style; + - TCHAR* GetFontName() { return fFace.lfFaceName; } + return h; +} - SkTypeface::Style GetFontStyle() { - int style = SkTypeface::kNormal; +static SkTypeface::Style GetFontStyle(const LOGFONT& lf) { - if (fFace.lfWeight == FW_SEMIBOLD || fFace.lfWeight == FW_DEMIBOLD || fFace.lfWeight == FW_BOLD) + int style = SkTypeface::kNormal; - style |= SkTypeface::kBold; + if (lf.lfWeight == FW_SEMIBOLD || lf.lfWeight == FW_DEMIBOLD || lf.lfWeight == FW_BOLD) - if (fFace.lfItalic) + style |= SkTypeface::kBold; - style |= SkTypeface::kItalic; + if (lf.lfItalic) + style |= SkTypeface::kItalic; + - 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() {} - long GetFontSize() { return fFace.lfHeight; } + + uint32_t ref() { + return ++fRefCnt; - LOGFONT fFace; + } }; +// Font Face list +static SkFaceRec* gFaceRecHead = NULL; -static const LOGFONT* get_default_font() -{ + +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 + +class FontFaceRec_Typeface : public SkTypeface { + +public: + + + + FontFaceRec_Typeface(Style style, uint32_t id) : SkTypeface(style, id) {}; + + + + virtual ~FontFaceRec_Typeface() {}; + +}; + + + +static const LOGFONT* get_default_font() { // don't hardcode on Windows, Win2000, XP, Vista, and international all have different default // and the user could change too + + + if (gDefaultFont.lfFaceName[0] != 0) { + + return &gDefaultFont; + } + + NONCLIENTMETRICS ncm; @@ -144,11 +346,11 @@ static const LOGFONT* get_default_font() SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0); - + memcpy(&gDefaultFont, &(ncm.lfMessageFont), sizeof(LOGFONT)); - + return &gDefaultFont; @@ -156,33 +358,33 @@ static const LOGFONT* get_default_font() -static uint32_t FontFaceChecksum(const LOGFONT& face) - -{ - - uint32_t cs = 0; +static SkTypeface* CreateTypeface_(const LOGFONT& lf) { - uint32_t bytesize = sizeof(LOGFONT); + - bytesize >>= 2; + SkTypeface::Style style = GetFontStyle(lf); - uint32_t *p32 = (uint32_t*)&face; + FontFaceRec_Typeface* ptypeface = new FontFaceRec_Typeface(style, FontFaceChecksum(lf.lfFaceName, style)); + + if (NULL == ptypeface) { - while (bytesize) { + SkASSERT(false); - bytesize --; + return NULL; - cs ^= *p32; + } - p32 ++; + - } + SkFaceRec* rec = insert_ft_face(lf); + SkASSERT(rec); + - return cs; + return ptypeface; } @@ -196,7 +398,7 @@ public: virtual ~SkScalerContext_Windows(); - + protected: @@ -204,6 +406,8 @@ protected: virtual uint16_t generateCharToGlyph(SkUnichar uni); + virtual void generateAdvance(SkGlyph* glyph); + virtual void generateMetrics(SkGlyph* glyph); virtual void generateImage(const SkGlyph& glyph); @@ -212,43 +416,77 @@ protected: virtual void generateLineHeight(SkPoint* ascent, SkPoint* descent); + virtual void generateFontMetrics(SkPaint::FontMetrics* mX, SkPaint::FontMetrics* mY); + //virtual SkDeviceContext getDC() {return ddc;} private: - LOGFONT* plf; + uint32_t fFontID; + + LOGFONT lf; MAT2 mat22; -}; + HDC ddc; + HFONT savefont; + HFONT font; -SkScalerContext_Windows::SkScalerContext_Windows(const SkDescriptor* desc) +}; - : SkScalerContext(desc), plf(NULL) -{ + +SkScalerContext_Windows::SkScalerContext_Windows(const SkDescriptor* desc) : SkScalerContext(desc), ddc(0), font(0), savefont(0) { SkAutoMutexAcquire ac(gFTMutex); + + fFontID = fRec.fFontID; - const LOGFONT** face = (const LOGFONT**)desc->findEntry(kTypeface_SkDescriptorTag, NULL); + SkFaceRec* rec = find_ft_face(fRec.fFontID); - plf = (LOGFONT*)*face; + if (rec) { - SkASSERT(plf); + rec->ref(); - + memcpy(&lf, &(rec->fFace), sizeof(LOGFONT)); - mat22.eM11 = SkFixedToFIXED(fRec.fPost2x2[0][0]); + } + + else { - mat22.eM12 = SkFixedToFIXED(-fRec.fPost2x2[0][1]); + SkASSERT(false); - mat22.eM21 = SkFixedToFIXED(fRec.fPost2x2[1][0]); + memcpy(&lf, &gDefaultFont, sizeof(LOGFONT)); - mat22.eM22 = SkFixedToFIXED(-fRec.fPost2x2[1][1]); + } + + + + mat22.eM11 = SkScalarToFIXED(fRec.fPost2x2[0][0]); + + mat22.eM12 = SkScalarToFIXED(-fRec.fPost2x2[0][1]); + + mat22.eM21 = SkScalarToFIXED(fRec.fPost2x2[1][0]); + + mat22.eM22 = SkScalarToFIXED(-fRec.fPost2x2[1][1]); + + + + ddc = ::CreateCompatibleDC(NULL); + + SetBkMode(ddc, TRANSPARENT); + + + + lf.lfHeight = SkScalarFloor(fRec.fTextSize); + + font = CreateFontIndirect(&lf); + + savefont = (HFONT)SelectObject(ddc, font); } @@ -256,6 +494,26 @@ SkScalerContext_Windows::SkScalerContext_Windows(const SkDescriptor* desc) SkScalerContext_Windows::~SkScalerContext_Windows() { + unref_ft_face(fFontID); + + + + if (ddc) { + + ::SelectObject(ddc, savefont); + + ::DeleteDC(ddc); + + ddc = NULL; + + } + + if (font) { + + ::DeleteObject(font); + + } + } @@ -264,7 +522,7 @@ unsigned SkScalerContext_Windows::generateGlyphCount() const { return 0xFFFF; -// return fFace->num_glyphs; + // return fFace->num_glyphs; } @@ -272,35 +530,37 @@ unsigned SkScalerContext_Windows::generateGlyphCount() const { uint16_t SkScalerContext_Windows::generateCharToGlyph(SkUnichar uni) { + + //uint16_t index = 0; - // let's just use the uni as index on Windows - - return SkToU16(uni); - -} + //GetGlyphIndicesW(ddc, &(uint16_t&)uni, 1, &index, 0); + //return index; + -void SkScalerContext_Windows::generateMetrics(SkGlyph* glyph) { + // let's just use the uni as index on Windows + return SkToU16(uni); +} - HDC ddc = ::CreateCompatibleDC(NULL); - SetBkMode(ddc, TRANSPARENT); +void SkScalerContext_Windows::generateAdvance(SkGlyph* glyph) { + this->generateMetrics(glyph); - SkASSERT(plf); +} - plf->lfHeight = -SkFixedFloor(fRec.fTextSize); +void SkScalerContext_Windows::generateMetrics(SkGlyph* glyph) { - HFONT font = CreateFontIndirect(plf); + - HFONT oldfont = (HFONT)SelectObject(ddc, font); + SkASSERT(ddc); @@ -308,19 +568,23 @@ void SkScalerContext_Windows::generateMetrics(SkGlyph* glyph) { memset(&gm, 0, sizeof(gm)); - + glyph->fRsbDelta = 0; glyph->fLsbDelta = 0; + + + UINT glyphIndexFlag = 0; //glyph->fIsCodePoint ? 0 : 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 // BlackBlox; we need the bigger one in case we need the image. fAdvance is the same. - uint32_t ret = GetGlyphOutlineW(ddc, glyph->f_GlyphID, GGO_GRAY8_BITMAP, &gm, 0, NULL, &mat22); + uint32_t ret = GetGlyphOutlineW(ddc, glyph->getGlyphID(0), GGO_GRAY8_BITMAP | glyphIndexFlag, &gm, 0, NULL, &mat22); @@ -338,63 +602,91 @@ void SkScalerContext_Windows::generateMetrics(SkGlyph* glyph) { glyph->fHeight = gm.gmBlackBoxY; - glyph->fTop = gm.gmptGlyphOrigin.y - gm.gmBlackBoxY; + glyph->fTop = SkToS16(gm.gmptGlyphOrigin.y - gm.gmBlackBoxY); - glyph->fLeft = gm.gmptGlyphOrigin.x; + glyph->fLeft = SkToS16(gm.gmptGlyphOrigin.x); glyph->fAdvanceX = SkIntToFixed(gm.gmCellIncX); glyph->fAdvanceY = -SkIntToFixed(gm.gmCellIncY); + } else { + + glyph->fWidth = 0; + } + +#if 0 - ::SelectObject(ddc, oldfont); + char buf[1024]; - ::DeleteObject(font); + sprintf(buf, "generateMetrics: id:%d, w=%d, h=%d, font:%s, fh:%d\n", glyph->fID, glyph->fWidth, glyph->fHeight, lf.lfFaceName, lf.lfHeight); - ::DeleteDC(ddc); + OutputDebugString(buf); + +#endif } -void SkScalerContext_Windows::generateImage(const SkGlyph& glyph) { +void SkScalerContext_Windows::generateFontMetrics(SkPaint::FontMetrics* mx, SkPaint::FontMetrics* my) { + //SkASSERT(false); + if (mx) - SkAutoMutexAcquire ac(gFTMutex); + memset(mx, 0, sizeof(SkPaint::FontMetrics)); + if (my) + memset(my, 0, sizeof(SkPaint::FontMetrics)); - SkASSERT(plf); + return; +} - HDC ddc = ::CreateCompatibleDC(NULL); - SetBkMode(ddc, TRANSPARENT); +void SkScalerContext_Windows::generateImage(const SkGlyph& glyph) { + + SkAutoMutexAcquire ac(gFTMutex); - plf->lfHeight = -SkFixedFloor(fRec.fTextSize); + + SkASSERT(ddc); + - HFONT font = CreateFontIndirect(plf); + GLYPHMETRICS gm; - HFONT oldfont = (HFONT)SelectObject(ddc, font); + memset(&gm, 0, sizeof(gm)); + + +#if 0 + char buf[1024]; - GLYPHMETRICS gm; + sprintf(buf, "generateImage: id:%d, w=%d, h=%d, font:%s,fh:%d\n", glyph.fID, glyph.fWidth, glyph.fHeight, lf.lfFaceName, lf.lfHeight); - memset(&gm, 0, sizeof(gm)); + OutputDebugString(buf); +#endif + + + uint32_t bytecount = 0; - uint32_t total_size = GetGlyphOutlineW(ddc, glyph.f_GlyphID, GGO_GRAY8_BITMAP, &gm, 0, NULL, &mat22); + UINT glyphIndexFlag = 0; //glyph.fIsCodePoint ? 0 : GGO_GLYPH_INDEX; + + // UINT glyphIndexFlag = GGO_GLYPH_INDEX; + + uint32_t total_size = GetGlyphOutlineW(ddc, glyph.fID, GGO_GRAY8_BITMAP | glyphIndexFlag, &gm, 0, NULL, &mat22); if (GDI_ERROR != total_size && total_size > 0) { @@ -402,25 +694,37 @@ void SkScalerContext_Windows::generateImage(const SkGlyph& glyph) { if (NULL != pBuff) { - total_size = GetGlyphOutlineW(ddc, glyph.f_GlyphID, GGO_GRAY8_BITMAP, &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(glyph.fWidth == gm.gmBlackBoxX); + SkASSERT(glyph.fHeight == gm.gmBlackBoxY); + + uint8_t* dst = (uint8_t*)glyph.fImage; uint32_t pitch = (gm.gmBlackBoxX + 3) & ~0x3; + if (pitch != glyph.rowBytes()) { + + SkASSERT(false); // glyph.fImage has different rowsize!? + } + + for (int32_t y = gm.gmBlackBoxY - 1; y >= 0; y--) { uint8_t* src = pBuff + pitch * y; - + for (uint32_t x = 0; x < gm.gmBlackBoxX; x++) { @@ -440,11 +744,17 @@ void SkScalerContext_Windows::generateImage(const SkGlyph& glyph) { src++; + bytecount++; + } - } + memset(dst, 0, glyph.rowBytes() - glyph.fWidth); + + dst += glyph.rowBytes() - glyph.fWidth; + } + delete[] pBuff; @@ -452,17 +762,11 @@ void SkScalerContext_Windows::generateImage(const SkGlyph& glyph) { } - + SkASSERT(GDI_ERROR != total_size && total_size >= 0); - - - ::SelectObject(ddc, oldfont); - - ::DeleteObject(font); - - ::DeleteDC(ddc); + } @@ -470,91 +774,85 @@ void SkScalerContext_Windows::generateImage(const SkGlyph& glyph) { void SkScalerContext_Windows::generatePath(const SkGlyph& glyph, SkPath* path) { - + SkAutoMutexAcquire ac(gFTMutex); - + SkASSERT(&glyph && path); + SkASSERT(ddc); - - SkASSERT(plf); - - + path->reset(); + +#if 0 - HDC ddc = ::CreateCompatibleDC(NULL); - - SetBkMode(ddc, TRANSPARENT); - - - - plf->lfHeight = -SkFixedFloor(fRec.fTextSize); - - + char buf[1024]; - HFONT font = CreateFontIndirect(plf); + sprintf(buf, "generatePath: id:%d, w=%d, h=%d, font:%s,fh:%d\n", glyph.fID, glyph.fWidth, glyph.fHeight, lf.lfFaceName, lf.lfHeight); - HFONT oldfont = (HFONT)SelectObject(ddc, font); + OutputDebugString(buf); +#endif + GLYPHMETRICS gm; + 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.f_GlyphID, GGO_NATIVE, &gm, BUFFERSIZE, glyphbuf, &mat22); - - + if (GDI_ERROR != total_size) { - + const uint8_t* cur_glyph = glyphbuf; const uint8_t* end_glyph = glyphbuf + total_size; - + while(cur_glyph < end_glyph) { const TTPOLYGONHEADER* th = (TTPOLYGONHEADER*)cur_glyph; - + const uint8_t* end_poly = cur_glyph + th->cb; const uint8_t* cur_poly = cur_glyph + sizeof(TTPOLYGONHEADER); - + - path->moveTo(*(SkFixed*)(&th->pfxStart.x), *(SkFixed*)(&th->pfxStart.y)); + path->moveTo(SkFixedToScalar(*(SkFixed*)(&th->pfxStart.x)), SkFixedToScalar(*(SkFixed*)(&th->pfxStart.y))); - + while(cur_poly < end_poly) { const TTPOLYCURVE* pc = (const TTPOLYCURVE*)cur_poly; - + if (pc->wType == TT_PRIM_LINE) { for (uint16_t i = 0; i < pc->cpfx; i++) { - path->lineTo(*(SkFixed*)(&pc->apfx[i].x), *(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) { @@ -564,7 +862,7 @@ void SkScalerContext_Windows::generatePath(const SkGlyph& glyph, SkPath* path) { POINTFX pnt_c = pc->apfx[u+1]; - + if (u < pc->cpfx - 2) { // If not on last spline, compute C @@ -574,9 +872,9 @@ void SkScalerContext_Windows::generatePath(const SkGlyph& glyph, SkPath* path) { } + - - path->quadTo(*(SkFixed*)(&pnt_b.x), *(SkFixed*)(&pnt_b.y), *(SkFixed*)(&pnt_c.x), *(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))); } @@ -588,6 +886,8 @@ void SkScalerContext_Windows::generatePath(const SkGlyph& glyph, SkPath* path) { cur_glyph += th->cb; + path->close(); + } } @@ -598,17 +898,11 @@ void SkScalerContext_Windows::generatePath(const SkGlyph& glyph, SkPath* path) { } + //char buf[1024]; + //sprintf(buf, "generatePath: count:%d\n", count); - path->close(); - - - - ::SelectObject(ddc, oldfont); - - ::DeleteObject(font); - - ::DeleteDC(ddc); + //OutputDebugString(buf); } @@ -620,33 +914,19 @@ void SkScalerContext_Windows::generatePath(const SkGlyph& glyph, SkPath* path) { void SkScalerContext_Windows::generateLineHeight(SkPoint* ascent, SkPoint* descent) { + + SkASSERT(ddc); - HDC ddc = ::CreateCompatibleDC(NULL); - - SetBkMode(ddc, TRANSPARENT); - - - - SkASSERT(plf); - - plf->lfHeight = -SkFixedFloor(fRec.fTextSize); - - - - HFONT font = CreateFontIndirect(plf); - - HFONT oldfont = (HFONT)SelectObject(ddc, font); - - + OUTLINETEXTMETRIC otm; - + uint32_t ret = GetOutlineTextMetrics(ddc, sizeof(otm), &otm); - + if (sizeof(otm) == ret) { @@ -660,15 +940,7 @@ void SkScalerContext_Windows::generateLineHeight(SkPoint* ascent, SkPoint* desce } - - - ::SelectObject(ddc, oldfont); - - ::DeleteObject(font); - - ::DeleteDC(ddc); - - + return; @@ -676,213 +948,237 @@ void SkScalerContext_Windows::generateLineHeight(SkPoint* ascent, SkPoint* desce -SkTypeface* SkFontHost::CreateTypeface( const SkTypeface* familyFace, const char familyName[], SkTypeface::Style style) { - - - - FontFaceRec_Typeface* ptypeface = new FontFaceRec_Typeface; +void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) { + SkASSERT(!"SkFontHost::Serialize unimplemented"); +} - if (NULL == ptypeface) { - SkASSERT(false); - return NULL; +SkTypeface* SkFontHost::Deserialize(SkStream* stream) { - } + SkASSERT(!"SkFontHost::Deserialize unimplemented"); + return NULL; +} - memset(&ptypeface->fFace, 0, sizeof(LOGFONT)); +SkTypeface* SkFontHost::CreateTypeface(SkStream* stream) { - // default + - ptypeface->fFace.lfHeight = -11; // default + //Should not be used on Windows, keep linker happy - ptypeface->fFace.lfWeight = (style & SkTypeface::kBold) != 0 ? FW_BOLD : FW_NORMAL ; + SkASSERT(false); - ptypeface->fFace.lfItalic = ((style & SkTypeface::kItalic) != 0); + get_default_font(); - ptypeface->fFace.lfQuality = PROOF_QUALITY; + return CreateTypeface_(gDefaultFont); +} - _tcscpy(ptypeface->fFace.lfFaceName, familyName); +SkScalerContext* SkFontHost::CreateScalerContext(const SkDescriptor* desc) { + return SkNEW_ARGS(SkScalerContext_Windows, (desc)); +} - return ptypeface; -} +SkScalerContext* SkFontHost::CreateFallbackScalerContext(const SkScalerContext::Rec& rec) { + get_default_font(); + -uint32_t SkFontHost::FlattenTypeface(const SkTypeface* tface, void* buffer) { + SkAutoDescriptor ad(sizeof(rec) + sizeof(gDefaultFont) + SkDescriptor::ComputeOverhead(2)); - const LOGFONT* face; + SkDescriptor* desc = ad.getDesc(); - if (tface) + desc->init(); - face = &((const FontFaceRec_Typeface*)tface)->fFace; + SkScalerContext::Rec* newRec = - else + (SkScalerContext::Rec*)desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec); - face = get_default_font(); + + get_default_font(); + CreateTypeface_(gDefaultFont); - size_t size = sizeof(face); + newRec->fFontID = FontFaceChecksum(gDefaultFont.lfFaceName, GetFontStyle(gDefaultFont)); + desc->computeChecksum(); + - size += sizeof(uint32_t); + return SkFontHost::CreateScalerContext(desc); +} - if (buffer) { - uint8_t* buf = (uint8_t*)buffer; +/** Return the closest matching typeface given either an existing family - memcpy(buf, &face, sizeof(face)); + (specified by a typeface in that family) or by a familyName, and a - uint32_t cs = FontFaceChecksum(*face); + requested style. + 1) If familyFace is null, use famillyName. + 2) If famillyName is null, use familyFace. - memcpy(buf+sizeof(face), &cs, sizeof(cs)); + 3) If both are null, return the default font that best matches style - } + This MUST not return NULL. + */ - return size; -} +SkTypeface* SkFontHost::FindTypeface(const SkTypeface* familyFace, const char familyName[], SkTypeface::Style style) { + + SkAutoMutexAcquire ac(gFTMutex); -SkScalerContext* SkFontHost::CreateScalerContext(const SkDescriptor* desc) { - return SkNEW_ARGS(SkScalerContext_Windows, (desc)); -} +#ifndef CAN_USE_LOGFONT_NAME + familyName = NULL; + familyFace = NULL; -void SkFontHost::GetDescriptorKeyString(const SkDescriptor* desc, SkString* keyString) { +#endif - const LOGFONT** face = (const LOGFONT**)desc->findEntry(kTypeface_SkDescriptorTag, NULL); - LOGFONT*lf = (LOGFONT*)*face; - keyString->set(SK_FONTKEY); + // clip to legal style bits - if (lf) { + style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic); - keyString->append(lf->lfFaceName); + - } + SkTypeface* tf = NULL; -} + if (NULL == familyFace && NULL == familyName) { + LOGFONT lf; + get_default_font(); -SkScalerContext* SkFontHost::CreateFallbackScalerContext(const SkScalerContext::Rec& rec) { + memcpy(&lf, &gDefaultFont, sizeof(LOGFONT)); - const LOGFONT* face = get_default_font(); + lf.lfWeight = (style & SkTypeface::kBold) != 0 ? FW_BOLD : FW_NORMAL ; + lf.lfItalic = ((style & SkTypeface::kItalic) != 0); + tf = CreateTypeface_(lf); - SkAutoDescriptor ad(sizeof(rec) + sizeof(face) + SkDescriptor::ComputeOverhead(2)); + } else { - SkDescriptor* desc = ad.getDesc(); +#ifdef CAN_USE_LOGFONT_NAME + LOGFONT lf; + if (NULL != familyFace) { - desc->init(); + uint32_t id = familyFace->uniqueID(); - desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec); + SkFaceRec* rec = find_ft_face(id); - desc->addEntry(kTypeface_SkDescriptorTag, sizeof(face), &face); + if (!rec) { - desc->computeChecksum(); + SkASSERT(false); + get_default_font(); + memcpy(&lf, &gDefaultFont, sizeof(LOGFONT)); - return SkFontHost::CreateScalerContext(desc); + } -} + else { + memcpy(&lf, &(rec->fFace), sizeof(LOGFONT)); + } -SkStream* SkFontHost::OpenDescriptorStream(const SkDescriptor* desc, const char keyString[]) { + } - SkASSERT(!"SkFontHost::OpenDescriptorStream unimplemented"); + else { - return NULL; + memset(&lf, 0, sizeof(LOGFONT)); -} + + lf.lfHeight = -11; // default + lf.lfQuality = PROOF_QUALITY; -uint32_t SkFontHost::TypefaceHash(const SkTypeface* face) { + lf.lfCharSet = DEFAULT_CHARSET; - + -// FontFaceRec_Typeface *ptypeface = dynamic_cast<FontFaceRec_Typeface*>(face); + _tcsncpy(lf.lfFaceName, familyName, LF_FACESIZE); - FontFaceRec_Typeface *ptypeface = (FontFaceRec_Typeface*)(face); + lf.lfFaceName[LF_FACESIZE-1] = '\0'; - SkASSERT(ptypeface); + } + + // use the style desired - return FontFaceChecksum(ptypeface->fFace); + lf.lfWeight = (style & SkTypeface::kBold) != 0 ? FW_BOLD : FW_NORMAL ; -} + lf.lfItalic = ((style & SkTypeface::kItalic) != 0); + tf = CreateTypeface_(lf); +#endif -bool SkFontHost::TypefaceEqual(const SkTypeface* facea, const SkTypeface* faceb) { + } - - FontFaceRec_Typeface *ptypefaceA = (FontFaceRec_Typeface*)facea; - SkASSERT(ptypefaceA); + if (NULL == tf) { + get_default_font(); + tf = CreateTypeface_(gDefaultFont); - FontFaceRec_Typeface *ptypefaceB = (FontFaceRec_Typeface*)faceb; + } - SkASSERT(ptypefaceB); + return tf; +} - if (_tcscmp(ptypefaceA->GetFontName(), ptypefaceB->GetFontName())) return false; - if (ptypefaceA->GetFontStyle() != ptypefaceB->GetFontStyle()) return false; +size_t SkFontHost::ShouldPurgeFontCache(size_t sizeAllocatedSoFar) { - if (ptypefaceA->GetFontSize() != ptypefaceB->GetFontSize()) return false; + if (sizeAllocatedSoFar > FONT_CACHE_MEMORY_BUDGET) + return sizeAllocatedSoFar - FONT_CACHE_MEMORY_BUDGET; + else - return true; + return 0; // nothing to do } -int SkFontHost::ComputeGammaFlag(const SkPaint& paint) - -{ +int SkFontHost::ComputeGammaFlag(const SkPaint& paint) { return 0; @@ -890,9 +1186,7 @@ int SkFontHost::ComputeGammaFlag(const SkPaint& paint) -void SkFontHost::GetGammaTables(const uint8_t* tables[2]) - -{ +void SkFontHost::GetGammaTables(const uint8_t* tables[2]) { tables[0] = NULL; // black gamma (e.g. exp=1.4) |