Home | History | Annotate | Download | only in ports
      1 
      2 /*
      3  * Copyright 2006 The Android Open Source Project
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 
     10 #include "SkColorFilter.h"
     11 #include "SkString.h"
     12 #include "SkEndian.h"
     13 #include "SkFontHost.h"
     14 #include "SkDescriptor.h"
     15 #include "SkAdvancedTypefaceMetrics.h"
     16 #include "SkStream.h"
     17 #include "SkThread.h"
     18 #include "SkTypeface_win.h"
     19 #include "SkTypefaceCache.h"
     20 #include "SkUtils.h"
     21 
     22 #ifdef WIN32
     23 #include "windows.h"
     24 #include "tchar.h"
     25 #include "usp10.h"
     26 
     27 // always packed xxRRGGBB
     28 typedef uint32_t SkGdiRGB;
     29 
     30 template <typename T> T* SkTAddByteOffset(T* ptr, size_t byteOffset) {
     31     return (T*)((char*)ptr + byteOffset);
     32 }
     33 
     34 // define this in your Makefile or .gyp to enforce AA requests
     35 // which GDI ignores at small sizes. This flag guarantees AA
     36 // for rotated text, regardless of GDI's notions.
     37 //#define SK_ENFORCE_ROTATED_TEXT_AA_ON_WINDOWS
     38 
     39 // client3d has to undefine this for now
     40 #define CAN_USE_LOGFONT_NAME
     41 
     42 static bool isLCD(const SkScalerContext::Rec& rec) {
     43     return SkMask::kLCD16_Format == rec.fMaskFormat ||
     44            SkMask::kLCD32_Format == rec.fMaskFormat;
     45 }
     46 
     47 static bool bothZero(SkScalar a, SkScalar b) {
     48     return 0 == a && 0 == b;
     49 }
     50 
     51 // returns false if there is any non-90-rotation or skew
     52 static bool isAxisAligned(const SkScalerContext::Rec& rec) {
     53     return 0 == rec.fPreSkewX &&
     54            (bothZero(rec.fPost2x2[0][1], rec.fPost2x2[1][0]) ||
     55             bothZero(rec.fPost2x2[0][0], rec.fPost2x2[1][1]));
     56 }
     57 
     58 static bool needToRenderWithSkia(const SkScalerContext::Rec& rec) {
     59 #ifdef SK_ENFORCE_ROTATED_TEXT_AA_ON_WINDOWS
     60     // What we really want to catch is when GDI will ignore the AA request and give
     61     // us BW instead. Smallish rotated text is one heuristic, so this code is just
     62     // an approximation. We shouldn't need to do this for larger sizes, but at those
     63     // sizes, the quality difference gets less and less between our general
     64     // scanconverter and GDI's.
     65     if (SkMask::kA8_Format == rec.fMaskFormat && !isAxisAligned(rec)) {
     66         return true;
     67     }
     68 #endif
     69     // false means allow GDI to generate the bits
     70     return false;
     71 }
     72 
     73 using namespace skia_advanced_typeface_metrics_utils;
     74 
     75 static const uint16_t BUFFERSIZE = (16384 - 32);
     76 static uint8_t glyphbuf[BUFFERSIZE];
     77 
     78 /**
     79  *  Since LOGFONT wants its textsize as an int, and we support fractional sizes,
     80  *  and since we have a cache of LOGFONTs for our tyepfaces, we always set the
     81  *  lfHeight to a canonical size, and then we use the 2x2 matrix to achieve the
     82  *  actual requested size.
     83  */
     84 static const int gCanonicalTextSize = 64;
     85 
     86 static void make_canonical(LOGFONT* lf) {
     87     lf->lfHeight = -gCanonicalTextSize;
     88     lf->lfQuality = CLEARTYPE_QUALITY;//PROOF_QUALITY;
     89     lf->lfCharSet = DEFAULT_CHARSET;
     90 //    lf->lfClipPrecision = 64;
     91 }
     92 
     93 static SkTypeface::Style get_style(const LOGFONT& lf) {
     94     unsigned style = 0;
     95     if (lf.lfWeight >= FW_BOLD) {
     96         style |= SkTypeface::kBold;
     97     }
     98     if (lf.lfItalic) {
     99         style |= SkTypeface::kItalic;
    100     }
    101     return static_cast<SkTypeface::Style>(style);
    102 }
    103 
    104 static void setStyle(LOGFONT* lf, SkTypeface::Style style) {
    105     lf->lfWeight = (style & SkTypeface::kBold) != 0 ? FW_BOLD : FW_NORMAL ;
    106     lf->lfItalic = ((style & SkTypeface::kItalic) != 0);
    107 }
    108 
    109 static inline FIXED SkFixedToFIXED(SkFixed x) {
    110     return *(FIXED*)(&x);
    111 }
    112 
    113 static inline FIXED SkScalarToFIXED(SkScalar x) {
    114     return SkFixedToFIXED(SkScalarToFixed(x));
    115 }
    116 
    117 static unsigned calculateGlyphCount(HDC hdc) {
    118     // The 'maxp' table stores the number of glyphs at offset 4, in 2 bytes.
    119     const DWORD maxpTag =
    120         SkEndian_SwapBE32(SkSetFourByteTag('m', 'a', 'x', 'p'));
    121     uint16_t glyphs;
    122     if (GetFontData(hdc, maxpTag, 4, &glyphs, sizeof(glyphs)) != GDI_ERROR) {
    123         return SkEndian_SwapBE16(glyphs);
    124     }
    125 
    126     // Binary search for glyph count.
    127     static const MAT2 mat2 = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
    128     int32_t max = SK_MaxU16 + 1;
    129     int32_t min = 0;
    130     GLYPHMETRICS gm;
    131     while (min < max) {
    132         int32_t mid = min + ((max - min) / 2);
    133         if (GetGlyphOutlineW(hdc, mid, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0,
    134                              NULL, &mat2) == GDI_ERROR) {
    135             max = mid;
    136         } else {
    137             min = mid + 1;
    138         }
    139     }
    140     SkASSERT(min == max);
    141     return min;
    142 }
    143 
    144 class LogFontTypeface : public SkTypeface {
    145 public:
    146     LogFontTypeface(SkTypeface::Style style, SkFontID fontID, const LOGFONT& lf) :
    147       SkTypeface(style, fontID, false), fLogFont(lf) {}
    148 
    149     LOGFONT fLogFont;
    150 
    151     static LogFontTypeface* Create(const LOGFONT& lf) {
    152         SkTypeface::Style style = get_style(lf);
    153         SkFontID fontID = SkTypefaceCache::NewFontID();
    154         return new LogFontTypeface(style, fontID, lf);
    155     }
    156 };
    157 
    158 static const LOGFONT& get_default_font() {
    159     static LOGFONT gDefaultFont;
    160     return gDefaultFont;
    161 }
    162 
    163 static bool FindByLogFont(SkTypeface* face, SkTypeface::Style requestedStyle, void* ctx) {
    164     LogFontTypeface* lface = reinterpret_cast<LogFontTypeface*>(face);
    165     const LOGFONT* lf = reinterpret_cast<const LOGFONT*>(ctx);
    166 
    167     return get_style(lface->fLogFont) == requestedStyle &&
    168            !memcmp(&lface->fLogFont, lf, sizeof(LOGFONT));
    169 }
    170 
    171 /**
    172  *  This guy is public. It first searches the cache, and if a match is not found,
    173  *  it creates a new face.
    174  */
    175 SkTypeface* SkCreateTypefaceFromLOGFONT(const LOGFONT& origLF) {
    176     LOGFONT lf = origLF;
    177     make_canonical(&lf);
    178     SkTypeface* face = SkTypefaceCache::FindByProcAndRef(FindByLogFont, &lf);
    179     if (NULL == face) {
    180         face = LogFontTypeface::Create(lf);
    181         SkTypefaceCache::Add(face, get_style(lf));
    182     }
    183     return face;
    184 }
    185 
    186 /**
    187  *  This guy is public
    188  */
    189 void SkLOGFONTFromTypeface(const SkTypeface* face, LOGFONT* lf) {
    190     if (NULL == face) {
    191         *lf = get_default_font();
    192     } else {
    193         *lf = ((const LogFontTypeface*)face)->fLogFont;
    194     }
    195 }
    196 
    197 SkFontID SkFontHost::NextLogicalFont(SkFontID currFontID, SkFontID origFontID) {
    198   // Zero means that we don't have any fallback fonts for this fontID.
    199   // This function is implemented on Android, but doesn't have much
    200   // meaning here.
    201   return 0;
    202 }
    203 
    204 static void ensure_typeface_accessible(SkFontID fontID) {
    205     LogFontTypeface* face = (LogFontTypeface*)SkTypefaceCache::FindByID(fontID);
    206     if (face) {
    207         SkFontHost::EnsureTypefaceAccessible(*face);
    208     }
    209 }
    210 
    211 static void GetLogFontByID(SkFontID fontID, LOGFONT* lf) {
    212     LogFontTypeface* face = (LogFontTypeface*)SkTypefaceCache::FindByID(fontID);
    213     if (face) {
    214         *lf = face->fLogFont;
    215     } else {
    216         sk_bzero(lf, sizeof(LOGFONT));
    217     }
    218 }
    219 
    220 // Construct Glyph to Unicode table.
    221 // Unicode code points that require conjugate pairs in utf16 are not
    222 // supported.
    223 // TODO(arthurhsu): Add support for conjugate pairs. It looks like that may
    224 // require parsing the TTF cmap table (platform 4, encoding 12) directly instead
    225 // of calling GetFontUnicodeRange().
    226 static void populate_glyph_to_unicode(HDC fontHdc, const unsigned glyphCount,
    227                                       SkTDArray<SkUnichar>* glyphToUnicode) {
    228     DWORD glyphSetBufferSize = GetFontUnicodeRanges(fontHdc, NULL);
    229     if (!glyphSetBufferSize) {
    230         return;
    231     }
    232 
    233     SkAutoTDeleteArray<BYTE> glyphSetBuffer(new BYTE[glyphSetBufferSize]);
    234     GLYPHSET* glyphSet =
    235         reinterpret_cast<LPGLYPHSET>(glyphSetBuffer.get());
    236     if (GetFontUnicodeRanges(fontHdc, glyphSet) != glyphSetBufferSize) {
    237         return;
    238     }
    239 
    240     glyphToUnicode->setCount(glyphCount);
    241     memset(glyphToUnicode->begin(), 0, glyphCount * sizeof(SkUnichar));
    242     for (DWORD i = 0; i < glyphSet->cRanges; ++i) {
    243         // There is no guarantee that within a Unicode range, the corresponding
    244         // glyph id in a font file are continuous. So, even if we have ranges,
    245         // we can't just use the first and last entry of the range to compute
    246         // result. We need to enumerate them one by one.
    247         int count = glyphSet->ranges[i].cGlyphs;
    248         SkAutoTArray<WCHAR> chars(count + 1);
    249         chars[count] = 0;  // termintate string
    250         SkAutoTArray<WORD> glyph(count);
    251         for (USHORT j = 0; j < count; ++j) {
    252             chars[j] = glyphSet->ranges[i].wcLow + j;
    253         }
    254         GetGlyphIndicesW(fontHdc, chars.get(), count, glyph.get(),
    255                          GGI_MARK_NONEXISTING_GLYPHS);
    256         // If the glyph ID is valid, and the glyph is not mapped, then we will
    257         // fill in the char id into the vector. If the glyph is mapped already,
    258         // skip it.
    259         // TODO(arthurhsu): better improve this. e.g. Get all used char ids from
    260         // font cache, then generate this mapping table from there. It's
    261         // unlikely to have collisions since glyph reuse happens mostly for
    262         // different Unicode pages.
    263         for (USHORT j = 0; j < count; ++j) {
    264             if (glyph[j] != 0xffff && glyph[j] < glyphCount &&
    265                 (*glyphToUnicode)[glyph[j]] == 0) {
    266                 (*glyphToUnicode)[glyph[j]] = chars[j];
    267             }
    268         }
    269     }
    270 }
    271 
    272 //////////////////////////////////////////////////////////////////////////////////////
    273 
    274 static int alignTo32(int n) {
    275     return (n + 31) & ~31;
    276 }
    277 
    278 struct MyBitmapInfo : public BITMAPINFO {
    279     RGBQUAD fMoreSpaceForColors[1];
    280 };
    281 
    282 class HDCOffscreen {
    283 public:
    284     HDCOffscreen() {
    285         fFont = 0;
    286         fDC = 0;
    287         fBM = 0;
    288         fBits = NULL;
    289         fWidth = fHeight = 0;
    290         fIsBW = false;
    291         fColor = kInvalid_Color;
    292     }
    293 
    294     ~HDCOffscreen() {
    295         if (fDC) {
    296             DeleteDC(fDC);
    297         }
    298         if (fBM) {
    299             DeleteObject(fBM);
    300         }
    301     }
    302 
    303     void init(HFONT font, const XFORM& xform) {
    304         fFont = font;
    305         fXform = xform;
    306     }
    307 
    308     const void* draw(const SkGlyph&, bool isBW, SkGdiRGB fgColor,
    309                      size_t* srcRBPtr);
    310 
    311 private:
    312     HDC     fDC;
    313     HBITMAP fBM;
    314     HFONT   fFont;
    315     XFORM   fXform;
    316     void*   fBits;  // points into fBM
    317     COLORREF fColor;
    318     int     fWidth;
    319     int     fHeight;
    320     bool    fIsBW;
    321 
    322     enum {
    323         // will always trigger us to reset the color, since we
    324         // should only store 0 or 0x00FFFFFF or gray (0x007F7F7F)
    325         kInvalid_Color = 12345
    326     };
    327 };
    328 
    329 const void* HDCOffscreen::draw(const SkGlyph& glyph, bool isBW,
    330                                SkGdiRGB fgColor, size_t* srcRBPtr) {
    331     if (0 == fDC) {
    332         fDC = CreateCompatibleDC(0);
    333         if (0 == fDC) {
    334             return NULL;
    335         }
    336         SetGraphicsMode(fDC, GM_ADVANCED);
    337         SetBkMode(fDC, TRANSPARENT);
    338         SetTextAlign(fDC, TA_LEFT | TA_BASELINE);
    339         SelectObject(fDC, fFont);
    340         fColor = kInvalid_Color;
    341     }
    342 
    343     if (fBM && (fIsBW != isBW || fWidth < glyph.fWidth || fHeight < glyph.fHeight)) {
    344         DeleteObject(fBM);
    345         fBM = 0;
    346     }
    347     fIsBW = isBW;
    348 
    349     COLORREF color = fgColor;
    350     if (fIsBW) {
    351         color = 0xFFFFFF;
    352     }
    353     if (fColor != color) {
    354         fColor = color;
    355         COLORREF prev = SetTextColor(fDC, color);
    356         SkASSERT(prev != CLR_INVALID);
    357     }
    358 
    359     fWidth = SkMax32(fWidth, glyph.fWidth);
    360     fHeight = SkMax32(fHeight, glyph.fHeight);
    361 
    362     int biWidth = isBW ? alignTo32(fWidth) : fWidth;
    363 
    364     if (0 == fBM) {
    365         MyBitmapInfo info;
    366         sk_bzero(&info, sizeof(info));
    367         if (isBW) {
    368             RGBQUAD blackQuad = { 0, 0, 0, 0 };
    369             RGBQUAD whiteQuad = { 0xFF, 0xFF, 0xFF, 0 };
    370             info.bmiColors[0] = blackQuad;
    371             info.bmiColors[1] = whiteQuad;
    372         }
    373         info.bmiHeader.biSize = sizeof(info.bmiHeader);
    374         info.bmiHeader.biWidth = biWidth;
    375         info.bmiHeader.biHeight = fHeight;
    376         info.bmiHeader.biPlanes = 1;
    377         info.bmiHeader.biBitCount = isBW ? 1 : 32;
    378         info.bmiHeader.biCompression = BI_RGB;
    379         if (isBW) {
    380             info.bmiHeader.biClrUsed = 2;
    381         }
    382         fBM = CreateDIBSection(fDC, &info, DIB_RGB_COLORS, &fBits, 0, 0);
    383         if (0 == fBM) {
    384             return NULL;
    385         }
    386         SelectObject(fDC, fBM);
    387     }
    388 
    389     // erase
    390     size_t srcRB = isBW ? (biWidth >> 3) : (fWidth << 2);
    391     size_t size = fHeight * srcRB;
    392     unsigned bg = (0 == color) ? 0xFF : 0;
    393     memset(fBits, bg, size);
    394 
    395     XFORM xform = fXform;
    396     xform.eDx = (float)-glyph.fLeft;
    397     xform.eDy = (float)-glyph.fTop;
    398     SetWorldTransform(fDC, &xform);
    399 
    400     uint16_t glyphID = glyph.getGlyphID();
    401     BOOL ret = ExtTextOutW(fDC, 0, 0, ETO_GLYPH_INDEX, NULL, reinterpret_cast<LPCWSTR>(&glyphID), 1, NULL);
    402     GdiFlush();
    403     if (0 == ret) {
    404         return NULL;
    405     }
    406     *srcRBPtr = srcRB;
    407     // offset to the start of the image
    408     return (const char*)fBits + (fHeight - glyph.fHeight) * srcRB;
    409 }
    410 
    411 //////////////////////////////////////////////////////////////////////////////////////
    412 
    413 class SkScalerContext_Windows : public SkScalerContext {
    414 public:
    415     SkScalerContext_Windows(const SkDescriptor* desc);
    416     virtual ~SkScalerContext_Windows();
    417 
    418 protected:
    419     virtual unsigned generateGlyphCount();
    420     virtual uint16_t generateCharToGlyph(SkUnichar uni);
    421     virtual void generateAdvance(SkGlyph* glyph);
    422     virtual void generateMetrics(SkGlyph* glyph);
    423     virtual void generateImage(const SkGlyph& glyph);
    424     virtual void generatePath(const SkGlyph& glyph, SkPath* path);
    425     virtual void generateFontMetrics(SkPaint::FontMetrics* mX, SkPaint::FontMetrics* mY);
    426 
    427 private:
    428     HDCOffscreen fOffscreen;
    429     SkScalar     fScale;  // to get from canonical size to real size
    430     MAT2         fMat22;
    431     XFORM        fXform;
    432     HDC          fDDC;
    433     HFONT        fSavefont;
    434     HFONT        fFont;
    435     SCRIPT_CACHE fSC;
    436     int          fGlyphCount;
    437 
    438     HFONT        fHiResFont;
    439     MAT2         fMat22Identity;
    440     SkMatrix     fHiResMatrix;
    441 };
    442 
    443 static float mul2float(SkScalar a, SkScalar b) {
    444     return SkScalarToFloat(SkScalarMul(a, b));
    445 }
    446 
    447 static FIXED float2FIXED(float x) {
    448     return SkFixedToFIXED(SkFloatToFixed(x));
    449 }
    450 
    451 SK_DECLARE_STATIC_MUTEX(gFTMutex);
    452 
    453 #define HIRES_TEXTSIZE  2048
    454 #define HIRES_SHIFT     11
    455 static inline SkFixed HiResToFixed(int value) {
    456     return value << (16 - HIRES_SHIFT);
    457 }
    458 
    459 static bool needHiResMetrics(const SkScalar mat[2][2]) {
    460     return mat[1][0] || mat[0][1];
    461 }
    462 
    463 static BYTE compute_quality(const SkScalerContext::Rec& rec) {
    464     switch (rec.fMaskFormat) {
    465         case SkMask::kBW_Format:
    466             return NONANTIALIASED_QUALITY;
    467         case SkMask::kLCD16_Format:
    468         case SkMask::kLCD32_Format:
    469             return CLEARTYPE_QUALITY;
    470         default:
    471             if (rec.fFlags & SkScalerContext::kGenA8FromLCD_Flag) {
    472                 return CLEARTYPE_QUALITY;
    473             } else {
    474                 return ANTIALIASED_QUALITY;
    475             }
    476     }
    477 }
    478 
    479 SkScalerContext_Windows::SkScalerContext_Windows(const SkDescriptor* desc)
    480         : SkScalerContext(desc), fDDC(0), fFont(0), fSavefont(0), fSC(0)
    481         , fGlyphCount(-1) {
    482     SkAutoMutexAcquire  ac(gFTMutex);
    483 
    484     fScale = fRec.fTextSize / gCanonicalTextSize;
    485 
    486     fXform.eM11 = mul2float(fScale, fRec.fPost2x2[0][0]);
    487     fXform.eM12 = mul2float(fScale, fRec.fPost2x2[1][0]);
    488     fXform.eM21 = mul2float(fScale, fRec.fPost2x2[0][1]);
    489     fXform.eM22 = mul2float(fScale, fRec.fPost2x2[1][1]);
    490     fXform.eDx = 0;
    491     fXform.eDy = 0;
    492 
    493     fMat22.eM11 = float2FIXED(fXform.eM11);
    494     fMat22.eM12 = float2FIXED(fXform.eM12);
    495     fMat22.eM21 = float2FIXED(-fXform.eM21);
    496     fMat22.eM22 = float2FIXED(-fXform.eM22);
    497 
    498     fDDC = ::CreateCompatibleDC(NULL);
    499     SetGraphicsMode(fDDC, GM_ADVANCED);
    500     SetBkMode(fDDC, TRANSPARENT);
    501 
    502     // Scaling by the DPI is inconsistent with how Skia draws elsewhere
    503     //SkScalar height = -(fRec.fTextSize * GetDeviceCaps(ddc, LOGPIXELSY) / 72);
    504     LOGFONT lf;
    505     GetLogFontByID(fRec.fFontID, &lf);
    506     lf.lfHeight = -gCanonicalTextSize;
    507     lf.lfQuality = compute_quality(fRec);
    508     fFont = CreateFontIndirect(&lf);
    509 
    510     // if we're rotated, or want fractional widths, create a hires font
    511     fHiResFont = 0;
    512     if (needHiResMetrics(fRec.fPost2x2)) {
    513         lf.lfHeight = -HIRES_TEXTSIZE;
    514         fHiResFont = CreateFontIndirect(&lf);
    515 
    516         fMat22Identity.eM11 = fMat22Identity.eM22 = SkFixedToFIXED(SK_Fixed1);
    517         fMat22Identity.eM12 = fMat22Identity.eM21 = SkFixedToFIXED(0);
    518 
    519         // construct a matrix to go from HIRES logical units to our device units
    520         fRec.getSingleMatrix(&fHiResMatrix);
    521         SkScalar scale = SkScalarInvert(SkIntToScalar(HIRES_TEXTSIZE));
    522         fHiResMatrix.preScale(scale, scale);
    523     }
    524     fSavefont = (HFONT)SelectObject(fDDC, fFont);
    525 
    526     if (needToRenderWithSkia(fRec)) {
    527         this->forceGenerateImageFromPath();
    528     }
    529 
    530     fOffscreen.init(fFont, fXform);
    531 }
    532 
    533 SkScalerContext_Windows::~SkScalerContext_Windows() {
    534     if (fDDC) {
    535         ::SelectObject(fDDC, fSavefont);
    536         ::DeleteDC(fDDC);
    537     }
    538     if (fFont) {
    539         ::DeleteObject(fFont);
    540     }
    541     if (fHiResFont) {
    542         ::DeleteObject(fHiResFont);
    543     }
    544     if (fSC) {
    545         ::ScriptFreeCache(&fSC);
    546     }
    547 }
    548 
    549 unsigned SkScalerContext_Windows::generateGlyphCount() {
    550     if (fGlyphCount < 0) {
    551         fGlyphCount = calculateGlyphCount(fDDC);
    552     }
    553     return fGlyphCount;
    554 }
    555 
    556 uint16_t SkScalerContext_Windows::generateCharToGlyph(SkUnichar uni) {
    557     uint16_t index = 0;
    558     WCHAR c[2];
    559     // TODO(ctguil): Support characters that generate more than one glyph.
    560     if (SkUTF16_FromUnichar(uni, (uint16_t*)c) == 1) {
    561         // Type1 fonts fail with uniscribe API. Use GetGlyphIndices for plane 0.
    562         SkAssertResult(GetGlyphIndicesW(fDDC, c, 1, &index, 0));
    563     } else {
    564         // Use uniscribe to detemine glyph index for non-BMP characters.
    565         // Need to add extra item to SCRIPT_ITEM to work around a bug in older
    566         // windows versions. https://bugzilla.mozilla.org/show_bug.cgi?id=366643
    567         SCRIPT_ITEM si[2 + 1];
    568         int items;
    569         SkAssertResult(
    570             SUCCEEDED(ScriptItemize(c, 2, 2, NULL, NULL, si, &items)));
    571 
    572         WORD log[2];
    573         SCRIPT_VISATTR vsa;
    574         int glyphs;
    575         SkAssertResult(SUCCEEDED(ScriptShape(
    576             fDDC, &fSC, c, 2, 1, &si[0].a, &index, log, &vsa, &glyphs)));
    577     }
    578     return index;
    579 }
    580 
    581 void SkScalerContext_Windows::generateAdvance(SkGlyph* glyph) {
    582     this->generateMetrics(glyph);
    583 }
    584 
    585 void SkScalerContext_Windows::generateMetrics(SkGlyph* glyph) {
    586 
    587     SkASSERT(fDDC);
    588 
    589     GLYPHMETRICS gm;
    590     sk_bzero(&gm, sizeof(gm));
    591 
    592     glyph->fRsbDelta = 0;
    593     glyph->fLsbDelta = 0;
    594 
    595     // Note: need to use GGO_GRAY8_BITMAP instead of GGO_METRICS because GGO_METRICS returns a smaller
    596     // BlackBlox; we need the bigger one in case we need the image.  fAdvance is the same.
    597     uint32_t ret = GetGlyphOutlineW(fDDC, glyph->getGlyphID(0), GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX, &gm, 0, NULL, &fMat22);
    598     if (GDI_ERROR == ret) {
    599         ensure_typeface_accessible(fRec.fFontID);
    600         ret = GetGlyphOutlineW(fDDC, glyph->getGlyphID(0), GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX, &gm, 0, NULL, &fMat22);
    601     }
    602 
    603     if (GDI_ERROR != ret) {
    604         if (ret == 0) {
    605             // for white space, ret is zero and gmBlackBoxX, gmBlackBoxY are 1 incorrectly!
    606             gm.gmBlackBoxX = gm.gmBlackBoxY = 0;
    607         }
    608         glyph->fWidth   = gm.gmBlackBoxX;
    609         glyph->fHeight  = gm.gmBlackBoxY;
    610         glyph->fTop     = SkToS16(gm.gmptGlyphOrigin.y - gm.gmBlackBoxY);
    611         glyph->fLeft    = SkToS16(gm.gmptGlyphOrigin.x);
    612         glyph->fAdvanceX = SkIntToFixed(gm.gmCellIncX);
    613         glyph->fAdvanceY = -SkIntToFixed(gm.gmCellIncY);
    614 
    615         // we outset in all dimensions, since the image may bleed outside
    616         // of the computed bounds returned by GetGlyphOutline.
    617         // This was deduced by trial and error for small text (e.g. 8pt), so there
    618         // maybe a more precise way to make this adjustment...
    619         //
    620         // This test shows us clipping the tops of some of the CJK fonts unless we
    621         // increase the top of the box by 2, hence the height by 4. This seems to
    622         // correspond to an embedded bitmap font, but not sure.
    623         //     LayoutTests/fast/text/backslash-to-yen-sign-euc.html
    624         //
    625         if (glyph->fWidth) {    // don't outset an empty glyph
    626             glyph->fWidth += 4;
    627             glyph->fHeight += 4;
    628             glyph->fTop -= 2;
    629             glyph->fLeft -= 2;
    630         }
    631 
    632         if (fHiResFont) {
    633             SelectObject(fDDC, fHiResFont);
    634             sk_bzero(&gm, sizeof(gm));
    635             ret = GetGlyphOutlineW(fDDC, glyph->getGlyphID(0), GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, NULL, &fMat22Identity);
    636             if (GDI_ERROR != ret) {
    637                 SkPoint advance;
    638                 fHiResMatrix.mapXY(SkIntToScalar(gm.gmCellIncX), SkIntToScalar(gm.gmCellIncY), &advance);
    639                 glyph->fAdvanceX = SkScalarToFixed(advance.fX);
    640                 glyph->fAdvanceY = SkScalarToFixed(advance.fY);
    641             }
    642             SelectObject(fDDC, fFont);
    643         }
    644     } else {
    645         glyph->fWidth = 0;
    646     }
    647 }
    648 
    649 void SkScalerContext_Windows::generateFontMetrics(SkPaint::FontMetrics* mx, SkPaint::FontMetrics* my) {
    650 // Note: This code was borrowed from generateLineHeight, which has a note
    651 // stating that it may be incorrect.
    652     if (!(mx || my))
    653       return;
    654 
    655     SkASSERT(fDDC);
    656 
    657     OUTLINETEXTMETRIC otm;
    658 
    659     uint32_t ret = GetOutlineTextMetrics(fDDC, sizeof(otm), &otm);
    660     if (GDI_ERROR == ret) {
    661         ensure_typeface_accessible(fRec.fFontID);
    662         ret = GetOutlineTextMetrics(fDDC, sizeof(otm), &otm);
    663     }
    664     if (sizeof(otm) != ret) {
    665       return;
    666     }
    667 
    668     if (mx) {
    669         mx->fTop = -fScale * otm.otmTextMetrics.tmAscent;
    670         mx->fAscent = -fScale * otm.otmAscent;
    671         mx->fDescent = -fScale * otm.otmDescent;
    672         mx->fBottom = fScale * otm.otmTextMetrics.tmDescent;
    673         mx->fLeading = fScale * (otm.otmTextMetrics.tmInternalLeading
    674                                  + otm.otmTextMetrics.tmExternalLeading);
    675     }
    676 
    677     if (my) {
    678         my->fTop = -fScale * otm.otmTextMetrics.tmAscent;
    679         my->fAscent = -fScale * otm.otmAscent;
    680         my->fDescent = -fScale * otm.otmDescent;
    681         my->fBottom = fScale * otm.otmTextMetrics.tmDescent;
    682         my->fLeading = fScale * (otm.otmTextMetrics.tmInternalLeading
    683                                  + otm.otmTextMetrics.tmExternalLeading);
    684     }
    685 }
    686 
    687 ////////////////////////////////////////////////////////////////////////////////////////
    688 
    689 static void build_power_table(uint8_t table[], float ee) {
    690     for (int i = 0; i < 256; i++) {
    691         float x = i / 255.f;
    692         x = powf(x, ee);
    693         int xx = SkScalarRound(SkFloatToScalar(x * 255));
    694         table[i] = SkToU8(xx);
    695     }
    696 }
    697 
    698 // This will invert the gamma applied by GDI, so we can sort-of get linear values.
    699 // Needed when we draw non-black, non-white text, and don't know how to bias it.
    700 static const uint8_t* getInverseGammaTable() {
    701     static bool gInited;
    702     static uint8_t gTable[256];
    703     if (!gInited) {
    704         UINT level = 0;
    705         if (!SystemParametersInfo(SPI_GETFONTSMOOTHINGCONTRAST, 0, &level, 0) || !level) {
    706             // can't get the data, so use a default
    707             level = 1400;
    708         }
    709         build_power_table(gTable, level / 1000.0f);
    710         gInited = true;
    711     }
    712     return gTable;
    713 }
    714 
    715 #include "SkColorPriv.h"
    716 
    717 // gdi's bitmap is upside-down, so we reverse dst walking in Y
    718 // whenever we copy it into skia's buffer
    719 
    720 static int compute_luminance(int r, int g, int b) {
    721 //    return (r * 2 + g * 5 + b) >> 3;
    722     return (r * 27 + g * 92 + b * 9) >> 7;
    723 }
    724 
    725 static inline uint8_t rgb_to_a8(SkGdiRGB rgb) {
    726     int r = (rgb >> 16) & 0xFF;
    727     int g = (rgb >>  8) & 0xFF;
    728     int b = (rgb >>  0) & 0xFF;
    729     return compute_luminance(r, g, b);
    730 }
    731 
    732 static inline uint16_t rgb_to_lcd16(SkGdiRGB rgb) {
    733     int r = (rgb >> 16) & 0xFF;
    734     int g = (rgb >>  8) & 0xFF;
    735     int b = (rgb >>  0) & 0xFF;
    736     return SkPackRGB16(SkR32ToR16(r), SkG32ToG16(g), SkB32ToB16(b));
    737 }
    738 
    739 static inline SkPMColor rgb_to_lcd32(SkGdiRGB rgb) {
    740     int r = (rgb >> 16) & 0xFF;
    741     int g = (rgb >>  8) & 0xFF;
    742     int b = (rgb >>  0) & 0xFF;
    743     int a = SkMax32(r, SkMax32(g, b));
    744     return SkPackARGB32(a, r, g, b);
    745 }
    746 
    747 // Is this GDI color neither black nor white? If so, we have to keep this
    748 // image as is, rather than smashing it down to a BW mask.
    749 //
    750 // returns int instead of bool, since we don't want/have to pay to convert
    751 // the zero/non-zero value into a bool
    752 static int is_not_black_or_white(SkGdiRGB c) {
    753     // same as (but faster than)
    754     //      c &= 0x00FFFFFF;
    755     //      return 0 == c || 0x00FFFFFF == c;
    756     return (c + (c & 1)) & 0x00FFFFFF;
    757 }
    758 
    759 static bool is_rgb_really_bw(const SkGdiRGB* src, int width, int height, int srcRB) {
    760     for (int y = 0; y < height; ++y) {
    761         for (int x = 0; x < width; ++x) {
    762             if (is_not_black_or_white(src[x])) {
    763                 return false;
    764             }
    765         }
    766         src = SkTAddByteOffset(src, srcRB);
    767     }
    768     return true;
    769 }
    770 
    771 static void rgb_to_bw(const SkGdiRGB* SK_RESTRICT src, size_t srcRB,
    772                       const SkGlyph& glyph, int32_t xorMask) {
    773     const int width = glyph.fWidth;
    774     const size_t dstRB = (width + 7) >> 3;
    775     uint8_t* SK_RESTRICT dst = (uint8_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB);
    776 
    777     int byteCount = width >> 3;
    778     int bitCount = width & 7;
    779 
    780     // adjust srcRB to skip the values in our byteCount loop,
    781     // since we increment src locally there
    782     srcRB -= byteCount * 8 * sizeof(SkGdiRGB);
    783 
    784     for (int y = 0; y < glyph.fHeight; ++y) {
    785         if (byteCount > 0) {
    786             for (int i = 0; i < byteCount; ++i) {
    787                 unsigned byte = 0;
    788                 byte |= (src[0] ^ xorMask) & (1 << 7);
    789                 byte |= (src[1] ^ xorMask) & (1 << 6);
    790                 byte |= (src[2] ^ xorMask) & (1 << 5);
    791                 byte |= (src[3] ^ xorMask) & (1 << 4);
    792                 byte |= (src[4] ^ xorMask) & (1 << 3);
    793                 byte |= (src[5] ^ xorMask) & (1 << 2);
    794                 byte |= (src[6] ^ xorMask) & (1 << 1);
    795                 byte |= (src[7] ^ xorMask) & (1 << 0);
    796                 dst[i] = byte;
    797                 src += 8;
    798             }
    799         }
    800         if (bitCount > 0) {
    801             unsigned byte = 0;
    802             unsigned mask = 0x80;
    803             for (int i = 0; i < bitCount; i++) {
    804                 byte |= (src[i] ^ xorMask) & mask;
    805                 mask >>= 1;
    806             }
    807             dst[byteCount] = byte;
    808         }
    809         src = SkTAddByteOffset(src, srcRB);
    810         dst -= dstRB;
    811     }
    812 }
    813 
    814 static void rgb_to_a8(const SkGdiRGB* SK_RESTRICT src, size_t srcRB,
    815                       const SkGlyph& glyph, int32_t xorMask) {
    816     const size_t dstRB = glyph.rowBytes();
    817     const int width = glyph.fWidth;
    818     uint8_t* SK_RESTRICT dst = (uint8_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB);
    819 
    820     for (int y = 0; y < glyph.fHeight; y++) {
    821         for (int i = 0; i < width; i++) {
    822             dst[i] = rgb_to_a8(src[i] ^ xorMask);
    823         }
    824         src = SkTAddByteOffset(src, srcRB);
    825         dst -= dstRB;
    826     }
    827 }
    828 
    829 static void rgb_to_lcd16(const SkGdiRGB* SK_RESTRICT src, size_t srcRB,
    830                          const SkGlyph& glyph, int32_t xorMask) {
    831     const size_t dstRB = glyph.rowBytes();
    832     const int width = glyph.fWidth;
    833     uint16_t* SK_RESTRICT dst = (uint16_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB);
    834 
    835     for (int y = 0; y < glyph.fHeight; y++) {
    836         for (int i = 0; i < width; i++) {
    837             dst[i] = rgb_to_lcd16(src[i] ^ xorMask);
    838         }
    839         src = SkTAddByteOffset(src, srcRB);
    840         dst = (uint16_t*)((char*)dst - dstRB);
    841     }
    842 }
    843 
    844 static void rgb_to_lcd32(const SkGdiRGB* SK_RESTRICT src, size_t srcRB,
    845                          const SkGlyph& glyph, int32_t xorMask) {
    846     const size_t dstRB = glyph.rowBytes();
    847     const int width = glyph.fWidth;
    848     SkPMColor* SK_RESTRICT dst = (SkPMColor*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB);
    849 
    850     for (int y = 0; y < glyph.fHeight; y++) {
    851         for (int i = 0; i < width; i++) {
    852             dst[i] = rgb_to_lcd32(src[i] ^ xorMask);
    853         }
    854         src = SkTAddByteOffset(src, srcRB);
    855         dst = (SkPMColor*)((char*)dst - dstRB);
    856     }
    857 }
    858 
    859 static inline unsigned clamp255(unsigned x) {
    860     SkASSERT(x <= 256);
    861     return x - (x >> 8);
    862 }
    863 
    864 #define WHITE_LUMINANCE_LIMIT   0xA0
    865 #define BLACK_LUMINANCE_LIMIT   0x40
    866 
    867 void SkScalerContext_Windows::generateImage(const SkGlyph& glyph) {
    868     SkAutoMutexAcquire  ac(gFTMutex);
    869 
    870     SkASSERT(fDDC);
    871 
    872     const bool isBW = SkMask::kBW_Format == fRec.fMaskFormat;
    873     const bool isAA = !isLCD(fRec);
    874     bool isWhite = fRec.getLuminanceByte() >= WHITE_LUMINANCE_LIMIT;
    875     bool isBlack = fRec.getLuminanceByte() <= BLACK_LUMINANCE_LIMIT;
    876 
    877     SkGdiRGB fgColor;
    878     uint32_t rgbXOR;
    879     const uint8_t* table = NULL;
    880     if (isBW || isWhite) {
    881         fgColor = 0x00FFFFFF;
    882         rgbXOR = 0;
    883     } else if (isBlack) {
    884         fgColor = 0;
    885         rgbXOR = ~0;
    886     } else {
    887         table = getInverseGammaTable();
    888         fgColor = 0x00FFFFFF;
    889         rgbXOR = 0;
    890     }
    891 
    892     size_t srcRB;
    893     const void* bits = fOffscreen.draw(glyph, isBW, fgColor, &srcRB);
    894     if (NULL == bits) {
    895         ensure_typeface_accessible(fRec.fFontID);
    896         bits = fOffscreen.draw(glyph, isBW, fgColor, &srcRB);
    897         if (NULL == bits) {
    898             sk_bzero(glyph.fImage, glyph.computeImageSize());
    899             return;
    900         }
    901     }
    902 
    903     if (table) {
    904         SkGdiRGB* addr = (SkGdiRGB*)bits;
    905         for (int y = 0; y < glyph.fHeight; ++y) {
    906             for (int x = 0; x < glyph.fWidth; ++x) {
    907                 int r = (addr[x] >> 16) & 0xFF;
    908                 int g = (addr[x] >>  8) & 0xFF;
    909                 int b = (addr[x] >>  0) & 0xFF;
    910                 addr[x] = (table[r] << 16) | (table[g] << 8) | table[b];
    911             }
    912             addr = SkTAddByteOffset(addr, srcRB);
    913         }
    914     }
    915 
    916     int width = glyph.fWidth;
    917     size_t dstRB = glyph.rowBytes();
    918     if (isBW) {
    919         const uint8_t* src = (const uint8_t*)bits;
    920         uint8_t* dst = (uint8_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB);
    921         for (int y = 0; y < glyph.fHeight; y++) {
    922             memcpy(dst, src, dstRB);
    923             src += srcRB;
    924             dst -= dstRB;
    925         }
    926     } else if (isAA) {
    927         // since the caller may require A8 for maskfilters, we can't check for BW
    928         // ... until we have the caller tell us that explicitly
    929         const SkGdiRGB* src = (const SkGdiRGB*)bits;
    930         rgb_to_a8(src, srcRB, glyph, rgbXOR);
    931     } else {    // LCD16
    932         const SkGdiRGB* src = (const SkGdiRGB*)bits;
    933         if (is_rgb_really_bw(src, width, glyph.fHeight, srcRB)) {
    934             rgb_to_bw(src, srcRB, glyph, rgbXOR);
    935             ((SkGlyph*)&glyph)->fMaskFormat = SkMask::kBW_Format;
    936         } else {
    937             if (SkMask::kLCD16_Format == glyph.fMaskFormat) {
    938                 rgb_to_lcd16(src, srcRB, glyph, rgbXOR);
    939             } else {
    940                 SkASSERT(SkMask::kLCD32_Format == glyph.fMaskFormat);
    941                 rgb_to_lcd32(src, srcRB, glyph, rgbXOR);
    942             }
    943         }
    944     }
    945 }
    946 
    947 void SkScalerContext_Windows::generatePath(const SkGlyph& glyph, SkPath* path) {
    948 
    949     SkAutoMutexAcquire  ac(gFTMutex);
    950 
    951     SkASSERT(&glyph && path);
    952     SkASSERT(fDDC);
    953 
    954     path->reset();
    955 
    956 #if 0
    957     char buf[1024];
    958     sprintf(buf, "generatePath: id:%d, w=%d, h=%d, font:%s,fh:%d\n", glyph.fID, glyph.fWidth, glyph.fHeight, lf.lfFaceName, lf.lfHeight);
    959     OutputDebugString(buf);
    960 #endif
    961 
    962     GLYPHMETRICS gm;
    963     uint32_t total_size = GetGlyphOutlineW(fDDC, glyph.fID, GGO_NATIVE | GGO_GLYPH_INDEX, &gm, BUFFERSIZE, glyphbuf, &fMat22);
    964     if (GDI_ERROR == total_size) {
    965         ensure_typeface_accessible(fRec.fFontID);
    966         total_size = GetGlyphOutlineW(fDDC, glyph.fID, GGO_NATIVE | GGO_GLYPH_INDEX, &gm, BUFFERSIZE, glyphbuf, &fMat22);
    967     }
    968 
    969     if (GDI_ERROR != total_size) {
    970 
    971         const uint8_t* cur_glyph = glyphbuf;
    972         const uint8_t* end_glyph = glyphbuf + total_size;
    973 
    974         while(cur_glyph < end_glyph) {
    975             const TTPOLYGONHEADER* th = (TTPOLYGONHEADER*)cur_glyph;
    976 
    977             const uint8_t* end_poly = cur_glyph + th->cb;
    978             const uint8_t* cur_poly = cur_glyph + sizeof(TTPOLYGONHEADER);
    979 
    980             path->moveTo(SkFixedToScalar(*(SkFixed*)(&th->pfxStart.x)), SkFixedToScalar(*(SkFixed*)(&th->pfxStart.y)));
    981 
    982             while(cur_poly < end_poly) {
    983                 const TTPOLYCURVE* pc = (const TTPOLYCURVE*)cur_poly;
    984 
    985                 if (pc->wType == TT_PRIM_LINE) {
    986                     for (uint16_t i = 0; i < pc->cpfx; i++) {
    987                         path->lineTo(SkFixedToScalar(*(SkFixed*)(&pc->apfx[i].x)), SkFixedToScalar(*(SkFixed*)(&pc->apfx[i].y)));
    988                     }
    989                 }
    990 
    991                 if (pc->wType == TT_PRIM_QSPLINE) {
    992                     for (uint16_t u = 0; u < pc->cpfx - 1; u++) { // Walk through points in spline
    993                         POINTFX pnt_b = pc->apfx[u];    // B is always the current point
    994                         POINTFX pnt_c = pc->apfx[u+1];
    995 
    996                         if (u < pc->cpfx - 2) {          // If not on last spline, compute C
    997                             pnt_c.x = SkFixedToFIXED(SkFixedAve(*(SkFixed*)(&pnt_b.x), *(SkFixed*)(&pnt_c.x)));
    998                             pnt_c.y = SkFixedToFIXED(SkFixedAve(*(SkFixed*)(&pnt_b.y), *(SkFixed*)(&pnt_c.y)));
    999                         }
   1000 
   1001                         path->quadTo(SkFixedToScalar(*(SkFixed*)(&pnt_b.x)), SkFixedToScalar(*(SkFixed*)(&pnt_b.y)), SkFixedToScalar(*(SkFixed*)(&pnt_c.x)), SkFixedToScalar(*(SkFixed*)(&pnt_c.y)));
   1002                     }
   1003                 }
   1004                 cur_poly += sizeof(uint16_t) * 2 + sizeof(POINTFX) * pc->cpfx;
   1005             }
   1006             cur_glyph += th->cb;
   1007             path->close();
   1008         }
   1009     }
   1010     else {
   1011         SkASSERT(false);
   1012     }
   1013     //char buf[1024];
   1014     //sprintf(buf, "generatePath: count:%d\n", count);
   1015     //OutputDebugString(buf);
   1016 }
   1017 
   1018 void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) {
   1019     SkDEBUGFAIL("SkFontHost::Serialize unimplemented");
   1020 }
   1021 
   1022 SkTypeface* SkFontHost::Deserialize(SkStream* stream) {
   1023     SkDEBUGFAIL("SkFontHost::Deserialize unimplemented");
   1024     return NULL;
   1025 }
   1026 
   1027 static bool getWidthAdvance(HDC hdc, int gId, int16_t* advance) {
   1028     // Initialize the MAT2 structure to the identify transformation matrix.
   1029     static const MAT2 mat2 = {SkScalarToFIXED(1), SkScalarToFIXED(0),
   1030                         SkScalarToFIXED(0), SkScalarToFIXED(1)};
   1031     int flags = GGO_METRICS | GGO_GLYPH_INDEX;
   1032     GLYPHMETRICS gm;
   1033     if (GDI_ERROR == GetGlyphOutline(hdc, gId, flags, &gm, 0, NULL, &mat2)) {
   1034         return false;
   1035     }
   1036     SkASSERT(advance);
   1037     *advance = gm.gmCellIncX;
   1038     return true;
   1039 }
   1040 
   1041 // static
   1042 SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
   1043         uint32_t fontID,
   1044         SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo,
   1045         const uint32_t* glyphIDs,
   1046         uint32_t glyphIDsCount) {
   1047     LOGFONT lf;
   1048     GetLogFontByID(fontID, &lf);
   1049     SkAdvancedTypefaceMetrics* info = NULL;
   1050 
   1051     HDC hdc = CreateCompatibleDC(NULL);
   1052     HFONT font = CreateFontIndirect(&lf);
   1053     HFONT savefont = (HFONT)SelectObject(hdc, font);
   1054     HFONT designFont = NULL;
   1055 
   1056     const char stem_chars[] = {'i', 'I', '!', '1'};
   1057     int16_t min_width;
   1058     unsigned glyphCount;
   1059 
   1060     // To request design units, create a logical font whose height is specified
   1061     // as unitsPerEm.
   1062     OUTLINETEXTMETRIC otm;
   1063     unsigned int otmRet = GetOutlineTextMetrics(hdc, sizeof(otm), &otm);
   1064     if (0 == otmRet) {
   1065         ensure_typeface_accessible(fontID);
   1066         otmRet = GetOutlineTextMetrics(hdc, sizeof(otm), &otm);
   1067     }
   1068     if (!otmRet || !GetTextFace(hdc, LF_FACESIZE, lf.lfFaceName)) {
   1069         goto Error;
   1070     }
   1071     lf.lfHeight = -SkToS32(otm.otmEMSquare);
   1072     designFont = CreateFontIndirect(&lf);
   1073     SelectObject(hdc, designFont);
   1074     if (!GetOutlineTextMetrics(hdc, sizeof(otm), &otm)) {
   1075         goto Error;
   1076     }
   1077     glyphCount = calculateGlyphCount(hdc);
   1078 
   1079     info = new SkAdvancedTypefaceMetrics;
   1080     info->fEmSize = otm.otmEMSquare;
   1081     info->fMultiMaster = false;
   1082     info->fLastGlyphID = SkToU16(glyphCount - 1);
   1083     info->fStyle = 0;
   1084 #ifdef UNICODE
   1085     // Get the buffer size needed first.
   1086     size_t str_len = WideCharToMultiByte(CP_UTF8, 0, lf.lfFaceName, -1, NULL,
   1087                                          0, NULL, NULL);
   1088     // Allocate a buffer (str_len already has terminating null accounted for).
   1089     char *familyName = new char[str_len];
   1090     // Now actually convert the string.
   1091     WideCharToMultiByte(CP_UTF8, 0, lf.lfFaceName, -1, familyName, str_len,
   1092                           NULL, NULL);
   1093     info->fFontName.set(familyName);
   1094     delete [] familyName;
   1095 #else
   1096     info->fFontName.set(lf.lfFaceName);
   1097 #endif
   1098 
   1099     if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo) {
   1100         populate_glyph_to_unicode(hdc, glyphCount, &(info->fGlyphToUnicode));
   1101     }
   1102 
   1103     if (otm.otmTextMetrics.tmPitchAndFamily & TMPF_TRUETYPE) {
   1104         info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font;
   1105     } else {
   1106         info->fType = SkAdvancedTypefaceMetrics::kOther_Font;
   1107         info->fItalicAngle = 0;
   1108         info->fAscent = 0;
   1109         info->fDescent = 0;
   1110         info->fStemV = 0;
   1111         info->fCapHeight = 0;
   1112         info->fBBox = SkIRect::MakeEmpty();
   1113         return info;
   1114     }
   1115 
   1116     // If this bit is clear the font is a fixed pitch font.
   1117     if (!(otm.otmTextMetrics.tmPitchAndFamily & TMPF_FIXED_PITCH)) {
   1118         info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;
   1119     }
   1120     if (otm.otmTextMetrics.tmItalic) {
   1121         info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style;
   1122     }
   1123     // Setting symbolic style by default for now.
   1124     info->fStyle |= SkAdvancedTypefaceMetrics::kSymbolic_Style;
   1125     if (otm.otmTextMetrics.tmPitchAndFamily & FF_ROMAN) {
   1126         info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;
   1127     } else if (otm.otmTextMetrics.tmPitchAndFamily & FF_SCRIPT) {
   1128             info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;
   1129     }
   1130 
   1131     // The main italic angle of the font, in tenths of a degree counterclockwise
   1132     // from vertical.
   1133     info->fItalicAngle = otm.otmItalicAngle / 10;
   1134     info->fAscent = SkToS16(otm.otmTextMetrics.tmAscent);
   1135     info->fDescent = SkToS16(-otm.otmTextMetrics.tmDescent);
   1136     // TODO(ctguil): Use alternate cap height calculation.
   1137     // MSDN says otmsCapEmHeight is not support but it is returning a value on
   1138     // my Win7 box.
   1139     info->fCapHeight = otm.otmsCapEmHeight;
   1140     info->fBBox =
   1141         SkIRect::MakeLTRB(otm.otmrcFontBox.left, otm.otmrcFontBox.top,
   1142                           otm.otmrcFontBox.right, otm.otmrcFontBox.bottom);
   1143 
   1144     // Figure out a good guess for StemV - Min width of i, I, !, 1.
   1145     // This probably isn't very good with an italic font.
   1146     min_width = SHRT_MAX;
   1147     info->fStemV = 0;
   1148     for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) {
   1149         ABC abcWidths;
   1150         if (GetCharABCWidths(hdc, stem_chars[i], stem_chars[i], &abcWidths)) {
   1151             int16_t width = abcWidths.abcB;
   1152             if (width > 0 && width < min_width) {
   1153                 min_width = width;
   1154                 info->fStemV = min_width;
   1155             }
   1156         }
   1157     }
   1158 
   1159     // If bit 1 is set, the font may not be embedded in a document.
   1160     // If bit 1 is clear, the font can be embedded.
   1161     // If bit 2 is set, the embedding is read-only.
   1162     if (otm.otmfsType & 0x1) {
   1163         info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font;
   1164     } else if (perGlyphInfo &
   1165                SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo) {
   1166         if (info->fStyle & SkAdvancedTypefaceMetrics::kFixedPitch_Style) {
   1167             appendRange(&info->fGlyphWidths, 0);
   1168             info->fGlyphWidths->fAdvance.append(1, &min_width);
   1169             finishRange(info->fGlyphWidths.get(), 0,
   1170                         SkAdvancedTypefaceMetrics::WidthRange::kDefault);
   1171         } else {
   1172             info->fGlyphWidths.reset(
   1173                 getAdvanceData(hdc,
   1174                                glyphCount,
   1175                                glyphIDs,
   1176                                glyphIDsCount,
   1177                                &getWidthAdvance));
   1178         }
   1179     }
   1180 
   1181 Error:
   1182     SelectObject(hdc, savefont);
   1183     DeleteObject(designFont);
   1184     DeleteObject(font);
   1185     DeleteDC(hdc);
   1186 
   1187     return info;
   1188 }
   1189 
   1190 SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
   1191 
   1192     //Should not be used on Windows, keep linker happy
   1193     SkASSERT(false);
   1194     return SkCreateTypefaceFromLOGFONT(get_default_font());
   1195 }
   1196 
   1197 SkStream* SkFontHost::OpenStream(SkFontID uniqueID) {
   1198     const DWORD kTTCTag =
   1199         SkEndian_SwapBE32(SkSetFourByteTag('t', 't', 'c', 'f'));
   1200     LOGFONT lf;
   1201     GetLogFontByID(uniqueID, &lf);
   1202 
   1203     HDC hdc = ::CreateCompatibleDC(NULL);
   1204     HFONT font = CreateFontIndirect(&lf);
   1205     HFONT savefont = (HFONT)SelectObject(hdc, font);
   1206 
   1207     SkMemoryStream* stream = NULL;
   1208     DWORD tables[2] = {kTTCTag, 0};
   1209     for (int i = 0; i < SK_ARRAY_COUNT(tables); i++) {
   1210         size_t bufferSize = GetFontData(hdc, tables[i], 0, NULL, 0);
   1211         if (bufferSize == GDI_ERROR) {
   1212             ensure_typeface_accessible(uniqueID);
   1213             bufferSize = GetFontData(hdc, tables[i], 0, NULL, 0);
   1214         }
   1215         if (bufferSize != GDI_ERROR) {
   1216             stream = new SkMemoryStream(bufferSize);
   1217             if (GetFontData(hdc, tables[i], 0, (void*)stream->getMemoryBase(),
   1218                             bufferSize)) {
   1219                 break;
   1220             } else {
   1221                 delete stream;
   1222                 stream = NULL;
   1223             }
   1224         }
   1225     }
   1226 
   1227     SelectObject(hdc, savefont);
   1228     DeleteObject(font);
   1229     DeleteDC(hdc);
   1230 
   1231     return stream;
   1232 }
   1233 
   1234 SkScalerContext* SkFontHost::CreateScalerContext(const SkDescriptor* desc) {
   1235     return SkNEW_ARGS(SkScalerContext_Windows, (desc));
   1236 }
   1237 
   1238 /** Return the closest matching typeface given either an existing family
   1239  (specified by a typeface in that family) or by a familyName, and a
   1240  requested style.
   1241  1) If familyFace is null, use familyName.
   1242  2) If familyName is null, use familyFace.
   1243  3) If both are null, return the default font that best matches style
   1244  This MUST not return NULL.
   1245  */
   1246 
   1247 SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
   1248                                        const char familyName[],
   1249                                        const void* data, size_t bytelength,
   1250                                        SkTypeface::Style style) {
   1251     LOGFONT lf;
   1252     if (NULL == familyFace && NULL == familyName) {
   1253         lf = get_default_font();
   1254     } else if (familyFace) {
   1255         LogFontTypeface* face = (LogFontTypeface*)familyFace;
   1256         lf = face->fLogFont;
   1257     } else {
   1258         memset(&lf, 0, sizeof(LOGFONT));
   1259 #ifdef UNICODE
   1260         // Get the buffer size needed first.
   1261         size_t str_len = ::MultiByteToWideChar(CP_UTF8, 0, familyName,
   1262                                                 -1, NULL, 0);
   1263         // Allocate a buffer (str_len already has terminating null
   1264         // accounted for).
   1265         wchar_t *wideFamilyName = new wchar_t[str_len];
   1266         // Now actually convert the string.
   1267         ::MultiByteToWideChar(CP_UTF8, 0, familyName, -1,
   1268                                 wideFamilyName, str_len);
   1269         ::wcsncpy(lf.lfFaceName, wideFamilyName, LF_FACESIZE);
   1270         delete [] wideFamilyName;
   1271 #else
   1272         ::strncpy(lf.lfFaceName, familyName, LF_FACESIZE);
   1273 #endif
   1274         lf.lfFaceName[LF_FACESIZE-1] = '\0';
   1275     }
   1276     setStyle(&lf, style);
   1277     return SkCreateTypefaceFromLOGFONT(lf);
   1278 }
   1279 
   1280 SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
   1281     printf("SkFontHost::CreateTypefaceFromFile unimplemented");
   1282     return NULL;
   1283 }
   1284 
   1285 void SkFontHost::FilterRec(SkScalerContext::Rec* rec) {
   1286     unsigned flagsWeDontSupport = SkScalerContext::kDevKernText_Flag |
   1287                                   SkScalerContext::kAutohinting_Flag |
   1288                                   SkScalerContext::kEmbeddedBitmapText_Flag |
   1289                                   SkScalerContext::kEmbolden_Flag |
   1290                                   SkScalerContext::kSubpixelPositioning_Flag |
   1291                                   SkScalerContext::kLCD_BGROrder_Flag |
   1292                                   SkScalerContext::kLCD_Vertical_Flag;
   1293     rec->fFlags &= ~flagsWeDontSupport;
   1294 
   1295     SkPaint::Hinting h = rec->getHinting();
   1296 
   1297     // I think we can support no-hinting, if we get hires outlines and just
   1298     // use skia to rasterize into a gray-scale mask...
   1299 #if 0
   1300     switch (h) {
   1301         case SkPaint::kNo_Hinting:
   1302         case SkPaint::kSlight_Hinting:
   1303             h = SkPaint::kNo_Hinting;
   1304             break;
   1305         case SkPaint::kNormal_Hinting:
   1306         case SkPaint::kFull_Hinting:
   1307             h = SkPaint::kNormal_Hinting;
   1308             break;
   1309         default:
   1310             SkDEBUGFAIL("unknown hinting");
   1311     }
   1312 #else
   1313     h = SkPaint::kNormal_Hinting;
   1314 #endif
   1315     rec->setHinting(h);
   1316 
   1317     // for compatibility at the moment, discretize luminance to 3 settings
   1318     // black, white, gray. This helps with fontcache utilization, since we
   1319     // won't create multiple entries that in the end map to the same results.
   1320     {
   1321         unsigned lum = rec->getLuminanceByte();
   1322         if (lum <= BLACK_LUMINANCE_LIMIT) {
   1323             lum = 0;
   1324         } else if (lum >= WHITE_LUMINANCE_LIMIT) {
   1325             lum = SkScalerContext::kLuminance_Max;
   1326         } else {
   1327             lum = SkScalerContext::kLuminance_Max >> 1;
   1328         }
   1329         rec->setLuminanceBits(lum);
   1330     }
   1331 
   1332 // turn this off since GDI might turn A8 into BW! Need a bigger fix.
   1333 #if 0
   1334     // Disable LCD when rotated, since GDI's output is ugly
   1335     if (isLCD(*rec) && !isAxisAligned(*rec)) {
   1336         rec->fMaskFormat = SkMask::kA8_Format;
   1337     }
   1338 #endif
   1339 
   1340 #if 0
   1341     if (SkMask::kLCD16_Format == rec->fMaskFormat) {
   1342         rec->fMaskFormat = SkMask::kLCD32_Format;
   1343     }
   1344 #endif
   1345 }
   1346 
   1347 #endif // WIN32
   1348