Home | History | Annotate | Download | only in ports
      1 /*
      2  ** Copyright 2006, The Android Open Source Project
      3  **
      4  ** Licensed under the Apache License, Version 2.0 (the "License");
      5  ** you may not use this file except in compliance with the License.
      6  ** You may obtain a copy of the License at
      7  **
      8  **     http://www.apache.org/licenses/LICENSE-2.0
      9  **
     10  ** Unless required by applicable law or agreed to in writing, software
     11  ** distributed under the License is distributed on an "AS IS" BASIS,
     12  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  ** See the License for the specific language governing permissions and
     14  ** limitations under the License.
     15  */
     16 
     17 #include "SkString.h"
     18 //#include "SkStream.h"
     19 
     20 #include "SkEndian.h"
     21 #include "SkFontHost.h"
     22 #include "SkDescriptor.h"
     23 #include "SkAdvancedTypefaceMetrics.h"
     24 #include "SkStream.h"
     25 #include "SkThread.h"
     26 #include "SkTypeface_win.h"
     27 #include "SkTypefaceCache.h"
     28 #include "SkUtils.h"
     29 
     30 #ifdef WIN32
     31 #include "windows.h"
     32 #include "tchar.h"
     33 #include "Usp10.h"
     34 
     35 // client3d has to undefine this for now
     36 #define CAN_USE_LOGFONT_NAME
     37 
     38 using namespace skia_advanced_typeface_metrics_utils;
     39 
     40 static const uint16_t BUFFERSIZE = (16384 - 32);
     41 static uint8_t glyphbuf[BUFFERSIZE];
     42 
     43 // Give 1MB font cache budget
     44 #define FONT_CACHE_MEMORY_BUDGET    (1024 * 1024)
     45 
     46 /**
     47  *	Since LOGFONT wants its textsize as an int, and we support fractional sizes,
     48  *  and since we have a cache of LOGFONTs for our tyepfaces, we always set the
     49  *  lfHeight to a canonical size, and then we use the 2x2 matrix to achieve the
     50  *  actual requested size.
     51  */
     52 static const int gCanonicalTextSize = 64;
     53 
     54 static void make_canonical(LOGFONT* lf) {
     55 	lf->lfHeight = -gCanonicalTextSize;
     56     lf->lfQuality = CLEARTYPE_QUALITY;//PROOF_QUALITY;
     57     lf->lfCharSet = DEFAULT_CHARSET;
     58 }
     59 
     60 static SkTypeface::Style getStyle(const LOGFONT& lf) {
     61     unsigned style = 0;
     62     if (lf.lfWeight >= FW_BOLD) {
     63         style |= SkTypeface::kBold;
     64     }
     65     if (lf.lfItalic) {
     66         style |= SkTypeface::kItalic;
     67     }
     68     return (SkTypeface::Style)style;
     69 }
     70 
     71 static void setStyle(LOGFONT* lf, SkTypeface::Style style) {
     72     lf->lfWeight = (style & SkTypeface::kBold) != 0 ? FW_BOLD : FW_NORMAL ;
     73     lf->lfItalic = ((style & SkTypeface::kItalic) != 0);
     74 }
     75 
     76 static inline FIXED SkFixedToFIXED(SkFixed x) {
     77     return *(FIXED*)(&x);
     78 }
     79 
     80 static inline FIXED SkScalarToFIXED(SkScalar x) {
     81     return SkFixedToFIXED(SkScalarToFixed(x));
     82 }
     83 
     84 static unsigned calculateGlyphCount(HDC hdc) {
     85     // The 'maxp' table stores the number of glyphs at offset 4, in 2 bytes.
     86     const DWORD maxpTag =
     87         SkEndian_SwapBE32(SkSetFourByteTag('m', 'a', 'x', 'p'));
     88     uint16_t glyphs;
     89     if (GetFontData(hdc, maxpTag, 4, &glyphs, sizeof(glyphs)) != GDI_ERROR) {
     90         return SkEndian_SwapBE16(glyphs);
     91     }
     92 
     93     // Binary search for glyph count.
     94     static const MAT2 mat2 = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
     95     int32_t max = SK_MaxU16 + 1;
     96     int32_t min = 0;
     97     GLYPHMETRICS gm;
     98     while (min < max) {
     99         int32_t mid = min + ((max - min) / 2);
    100         if (GetGlyphOutlineW(hdc, mid, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0,
    101                              NULL, &mat2) == GDI_ERROR) {
    102             max = mid;
    103         } else {
    104             min = mid + 1;
    105         }
    106     }
    107     SkASSERT(min == max);
    108     return min;
    109 }
    110 
    111 static SkTypeface::Style GetFontStyle(const LOGFONT& lf) {
    112     int style = SkTypeface::kNormal;
    113     if (lf.lfWeight == FW_SEMIBOLD || lf.lfWeight == FW_DEMIBOLD || lf.lfWeight == FW_BOLD)
    114         style |= SkTypeface::kBold;
    115     if (lf.lfItalic)
    116         style |= SkTypeface::kItalic;
    117 
    118     return (SkTypeface::Style)style;
    119 }
    120 
    121 class LogFontTypeface : public SkTypeface {
    122 public:
    123     LogFontTypeface(SkTypeface::Style style, SkFontID fontID, const LOGFONT& lf) :
    124       SkTypeface(style, fontID, false), fLogFont(lf) {}
    125 
    126     LOGFONT fLogFont;
    127 
    128     static LogFontTypeface* Create(const LOGFONT& lf) {
    129         SkTypeface::Style style = GetFontStyle(lf);
    130         SkFontID fontID = SkTypefaceCache::NewFontID();
    131         return new LogFontTypeface(style, fontID, lf);
    132     }
    133 };
    134 
    135 static const LOGFONT& get_default_font() {
    136     static LOGFONT gDefaultFont;
    137     // don't hardcode on Windows, Win2000, XP, Vista, and international all have different default
    138     // and the user could change too
    139 
    140 
    141 //  lfMessageFont is garbage on my XP, so skip for now
    142 #if 0
    143     if (gDefaultFont.lfFaceName[0] != 0) {
    144         return gDefaultFont;
    145     }
    146 
    147     NONCLIENTMETRICS ncm;
    148     ncm.cbSize = sizeof(NONCLIENTMETRICS);
    149     SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0);
    150 
    151     //memcpy(&gDefaultFont, &(ncm.lfMessageFont), sizeof(LOGFONT));
    152 #endif
    153 
    154     return gDefaultFont;
    155 }
    156 
    157 static bool FindByLogFont(SkTypeface* face, SkTypeface::Style requestedStyle, void* ctx) {
    158     LogFontTypeface* lface = reinterpret_cast<LogFontTypeface*>(face);
    159     const LOGFONT* lf = reinterpret_cast<const LOGFONT*>(ctx);
    160 
    161     return getStyle(lface->fLogFont) == requestedStyle &&
    162            !memcmp(&lface->fLogFont, lf, sizeof(LOGFONT));
    163 }
    164 
    165 /**
    166  *  This guy is public. It first searches the cache, and if a match is not found,
    167  *  it creates a new face.
    168  */
    169 SkTypeface* SkCreateTypefaceFromLOGFONT(const LOGFONT& origLF) {
    170     LOGFONT lf = origLF;
    171     make_canonical(&lf);
    172     SkTypeface* face = SkTypefaceCache::FindByProc(FindByLogFont, &lf);
    173     if (face) {
    174         face->ref();
    175     } else {
    176         face = LogFontTypeface::Create(lf);
    177         SkTypefaceCache::Add(face, getStyle(lf));
    178     }
    179     return face;
    180 }
    181 
    182 SkFontID SkFontHost::NextLogicalFont(SkFontID currFontID, SkFontID origFontID) {
    183   // Zero means that we don't have any fallback fonts for this fontID.
    184   // This function is implemented on Android, but doesn't have much
    185   // meaning here.
    186   return 0;
    187 }
    188 
    189 static void GetLogFontByID(SkFontID fontID, LOGFONT* lf) {
    190     LogFontTypeface* face = (LogFontTypeface*)SkTypefaceCache::FindByID(fontID);
    191     if (face) {
    192         *lf = face->fLogFont;
    193     } else {
    194         sk_bzero(lf, sizeof(LOGFONT));
    195     }
    196 }
    197 
    198 // Construct Glyph to Unicode table.
    199 // Unicode code points that require conjugate pairs in utf16 are not
    200 // supported.
    201 // TODO(arthurhsu): Add support for conjugate pairs. It looks like that may
    202 // require parsing the TTF cmap table (platform 4, encoding 12) directly instead
    203 // of calling GetFontUnicodeRange().
    204 static void populate_glyph_to_unicode(HDC fontHdc, const unsigned glyphCount,
    205                                       SkTDArray<SkUnichar>* glyphToUnicode) {
    206     DWORD glyphSetBufferSize = GetFontUnicodeRanges(fontHdc, NULL);
    207     if (!glyphSetBufferSize) {
    208         return;
    209     }
    210 
    211     SkAutoTDeleteArray<BYTE> glyphSetBuffer(new BYTE[glyphSetBufferSize]);
    212     GLYPHSET* glyphSet =
    213         reinterpret_cast<LPGLYPHSET>(glyphSetBuffer.get());
    214     if (GetFontUnicodeRanges(fontHdc, glyphSet) != glyphSetBufferSize) {
    215         return;
    216     }
    217 
    218     glyphToUnicode->setCount(glyphCount);
    219     memset(glyphToUnicode->begin(), 0, glyphCount * sizeof(SkUnichar));
    220     for (DWORD i = 0; i < glyphSet->cRanges; ++i) {
    221         // There is no guarantee that within a Unicode range, the corresponding
    222         // glyph id in a font file are continuous. So, even if we have ranges,
    223         // we can't just use the first and last entry of the range to compute
    224         // result. We need to enumerate them one by one.
    225         int count = glyphSet->ranges[i].cGlyphs;
    226         SkAutoTArray<WCHAR> chars(count + 1);
    227         chars[count] = 0;  // termintate string
    228         SkAutoTArray<WORD> glyph(count);
    229         for (USHORT j = 0; j < count; ++j) {
    230             chars[j] = glyphSet->ranges[i].wcLow + j;
    231         }
    232         GetGlyphIndicesW(fontHdc, chars.get(), count, glyph.get(),
    233                          GGI_MARK_NONEXISTING_GLYPHS);
    234         // If the glyph ID is valid, and the glyph is not mapped, then we will
    235         // fill in the char id into the vector. If the glyph is mapped already,
    236         // skip it.
    237         // TODO(arthurhsu): better improve this. e.g. Get all used char ids from
    238         // font cache, then generate this mapping table from there. It's
    239         // unlikely to have collisions since glyph reuse happens mostly for
    240         // different Unicode pages.
    241         for (USHORT j = 0; j < count; ++j) {
    242             if (glyph[j] != 0xffff && glyph[j] < glyphCount &&
    243                 (*glyphToUnicode)[glyph[j]] == 0) {
    244                 (*glyphToUnicode)[glyph[j]] = chars[j];
    245             }
    246         }
    247     }
    248 }
    249 
    250 //////////////////////////////////////////////////////////////////////////////////////////////
    251 
    252 class SkScalerContext_Windows : public SkScalerContext {
    253 public:
    254     SkScalerContext_Windows(const SkDescriptor* desc);
    255     virtual ~SkScalerContext_Windows();
    256 
    257 protected:
    258     virtual unsigned generateGlyphCount();
    259     virtual uint16_t generateCharToGlyph(SkUnichar uni);
    260     virtual void generateAdvance(SkGlyph* glyph);
    261     virtual void generateMetrics(SkGlyph* glyph);
    262     virtual void generateImage(const SkGlyph& glyph);
    263     virtual void generatePath(const SkGlyph& glyph, SkPath* path);
    264     virtual void generateFontMetrics(SkPaint::FontMetrics* mX, SkPaint::FontMetrics* mY);
    265     //virtual SkDeviceContext getDC() {return ddc;}
    266 private:
    267 	SkScalar	 fScale;	// to get from canonical size to real size
    268     MAT2         fMat22;
    269     XFORM        fXform;
    270     HDC          fDDC;
    271     HFONT        fSavefont;
    272     HFONT        fFont;
    273     SCRIPT_CACHE fSC;
    274     int          fGlyphCount;
    275 
    276     HFONT        fHiResFont;
    277     MAT2         fMat22Identity;
    278     SkMatrix     fHiResMatrix;
    279 };
    280 
    281 static float mul2float(SkScalar a, SkScalar b) {
    282     return SkScalarToFloat(SkScalarMul(a, b));
    283 }
    284 
    285 static FIXED float2FIXED(float x) {
    286     return SkFixedToFIXED(SkFloatToFixed(x));
    287 }
    288 
    289 static SkMutex gFTMutex;
    290 
    291 #define HIRES_TEXTSIZE  2048
    292 #define HIRES_SHIFT     11
    293 static inline SkFixed HiResToFixed(int value) {
    294     return value << (16 - HIRES_SHIFT);
    295 }
    296 
    297 static bool needHiResMetrics(const SkScalar mat[2][2]) {
    298     return mat[1][0] || mat[0][1];
    299 }
    300 
    301 SkScalerContext_Windows::SkScalerContext_Windows(const SkDescriptor* desc)
    302         : SkScalerContext(desc), fDDC(0), fFont(0), fSavefont(0), fSC(0)
    303         , fGlyphCount(-1) {
    304     SkAutoMutexAcquire  ac(gFTMutex);
    305 
    306 	fScale = fRec.fTextSize / gCanonicalTextSize;
    307 
    308     fXform.eM11 = mul2float(fScale, fRec.fPost2x2[0][0]);
    309     fXform.eM12 = mul2float(fScale, fRec.fPost2x2[1][0]);
    310     fXform.eM21 = mul2float(fScale, fRec.fPost2x2[0][1]);
    311     fXform.eM22 = mul2float(fScale, fRec.fPost2x2[1][1]);
    312     fXform.eDx = 0;
    313     fXform.eDy = 0;
    314 
    315     fMat22.eM11 = float2FIXED(fXform.eM11);
    316     fMat22.eM12 = float2FIXED(fXform.eM12);
    317     fMat22.eM21 = float2FIXED(-fXform.eM21);
    318     fMat22.eM22 = float2FIXED(-fXform.eM22);
    319 
    320     fDDC = ::CreateCompatibleDC(NULL);
    321     SetGraphicsMode(fDDC, GM_ADVANCED);
    322     SetBkMode(fDDC, TRANSPARENT);
    323 
    324     // Scaling by the DPI is inconsistent with how Skia draws elsewhere
    325     //SkScalar height = -(fRec.fTextSize * GetDeviceCaps(ddc, LOGPIXELSY) / 72);
    326     LOGFONT lf;
    327     GetLogFontByID(fRec.fFontID, &lf);
    328     lf.lfHeight = -gCanonicalTextSize;
    329     fFont = CreateFontIndirect(&lf);
    330 
    331     // if we're rotated, or want fractional widths, create a hires font
    332     fHiResFont = 0;
    333     if (needHiResMetrics(fRec.fPost2x2) || (fRec.fFlags & kSubpixelPositioning_Flag)) {
    334         lf.lfHeight = -HIRES_TEXTSIZE;
    335         fHiResFont = CreateFontIndirect(&lf);
    336 
    337         fMat22Identity.eM11 = fMat22Identity.eM22 = SkFixedToFIXED(SK_Fixed1);
    338         fMat22Identity.eM12 = fMat22Identity.eM21 = SkFixedToFIXED(0);
    339 
    340         // construct a matrix to go from HIRES logical units to our device units
    341         fRec.getSingleMatrix(&fHiResMatrix);
    342         SkScalar scale = SkScalarInvert(SkIntToScalar(HIRES_TEXTSIZE));
    343         fHiResMatrix.preScale(scale, scale);
    344     }
    345     fSavefont = (HFONT)SelectObject(fDDC, fFont);
    346 }
    347 
    348 SkScalerContext_Windows::~SkScalerContext_Windows() {
    349     if (fDDC) {
    350         ::SelectObject(fDDC, fSavefont);
    351         ::DeleteDC(fDDC);
    352     }
    353     if (fFont) {
    354         ::DeleteObject(fFont);
    355     }
    356     if (fHiResFont) {
    357         ::DeleteObject(fHiResFont);
    358     }
    359     if (fSC) {
    360         ::ScriptFreeCache(&fSC);
    361     }
    362 }
    363 
    364 unsigned SkScalerContext_Windows::generateGlyphCount() {
    365     if (fGlyphCount < 0) {
    366         fGlyphCount = calculateGlyphCount(fDDC);
    367     }
    368     return fGlyphCount;
    369 }
    370 
    371 uint16_t SkScalerContext_Windows::generateCharToGlyph(SkUnichar uni) {
    372     uint16_t index = 0;
    373     WCHAR c[2];
    374     // TODO(ctguil): Support characters that generate more than one glyph.
    375     if (SkUTF16_FromUnichar(uni, (uint16_t*)c) == 1) {
    376         // Type1 fonts fail with uniscribe API. Use GetGlyphIndices for plane 0.
    377         SkAssertResult(GetGlyphIndicesW(fDDC, c, 1, &index, 0));
    378     } else {
    379         // Use uniscribe to detemine glyph index for non-BMP characters.
    380         // Need to add extra item to SCRIPT_ITEM to work around a bug in older
    381         // windows versions. https://bugzilla.mozilla.org/show_bug.cgi?id=366643
    382         SCRIPT_ITEM si[2 + 1];
    383         int items;
    384         SkAssertResult(
    385             SUCCEEDED(ScriptItemize(c, 2, 2, NULL, NULL, si, &items)));
    386 
    387         WORD log[2];
    388         SCRIPT_VISATTR vsa;
    389         int glyphs;
    390         SkAssertResult(SUCCEEDED(ScriptShape(
    391             fDDC, &fSC, c, 2, 1, &si[0].a, &index, log, &vsa, &glyphs)));
    392     }
    393     return index;
    394 }
    395 
    396 void SkScalerContext_Windows::generateAdvance(SkGlyph* glyph) {
    397     this->generateMetrics(glyph);
    398 }
    399 
    400 void SkScalerContext_Windows::generateMetrics(SkGlyph* glyph) {
    401 
    402     SkASSERT(fDDC);
    403 
    404     GLYPHMETRICS gm;
    405     sk_bzero(&gm, sizeof(gm));
    406 
    407     glyph->fRsbDelta = 0;
    408     glyph->fLsbDelta = 0;
    409 
    410     // Note: need to use GGO_GRAY8_BITMAP instead of GGO_METRICS because GGO_METRICS returns a smaller
    411     // BlackBlox; we need the bigger one in case we need the image.  fAdvance is the same.
    412     uint32_t ret = GetGlyphOutlineW(fDDC, glyph->getGlyphID(0), GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX, &gm, 0, NULL, &fMat22);
    413 
    414     if (GDI_ERROR != ret) {
    415         if (ret == 0) {
    416             // for white space, ret is zero and gmBlackBoxX, gmBlackBoxY are 1 incorrectly!
    417             gm.gmBlackBoxX = gm.gmBlackBoxY = 0;
    418         }
    419         glyph->fWidth   = gm.gmBlackBoxX;
    420         glyph->fHeight  = gm.gmBlackBoxY;
    421         glyph->fTop     = SkToS16(gm.gmptGlyphOrigin.y - gm.gmBlackBoxY);
    422         glyph->fLeft    = SkToS16(gm.gmptGlyphOrigin.x);
    423         glyph->fAdvanceX = SkIntToFixed(gm.gmCellIncX);
    424         glyph->fAdvanceY = -SkIntToFixed(gm.gmCellIncY);
    425 
    426         // we outset by 1 in all dimensions, since the lcd image may bleed outside
    427         // of the computed bounds returned by GetGlyphOutline.
    428         // This was deduced by trial and error for small text (e.g. 8pt), so there
    429         // maybe a more precise way to make this adjustment...
    430         if (SkMask::kLCD16_Format == fRec.fMaskFormat) {
    431             glyph->fWidth += 2;
    432             glyph->fHeight += 2;
    433             glyph->fTop -= 1;
    434             glyph->fLeft -= 1;
    435         }
    436 
    437         if (fHiResFont) {
    438             SelectObject(fDDC, fHiResFont);
    439             sk_bzero(&gm, sizeof(gm));
    440             ret = GetGlyphOutlineW(fDDC, glyph->getGlyphID(0), GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, NULL, &fMat22Identity);
    441             if (GDI_ERROR != ret) {
    442                 SkPoint advance;
    443                 fHiResMatrix.mapXY(SkIntToScalar(gm.gmCellIncX), SkIntToScalar(gm.gmCellIncY), &advance);
    444                 glyph->fAdvanceX = SkScalarToFixed(advance.fX);
    445                 glyph->fAdvanceY = SkScalarToFixed(advance.fY);
    446             }
    447             SelectObject(fDDC, fFont);
    448         }
    449     } else {
    450         glyph->fWidth = 0;
    451     }
    452 }
    453 
    454 void SkScalerContext_Windows::generateFontMetrics(SkPaint::FontMetrics* mx, SkPaint::FontMetrics* my) {
    455 // Note: This code was borrowed from generateLineHeight, which has a note
    456 // stating that it may be incorrect.
    457     if (!(mx || my))
    458       return;
    459 
    460     SkASSERT(fDDC);
    461 
    462     OUTLINETEXTMETRIC otm;
    463 
    464     uint32_t ret = GetOutlineTextMetrics(fDDC, sizeof(otm), &otm);
    465     if (sizeof(otm) != ret) {
    466       return;
    467     }
    468 
    469     if (mx) {
    470         mx->fTop = -fScale * otm.otmTextMetrics.tmAscent;
    471 		mx->fAscent = -fScale * otm.otmAscent;
    472 		mx->fDescent = -fScale * otm.otmDescent;
    473 		mx->fBottom = fScale * otm.otmTextMetrics.tmDescent;
    474 		mx->fLeading = fScale * (otm.otmTextMetrics.tmInternalLeading
    475 								 + otm.otmTextMetrics.tmExternalLeading);
    476     }
    477 
    478     if (my) {
    479 		my->fTop = -fScale * otm.otmTextMetrics.tmAscent;
    480 		my->fAscent = -fScale * otm.otmAscent;
    481 		my->fDescent = -fScale * otm.otmDescent;
    482 		my->fBottom = fScale * otm.otmTextMetrics.tmDescent;
    483 		my->fLeading = fScale * (otm.otmTextMetrics.tmInternalLeading
    484 								 + otm.otmTextMetrics.tmExternalLeading);
    485     }
    486 }
    487 
    488 #include "SkColorPriv.h"
    489 
    490 static inline uint16_t rgb_to_lcd16(uint32_t rgb) {
    491     int r = (rgb >> 16) & 0xFF;
    492     int g = (rgb >>  8) & 0xFF;
    493     int b = (rgb >>  0) & 0xFF;
    494 
    495     // invert, since we draw black-on-white, but we want the original
    496     // src mask values.
    497     r = 255 - r;
    498     g = 255 - g;
    499     b = 255 - b;
    500     return SkPackRGB16(SkR32ToR16(r), SkG32ToG16(g), SkB32ToB16(b));
    501 }
    502 
    503 static int alignTo32(int n) {
    504     return (n + 31) & ~31;
    505 }
    506 
    507 struct MyBitmapInfo : public BITMAPINFO {
    508     RGBQUAD fMoreSpaceForColors[1];
    509 };
    510 
    511 void SkScalerContext_Windows::generateImage(const SkGlyph& glyph) {
    512 
    513     SkAutoMutexAcquire  ac(gFTMutex);
    514 
    515     SkASSERT(fDDC);
    516 
    517     const bool isBW = SkMask::kBW_Format == fRec.fMaskFormat;
    518     if ((SkMask::kLCD16_Format == fRec.fMaskFormat) || isBW) {
    519         HDC dc = CreateCompatibleDC(0);
    520         void* bits = 0;
    521         int biWidth = isBW ? alignTo32(glyph.fWidth) : glyph.fWidth;
    522         MyBitmapInfo info;
    523         sk_bzero(&info, sizeof(info));
    524         if (isBW) {
    525             RGBQUAD blackQuad = { 0, 0, 0, 0 };
    526             RGBQUAD whiteQuad = { 0xFF, 0xFF, 0xFF, 0 };
    527             info.bmiColors[0] = blackQuad;
    528             info.bmiColors[1] = whiteQuad;
    529         }
    530         info.bmiHeader.biSize = sizeof(info.bmiHeader);
    531         info.bmiHeader.biWidth = biWidth;
    532         info.bmiHeader.biHeight = glyph.fHeight;
    533         info.bmiHeader.biPlanes = 1;
    534         info.bmiHeader.biBitCount = isBW ? 1 : 32;
    535         info.bmiHeader.biCompression = BI_RGB;
    536         if (isBW) {
    537             info.bmiHeader.biClrUsed = 2;
    538         }
    539         HBITMAP bm = CreateDIBSection(dc, &info, DIB_RGB_COLORS, &bits, 0, 0);
    540         SelectObject(dc, bm);
    541 
    542         // erase to white
    543         size_t srcRB = isBW ? (biWidth >> 3) : (glyph.fWidth << 2);
    544         size_t size = glyph.fHeight * srcRB;
    545         memset(bits, isBW ? 0 : 0xFF, size);
    546 
    547         SetGraphicsMode(dc, GM_ADVANCED);
    548         SetBkMode(dc, TRANSPARENT);
    549         SetTextAlign(dc, TA_LEFT | TA_BASELINE);
    550 
    551         XFORM xform = fXform;
    552         xform.eDx = (float)-glyph.fLeft;
    553         xform.eDy = (float)-glyph.fTop;
    554         SetWorldTransform(dc, &xform);
    555 
    556         HGDIOBJ prevFont = SelectObject(dc, fFont);
    557         COLORREF color = SetTextColor(dc, isBW ? 0xFFFFFF : 0);
    558         SkASSERT(color != CLR_INVALID);
    559         uint16_t glyphID = glyph.getGlyphID();
    560 #if defined(UNICODE)
    561         ExtTextOut(dc, 0, 0, ETO_GLYPH_INDEX, NULL, (LPCWSTR)&glyphID, 1, NULL);
    562 #else
    563         ExtTextOut(dc, 0, 0, ETO_GLYPH_INDEX, NULL, (LPCSTR)&glyphID, 1, NULL);
    564 #endif
    565         GdiFlush();
    566 
    567         // downsample from rgba to rgb565
    568         int width = glyph.fWidth;
    569         size_t dstRB = glyph.rowBytes();
    570         if (isBW) {
    571             const uint8_t* src = (const uint8_t*)bits;
    572             // gdi's bitmap is upside-down, so we reverse dst walking in Y
    573             uint8_t* dst = (uint8_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB);
    574             for (int y = 0; y < glyph.fHeight; y++) {
    575                 memcpy(dst, src, dstRB);
    576                 src += srcRB;
    577                 dst -= dstRB;
    578             }
    579         } else {    // LCD16
    580             const uint32_t* src = (const uint32_t*)bits;
    581             // gdi's bitmap is upside-down, so we reverse dst walking in Y
    582             uint16_t* dst = (uint16_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB);
    583             for (int y = 0; y < glyph.fHeight; y++) {
    584                 for (int i = 0; i < width; i++) {
    585                     dst[i] = rgb_to_lcd16(src[i]);
    586                 }
    587                 src = (const uint32_t*)((const char*)src + srcRB);
    588                 dst = (uint16_t*)((char*)dst - dstRB);
    589             }
    590         }
    591 
    592         DeleteDC(dc);
    593         DeleteObject(bm);
    594         return;
    595     }
    596 
    597     GLYPHMETRICS gm;
    598     memset(&gm, 0, sizeof(gm));
    599     uint32_t bytecount = 0;
    600     uint32_t total_size = GetGlyphOutlineW(fDDC, glyph.fID, GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX, &gm, 0, NULL, &fMat22);
    601     if (GDI_ERROR != total_size && total_size > 0) {
    602         uint8_t *pBuff = new uint8_t[total_size];
    603         if (NULL != pBuff) {
    604             total_size = GetGlyphOutlineW(fDDC, glyph.fID, GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX, &gm, total_size, pBuff, &fMat22);
    605 
    606             SkASSERT(total_size != GDI_ERROR);
    607 
    608             SkASSERT(glyph.fWidth == gm.gmBlackBoxX);
    609             SkASSERT(glyph.fHeight == gm.gmBlackBoxY);
    610 
    611             uint8_t* dst = (uint8_t*)glyph.fImage;
    612             uint32_t pitch = (gm.gmBlackBoxX + 3) & ~0x3;
    613             if (pitch != glyph.rowBytes()) {
    614                 SkASSERT(false); // glyph.fImage has different rowsize!?
    615             }
    616 
    617             for (int32_t y = gm.gmBlackBoxY - 1; y >= 0; y--) {
    618                 uint8_t* src = pBuff + pitch * y;
    619 
    620                 for (uint32_t x = 0; x < gm.gmBlackBoxX; x++) {
    621                     if (*src > 63) {
    622                         *dst = 0xFF;
    623                     }
    624                     else {
    625                         *dst = *src << 2; // scale to 0-255
    626                     }
    627                     dst++;
    628                     src++;
    629                     bytecount++;
    630                 }
    631                 memset(dst, 0, glyph.rowBytes() - glyph.fWidth);
    632                 dst += glyph.rowBytes() - glyph.fWidth;
    633             }
    634 
    635             delete[] pBuff;
    636         }
    637     }
    638 
    639     SkASSERT(GDI_ERROR != total_size && total_size >= 0);
    640 
    641 }
    642 
    643 void SkScalerContext_Windows::generatePath(const SkGlyph& glyph, SkPath* path) {
    644 
    645     SkAutoMutexAcquire  ac(gFTMutex);
    646 
    647     SkASSERT(&glyph && path);
    648     SkASSERT(fDDC);
    649 
    650     path->reset();
    651 
    652 #if 0
    653     char buf[1024];
    654     sprintf(buf, "generatePath: id:%d, w=%d, h=%d, font:%s,fh:%d\n", glyph.fID, glyph.fWidth, glyph.fHeight, lf.lfFaceName, lf.lfHeight);
    655     OutputDebugString(buf);
    656 #endif
    657 
    658     GLYPHMETRICS gm;
    659     uint32_t total_size = GetGlyphOutlineW(fDDC, glyph.fID, GGO_NATIVE | GGO_GLYPH_INDEX, &gm, BUFFERSIZE, glyphbuf, &fMat22);
    660 
    661     if (GDI_ERROR != total_size) {
    662 
    663         const uint8_t* cur_glyph = glyphbuf;
    664         const uint8_t* end_glyph = glyphbuf + total_size;
    665 
    666         while(cur_glyph < end_glyph) {
    667             const TTPOLYGONHEADER* th = (TTPOLYGONHEADER*)cur_glyph;
    668 
    669             const uint8_t* end_poly = cur_glyph + th->cb;
    670             const uint8_t* cur_poly = cur_glyph + sizeof(TTPOLYGONHEADER);
    671 
    672             path->moveTo(SkFixedToScalar(*(SkFixed*)(&th->pfxStart.x)), SkFixedToScalar(*(SkFixed*)(&th->pfxStart.y)));
    673 
    674             while(cur_poly < end_poly) {
    675                 const TTPOLYCURVE* pc = (const TTPOLYCURVE*)cur_poly;
    676 
    677                 if (pc->wType == TT_PRIM_LINE) {
    678                     for (uint16_t i = 0; i < pc->cpfx; i++) {
    679                         path->lineTo(SkFixedToScalar(*(SkFixed*)(&pc->apfx[i].x)), SkFixedToScalar(*(SkFixed*)(&pc->apfx[i].y)));
    680                     }
    681                 }
    682 
    683                 if (pc->wType == TT_PRIM_QSPLINE) {
    684                     for (uint16_t u = 0; u < pc->cpfx - 1; u++) { // Walk through points in spline
    685                         POINTFX pnt_b = pc->apfx[u];    // B is always the current point
    686                         POINTFX pnt_c = pc->apfx[u+1];
    687 
    688                         if (u < pc->cpfx - 2) {          // If not on last spline, compute C
    689                             pnt_c.x = SkFixedToFIXED(SkFixedAve(*(SkFixed*)(&pnt_b.x), *(SkFixed*)(&pnt_c.x)));
    690                             pnt_c.y = SkFixedToFIXED(SkFixedAve(*(SkFixed*)(&pnt_b.y), *(SkFixed*)(&pnt_c.y)));
    691                         }
    692 
    693                         path->quadTo(SkFixedToScalar(*(SkFixed*)(&pnt_b.x)), SkFixedToScalar(*(SkFixed*)(&pnt_b.y)), SkFixedToScalar(*(SkFixed*)(&pnt_c.x)), SkFixedToScalar(*(SkFixed*)(&pnt_c.y)));
    694                     }
    695                 }
    696                 cur_poly += sizeof(uint16_t) * 2 + sizeof(POINTFX) * pc->cpfx;
    697             }
    698             cur_glyph += th->cb;
    699             path->close();
    700         }
    701     }
    702     else {
    703         SkASSERT(false);
    704     }
    705     //char buf[1024];
    706     //sprintf(buf, "generatePath: count:%d\n", count);
    707     //OutputDebugString(buf);
    708 }
    709 
    710 void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) {
    711     SkASSERT(!"SkFontHost::Serialize unimplemented");
    712 }
    713 
    714 SkTypeface* SkFontHost::Deserialize(SkStream* stream) {
    715     SkASSERT(!"SkFontHost::Deserialize unimplemented");
    716     return NULL;
    717 }
    718 
    719 static bool getWidthAdvance(HDC hdc, int gId, int16_t* advance) {
    720     // Initialize the MAT2 structure to the identify transformation matrix.
    721     static const MAT2 mat2 = {SkScalarToFIXED(1), SkScalarToFIXED(0),
    722                         SkScalarToFIXED(0), SkScalarToFIXED(1)};
    723     int flags = GGO_METRICS | GGO_GLYPH_INDEX;
    724     GLYPHMETRICS gm;
    725     if (GDI_ERROR == GetGlyphOutline(hdc, gId, flags, &gm, 0, NULL, &mat2)) {
    726         return false;
    727     }
    728     SkASSERT(advance);
    729     *advance = gm.gmCellIncX;
    730     return true;
    731 }
    732 
    733 // static
    734 SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
    735         uint32_t fontID,
    736         SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) {
    737     LOGFONT lf;
    738     GetLogFontByID(fontID, &lf);
    739     SkAdvancedTypefaceMetrics* info = NULL;
    740 
    741     HDC hdc = CreateCompatibleDC(NULL);
    742     HFONT font = CreateFontIndirect(&lf);
    743     HFONT savefont = (HFONT)SelectObject(hdc, font);
    744     HFONT designFont = NULL;
    745 
    746     // To request design units, create a logical font whose height is specified
    747     // as unitsPerEm.
    748     OUTLINETEXTMETRIC otm;
    749     if (!GetOutlineTextMetrics(hdc, sizeof(otm), &otm) ||
    750         !GetTextFace(hdc, LF_FACESIZE, lf.lfFaceName)) {
    751         goto Error;
    752     }
    753     lf.lfHeight = -SkToS32(otm.otmEMSquare);
    754     designFont = CreateFontIndirect(&lf);
    755     SelectObject(hdc, designFont);
    756     if (!GetOutlineTextMetrics(hdc, sizeof(otm), &otm)) {
    757         goto Error;
    758     }
    759     const unsigned glyphCount = calculateGlyphCount(hdc);
    760 
    761     info = new SkAdvancedTypefaceMetrics;
    762     info->fEmSize = otm.otmEMSquare;
    763     info->fMultiMaster = false;
    764     info->fLastGlyphID = SkToU16(glyphCount - 1);
    765     info->fStyle = 0;
    766 #ifdef UNICODE
    767     // Get the buffer size needed first.
    768     size_t str_len = WideCharToMultiByte(CP_UTF8, 0, lf.lfFaceName, -1, NULL,
    769                                          0, NULL, NULL);
    770     // Allocate a buffer (str_len already has terminating null accounted for).
    771     char *familyName = new char[str_len];
    772     // Now actually convert the string.
    773     WideCharToMultiByte(CP_UTF8, 0, lf.lfFaceName, -1, familyName, str_len,
    774                           NULL, NULL);
    775     info->fFontName.set(familyName);
    776     delete [] familyName;
    777 #else
    778     info->fFontName.set(lf.lfFaceName);
    779 #endif
    780 
    781     if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo) {
    782         populate_glyph_to_unicode(hdc, glyphCount, &(info->fGlyphToUnicode));
    783     }
    784 
    785     if (otm.otmTextMetrics.tmPitchAndFamily & TMPF_TRUETYPE) {
    786         info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font;
    787     } else {
    788         info->fType = SkAdvancedTypefaceMetrics::kOther_Font;
    789         info->fItalicAngle = 0;
    790         info->fAscent = 0;
    791         info->fDescent = 0;
    792         info->fStemV = 0;
    793         info->fCapHeight = 0;
    794         info->fBBox = SkIRect::MakeEmpty();
    795         return info;
    796     }
    797 
    798     // If this bit is clear the font is a fixed pitch font.
    799     if (!(otm.otmTextMetrics.tmPitchAndFamily & TMPF_FIXED_PITCH)) {
    800         info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;
    801     }
    802     if (otm.otmTextMetrics.tmItalic) {
    803         info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style;
    804     }
    805     // Setting symbolic style by default for now.
    806     info->fStyle |= SkAdvancedTypefaceMetrics::kSymbolic_Style;
    807     if (otm.otmTextMetrics.tmPitchAndFamily & FF_ROMAN) {
    808         info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;
    809     } else if (otm.otmTextMetrics.tmPitchAndFamily & FF_SCRIPT) {
    810             info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;
    811     }
    812 
    813     // The main italic angle of the font, in tenths of a degree counterclockwise
    814     // from vertical.
    815     info->fItalicAngle = otm.otmItalicAngle / 10;
    816     info->fAscent = SkToS16(otm.otmTextMetrics.tmAscent);
    817     info->fDescent = SkToS16(-otm.otmTextMetrics.tmDescent);
    818     // TODO(ctguil): Use alternate cap height calculation.
    819     // MSDN says otmsCapEmHeight is not support but it is returning a value on
    820     // my Win7 box.
    821     info->fCapHeight = otm.otmsCapEmHeight;
    822     info->fBBox =
    823         SkIRect::MakeLTRB(otm.otmrcFontBox.left, otm.otmrcFontBox.top,
    824                           otm.otmrcFontBox.right, otm.otmrcFontBox.bottom);
    825 
    826     // Figure out a good guess for StemV - Min width of i, I, !, 1.
    827     // This probably isn't very good with an italic font.
    828     int16_t min_width = SHRT_MAX;
    829     info->fStemV = 0;
    830     char stem_chars[] = {'i', 'I', '!', '1'};
    831     for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) {
    832         ABC abcWidths;
    833         if (GetCharABCWidths(hdc, stem_chars[i], stem_chars[i], &abcWidths)) {
    834             int16_t width = abcWidths.abcB;
    835             if (width > 0 && width < min_width) {
    836                 min_width = width;
    837                 info->fStemV = min_width;
    838             }
    839         }
    840     }
    841 
    842     // If bit 1 is set, the font may not be embedded in a document.
    843     // If bit 1 is clear, the font can be embedded.
    844     // If bit 2 is set, the embedding is read-only.
    845     if (otm.otmfsType & 0x1) {
    846         info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font;
    847     } else if (perGlyphInfo &
    848                SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo) {
    849         info->fGlyphWidths.reset(
    850             getAdvanceData(hdc, glyphCount, &getWidthAdvance));
    851     }
    852 
    853 Error:
    854     SelectObject(hdc, savefont);
    855     DeleteObject(designFont);
    856     DeleteObject(font);
    857     DeleteDC(hdc);
    858 
    859     return info;
    860 }
    861 
    862 SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
    863 
    864     //Should not be used on Windows, keep linker happy
    865     SkASSERT(false);
    866     return SkCreateTypefaceFromLOGFONT(get_default_font());
    867 }
    868 
    869 SkStream* SkFontHost::OpenStream(SkFontID uniqueID) {
    870     const DWORD kTTCTag =
    871         SkEndian_SwapBE32(SkSetFourByteTag('t', 't', 'c', 'f'));
    872     LOGFONT lf;
    873     GetLogFontByID(uniqueID, &lf);
    874 
    875     HDC hdc = ::CreateCompatibleDC(NULL);
    876     HFONT font = CreateFontIndirect(&lf);
    877     HFONT savefont = (HFONT)SelectObject(hdc, font);
    878 
    879     SkMemoryStream* stream = NULL;
    880     DWORD tables[2] = {kTTCTag, 0};
    881     for (int i = 0; i < SK_ARRAY_COUNT(tables); i++) {
    882         size_t bufferSize = GetFontData(hdc, tables[i], 0, NULL, 0);
    883         if (bufferSize != GDI_ERROR) {
    884             stream = new SkMemoryStream(bufferSize);
    885             if (GetFontData(hdc, tables[i], 0, (void*)stream->getMemoryBase(),
    886                             bufferSize)) {
    887                 break;
    888             } else {
    889                 delete stream;
    890                 stream = NULL;
    891             }
    892         }
    893     }
    894 
    895     SelectObject(hdc, savefont);
    896     DeleteObject(font);
    897     DeleteDC(hdc);
    898 
    899     return stream;
    900 }
    901 
    902 SkScalerContext* SkFontHost::CreateScalerContext(const SkDescriptor* desc) {
    903     return SkNEW_ARGS(SkScalerContext_Windows, (desc));
    904 }
    905 
    906 /** Return the closest matching typeface given either an existing family
    907  (specified by a typeface in that family) or by a familyName, and a
    908  requested style.
    909  1) If familyFace is null, use famillyName.
    910  2) If famillyName is null, use familyFace.
    911  3) If both are null, return the default font that best matches style
    912  This MUST not return NULL.
    913  */
    914 
    915 SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
    916                                        const char familyName[],
    917                                        const void* data, size_t bytelength,
    918                                        SkTypeface::Style style) {
    919     LOGFONT lf;
    920     if (NULL == familyFace && NULL == familyName) {
    921         lf = get_default_font();
    922     } else if (familyFace) {
    923         LogFontTypeface* face = (LogFontTypeface*)familyFace;
    924         lf = face->fLogFont;
    925     } else {
    926         memset(&lf, 0, sizeof(LOGFONT));
    927 #ifdef UNICODE
    928         // Get the buffer size needed first.
    929         size_t str_len = ::MultiByteToWideChar(CP_UTF8, 0, familyName,
    930                                                 -1, NULL, 0);
    931         // Allocate a buffer (str_len already has terminating null
    932         // accounted for).
    933         wchar_t *wideFamilyName = new wchar_t[str_len];
    934         // Now actually convert the string.
    935         ::MultiByteToWideChar(CP_UTF8, 0, familyName, -1,
    936                                 wideFamilyName, str_len);
    937         ::wcsncpy(lf.lfFaceName, wideFamilyName, LF_FACESIZE);
    938         delete [] wideFamilyName;
    939 #else
    940         ::strncpy(lf.lfFaceName, familyName, LF_FACESIZE);
    941 #endif
    942         lf.lfFaceName[LF_FACESIZE-1] = '\0';
    943     }
    944     setStyle(&lf, style);
    945     return SkCreateTypefaceFromLOGFONT(lf);
    946 }
    947 
    948 size_t SkFontHost::ShouldPurgeFontCache(size_t sizeAllocatedSoFar) {
    949     if (sizeAllocatedSoFar > FONT_CACHE_MEMORY_BUDGET)
    950         return sizeAllocatedSoFar - FONT_CACHE_MEMORY_BUDGET;
    951     else
    952         return 0;   // nothing to do
    953 }
    954 
    955 int SkFontHost::ComputeGammaFlag(const SkPaint& paint) {
    956     return 0;
    957 }
    958 
    959 void SkFontHost::GetGammaTables(const uint8_t* tables[2]) {
    960     tables[0] = NULL;   // black gamma (e.g. exp=1.4)
    961     tables[1] = NULL;   // white gamma (e.g. exp= 1/1.4)
    962 }
    963 
    964 SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
    965     printf("SkFontHost::CreateTypefaceFromFile unimplemented");
    966     return NULL;
    967 }
    968 
    969 void SkFontHost::FilterRec(SkScalerContext::Rec* rec) {
    970     // We don't control the hinting nor ClearType settings here
    971     rec->setHinting(SkPaint::kNormal_Hinting);
    972 
    973     // we do support LCD16
    974     if (SkMask::kLCD16_Format == rec->fMaskFormat) {
    975         return;
    976     }
    977 
    978     if (SkMask::FormatIsLCD((SkMask::Format)rec->fMaskFormat)) {
    979         rec->fMaskFormat = SkMask::kA8_Format;
    980     }
    981 }
    982 
    983 #endif // WIN32
    984