Home | History | Annotate | Download | only in ports
      1 /*
      2  * Copyright 2006 The Android Open Source Project
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkTypes.h"
      9 #if defined(SK_BUILD_FOR_WIN32)
     10 
     11 #include "SkAdvancedTypefaceMetrics.h"
     12 #include "SkBase64.h"
     13 #include "SkColorPriv.h"
     14 #include "SkData.h"
     15 #include "SkDescriptor.h"
     16 #include "SkFontDescriptor.h"
     17 #include "SkGlyph.h"
     18 #include "SkHRESULT.h"
     19 #include "SkMaskGamma.h"
     20 #include "SkMatrix22.h"
     21 #include "SkOTTable_maxp.h"
     22 #include "SkOTTable_name.h"
     23 #include "SkOTUtils.h"
     24 #include "SkPath.h"
     25 #include "SkSFNTHeader.h"
     26 #include "SkStream.h"
     27 #include "SkString.h"
     28 #include "SkTemplates.h"
     29 #include "SkTypeface_win.h"
     30 #include "SkTypefaceCache.h"
     31 #include "SkUtils.h"
     32 
     33 #include "SkTypes.h"
     34 #include <tchar.h>
     35 #include <usp10.h>
     36 #include <objbase.h>
     37 
     38 static void (*gEnsureLOGFONTAccessibleProc)(const LOGFONT&);
     39 
     40 void SkTypeface_SetEnsureLOGFONTAccessibleProc(void (*proc)(const LOGFONT&)) {
     41     gEnsureLOGFONTAccessibleProc = proc;
     42 }
     43 
     44 static void call_ensure_accessible(const LOGFONT& lf) {
     45     if (gEnsureLOGFONTAccessibleProc) {
     46         gEnsureLOGFONTAccessibleProc(lf);
     47     }
     48 }
     49 
     50 ///////////////////////////////////////////////////////////////////////////////
     51 
     52 // always packed xxRRGGBB
     53 typedef uint32_t SkGdiRGB;
     54 
     55 // define this in your Makefile or .gyp to enforce AA requests
     56 // which GDI ignores at small sizes. This flag guarantees AA
     57 // for rotated text, regardless of GDI's notions.
     58 //#define SK_ENFORCE_ROTATED_TEXT_AA_ON_WINDOWS
     59 
     60 static bool isLCD(const SkScalerContext::Rec& rec) {
     61     return SkMask::kLCD16_Format == rec.fMaskFormat;
     62 }
     63 
     64 static bool bothZero(SkScalar a, SkScalar b) {
     65     return 0 == a && 0 == b;
     66 }
     67 
     68 // returns false if there is any non-90-rotation or skew
     69 static bool isAxisAligned(const SkScalerContext::Rec& rec) {
     70     return 0 == rec.fPreSkewX &&
     71            (bothZero(rec.fPost2x2[0][1], rec.fPost2x2[1][0]) ||
     72             bothZero(rec.fPost2x2[0][0], rec.fPost2x2[1][1]));
     73 }
     74 
     75 static bool needToRenderWithSkia(const SkScalerContext::Rec& rec) {
     76 #ifdef SK_ENFORCE_ROTATED_TEXT_AA_ON_WINDOWS
     77     // What we really want to catch is when GDI will ignore the AA request and give
     78     // us BW instead. Smallish rotated text is one heuristic, so this code is just
     79     // an approximation. We shouldn't need to do this for larger sizes, but at those
     80     // sizes, the quality difference gets less and less between our general
     81     // scanconverter and GDI's.
     82     if (SkMask::kA8_Format == rec.fMaskFormat && !isAxisAligned(rec)) {
     83         return true;
     84     }
     85 #endif
     86     return rec.getHinting() == SkPaint::kNo_Hinting || rec.getHinting() == SkPaint::kSlight_Hinting;
     87 }
     88 
     89 using namespace skia_advanced_typeface_metrics_utils;
     90 
     91 static void tchar_to_skstring(const TCHAR t[], SkString* s) {
     92 #ifdef UNICODE
     93     size_t sSize = WideCharToMultiByte(CP_UTF8, 0, t, -1, nullptr, 0, nullptr, nullptr);
     94     s->resize(sSize);
     95     WideCharToMultiByte(CP_UTF8, 0, t, -1, s->writable_str(), sSize, nullptr, nullptr);
     96 #else
     97     s->set(t);
     98 #endif
     99 }
    100 
    101 static void dcfontname_to_skstring(HDC deviceContext, const LOGFONT& lf, SkString* familyName) {
    102     int fontNameLen; //length of fontName in TCHARS.
    103     if (0 == (fontNameLen = GetTextFace(deviceContext, 0, nullptr))) {
    104         call_ensure_accessible(lf);
    105         if (0 == (fontNameLen = GetTextFace(deviceContext, 0, nullptr))) {
    106             fontNameLen = 0;
    107         }
    108     }
    109 
    110     SkAutoSTArray<LF_FULLFACESIZE, TCHAR> fontName(fontNameLen+1);
    111     if (0 == GetTextFace(deviceContext, fontNameLen, fontName.get())) {
    112         call_ensure_accessible(lf);
    113         if (0 == GetTextFace(deviceContext, fontNameLen, fontName.get())) {
    114             fontName[0] = 0;
    115         }
    116     }
    117 
    118     tchar_to_skstring(fontName.get(), familyName);
    119 }
    120 
    121 static void make_canonical(LOGFONT* lf) {
    122     lf->lfHeight = -64;
    123     lf->lfQuality = CLEARTYPE_QUALITY;//PROOF_QUALITY;
    124     lf->lfCharSet = DEFAULT_CHARSET;
    125 //    lf->lfClipPrecision = 64;
    126 }
    127 
    128 static SkFontStyle get_style(const LOGFONT& lf) {
    129     return SkFontStyle(lf.lfWeight,
    130                        lf.lfWidth,
    131                        lf.lfItalic ? SkFontStyle::kItalic_Slant : SkFontStyle::kUpright_Slant);
    132 }
    133 
    134 static inline FIXED SkFixedToFIXED(SkFixed x) {
    135     return *(FIXED*)(&x);
    136 }
    137 static inline SkFixed SkFIXEDToFixed(FIXED x) {
    138     return *(SkFixed*)(&x);
    139 }
    140 
    141 static inline FIXED SkScalarToFIXED(SkScalar x) {
    142     return SkFixedToFIXED(SkScalarToFixed(x));
    143 }
    144 
    145 static inline SkScalar SkFIXEDToScalar(FIXED x) {
    146     return SkFixedToScalar(SkFIXEDToFixed(x));
    147 }
    148 
    149 static unsigned calculateGlyphCount(HDC hdc, const LOGFONT& lf) {
    150     TEXTMETRIC textMetric;
    151     if (0 == GetTextMetrics(hdc, &textMetric)) {
    152         textMetric.tmPitchAndFamily = TMPF_VECTOR;
    153         call_ensure_accessible(lf);
    154         GetTextMetrics(hdc, &textMetric);
    155     }
    156 
    157     if (!(textMetric.tmPitchAndFamily & TMPF_VECTOR)) {
    158         return textMetric.tmLastChar;
    159     }
    160 
    161     // The 'maxp' table stores the number of glyphs at offset 4, in 2 bytes.
    162     uint16_t glyphs;
    163     if (GDI_ERROR != GetFontData(hdc, SkOTTableMaximumProfile::TAG, 4, &glyphs, sizeof(glyphs))) {
    164         return SkEndian_SwapBE16(glyphs);
    165     }
    166 
    167     // Binary search for glyph count.
    168     static const MAT2 mat2 = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
    169     int32_t max = SK_MaxU16 + 1;
    170     int32_t min = 0;
    171     GLYPHMETRICS gm;
    172     while (min < max) {
    173         int32_t mid = min + ((max - min) / 2);
    174         if (GetGlyphOutlineW(hdc, mid, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0,
    175                              nullptr, &mat2) == GDI_ERROR) {
    176             max = mid;
    177         } else {
    178             min = mid + 1;
    179         }
    180     }
    181     SkASSERT(min == max);
    182     return min;
    183 }
    184 
    185 static unsigned calculateUPEM(HDC hdc, const LOGFONT& lf) {
    186     TEXTMETRIC textMetric;
    187     if (0 == GetTextMetrics(hdc, &textMetric)) {
    188         textMetric.tmPitchAndFamily = TMPF_VECTOR;
    189         call_ensure_accessible(lf);
    190         GetTextMetrics(hdc, &textMetric);
    191     }
    192 
    193     if (!(textMetric.tmPitchAndFamily & TMPF_VECTOR)) {
    194         return textMetric.tmMaxCharWidth;
    195     }
    196 
    197     OUTLINETEXTMETRIC otm;
    198     unsigned int otmRet = GetOutlineTextMetrics(hdc, sizeof(otm), &otm);
    199     if (0 == otmRet) {
    200         call_ensure_accessible(lf);
    201         otmRet = GetOutlineTextMetrics(hdc, sizeof(otm), &otm);
    202     }
    203 
    204     return (0 == otmRet) ? 0 : otm.otmEMSquare;
    205 }
    206 
    207 class LogFontTypeface : public SkTypeface {
    208 public:
    209     LogFontTypeface(const SkFontStyle& style, const LOGFONT& lf, bool serializeAsStream)
    210         : SkTypeface(style, SkTypefaceCache::NewFontID(), false)
    211         , fLogFont(lf)
    212         , fSerializeAsStream(serializeAsStream)
    213     {
    214 
    215         // If the font has cubic outlines, it will not be rendered with ClearType.
    216         HFONT font = CreateFontIndirect(&lf);
    217 
    218         HDC deviceContext = ::CreateCompatibleDC(nullptr);
    219         HFONT savefont = (HFONT)SelectObject(deviceContext, font);
    220 
    221         TEXTMETRIC textMetric;
    222         if (0 == GetTextMetrics(deviceContext, &textMetric)) {
    223             call_ensure_accessible(lf);
    224             if (0 == GetTextMetrics(deviceContext, &textMetric)) {
    225                 textMetric.tmPitchAndFamily = TMPF_TRUETYPE;
    226             }
    227         }
    228         if (deviceContext) {
    229             ::SelectObject(deviceContext, savefont);
    230             ::DeleteDC(deviceContext);
    231         }
    232         if (font) {
    233             ::DeleteObject(font);
    234         }
    235 
    236         // The fixed pitch bit is set if the font is *not* fixed pitch.
    237         this->setIsFixedPitch((textMetric.tmPitchAndFamily & TMPF_FIXED_PITCH) == 0);
    238 
    239         // Used a logfont on a memory context, should never get a device font.
    240         // Therefore all TMPF_DEVICE will be PostScript (cubic) fonts.
    241         fCanBeLCD = !((textMetric.tmPitchAndFamily & TMPF_VECTOR) &&
    242                       (textMetric.tmPitchAndFamily & TMPF_DEVICE));
    243     }
    244 
    245     LOGFONT fLogFont;
    246     bool fSerializeAsStream;
    247     bool fCanBeLCD;
    248 
    249     static LogFontTypeface* Create(const LOGFONT& lf) {
    250         return new LogFontTypeface(get_style(lf), lf, false);
    251     }
    252 
    253     static void EnsureAccessible(const SkTypeface* face) {
    254         call_ensure_accessible(static_cast<const LogFontTypeface*>(face)->fLogFont);
    255     }
    256 
    257 protected:
    258     SkStreamAsset* onOpenStream(int* ttcIndex) const override;
    259     SkScalerContext* onCreateScalerContext(const SkDescriptor*) const override;
    260     void onFilterRec(SkScalerContextRec*) const override;
    261     SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics(
    262                                 PerGlyphInfo, const uint32_t*, uint32_t) const override;
    263     void onGetFontDescriptor(SkFontDescriptor*, bool*) const override;
    264     virtual int onCharsToGlyphs(const void* chars, Encoding encoding,
    265                                 uint16_t glyphs[], int glyphCount) const override;
    266     int onCountGlyphs() const override;
    267     int onGetUPEM() const override;
    268     void onGetFamilyName(SkString* familyName) const override;
    269     SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const override;
    270     int onGetTableTags(SkFontTableTag tags[]) const override;
    271     virtual size_t onGetTableData(SkFontTableTag, size_t offset,
    272                                   size_t length, void* data) const override;
    273 };
    274 
    275 class FontMemResourceTypeface : public LogFontTypeface {
    276 public:
    277     /**
    278      *  The created FontMemResourceTypeface takes ownership of fontMemResource.
    279      */
    280     static FontMemResourceTypeface* Create(const LOGFONT& lf, HANDLE fontMemResource) {
    281         return new FontMemResourceTypeface(get_style(lf), lf, fontMemResource);
    282     }
    283 
    284 protected:
    285     void weak_dispose() const override {
    286         RemoveFontMemResourceEx(fFontMemResource);
    287         //SkTypefaceCache::Remove(this);
    288         INHERITED::weak_dispose();
    289     }
    290 
    291 private:
    292     /**
    293      *  Takes ownership of fontMemResource.
    294      */
    295     FontMemResourceTypeface(const SkFontStyle& style, const LOGFONT& lf, HANDLE fontMemResource)
    296         : LogFontTypeface(style, lf, true), fFontMemResource(fontMemResource)
    297     { }
    298 
    299     HANDLE fFontMemResource;
    300 
    301     typedef LogFontTypeface INHERITED;
    302 };
    303 
    304 static const LOGFONT& get_default_font() {
    305     static LOGFONT gDefaultFont;
    306     return gDefaultFont;
    307 }
    308 
    309 static bool FindByLogFont(SkTypeface* face, const SkFontStyle& requestedStyle, void* ctx) {
    310     LogFontTypeface* lface = static_cast<LogFontTypeface*>(face);
    311     const LOGFONT* lf = reinterpret_cast<const LOGFONT*>(ctx);
    312 
    313     return lface &&
    314            get_style(lface->fLogFont) == requestedStyle &&
    315            !memcmp(&lface->fLogFont, lf, sizeof(LOGFONT));
    316 }
    317 
    318 /**
    319  *  This guy is public. It first searches the cache, and if a match is not found,
    320  *  it creates a new face.
    321  */
    322 SkTypeface* SkCreateTypefaceFromLOGFONT(const LOGFONT& origLF) {
    323     LOGFONT lf = origLF;
    324     make_canonical(&lf);
    325     SkTypeface* face = SkTypefaceCache::FindByProcAndRef(FindByLogFont, &lf);
    326     if (nullptr == face) {
    327         face = LogFontTypeface::Create(lf);
    328         SkTypefaceCache::Add(face, get_style(lf));
    329     }
    330     return face;
    331 }
    332 
    333 /**
    334  *  The created SkTypeface takes ownership of fontMemResource.
    335  */
    336 SkTypeface* SkCreateFontMemResourceTypefaceFromLOGFONT(const LOGFONT& origLF, HANDLE fontMemResource) {
    337     LOGFONT lf = origLF;
    338     make_canonical(&lf);
    339     // We'll never get a cache hit, so no point in putting this in SkTypefaceCache.
    340     return FontMemResourceTypeface::Create(lf, fontMemResource);
    341 }
    342 
    343 /**
    344  *  This guy is public
    345  */
    346 void SkLOGFONTFromTypeface(const SkTypeface* face, LOGFONT* lf) {
    347     if (nullptr == face) {
    348         *lf = get_default_font();
    349     } else {
    350         *lf = static_cast<const LogFontTypeface*>(face)->fLogFont;
    351     }
    352 }
    353 
    354 // Construct Glyph to Unicode table.
    355 // Unicode code points that require conjugate pairs in utf16 are not
    356 // supported.
    357 // TODO(arthurhsu): Add support for conjugate pairs. It looks like that may
    358 // require parsing the TTF cmap table (platform 4, encoding 12) directly instead
    359 // of calling GetFontUnicodeRange().
    360 static void populate_glyph_to_unicode(HDC fontHdc, const unsigned glyphCount,
    361                                       SkTDArray<SkUnichar>* glyphToUnicode) {
    362     DWORD glyphSetBufferSize = GetFontUnicodeRanges(fontHdc, nullptr);
    363     if (!glyphSetBufferSize) {
    364         return;
    365     }
    366 
    367     SkAutoTDeleteArray<BYTE> glyphSetBuffer(new BYTE[glyphSetBufferSize]);
    368     GLYPHSET* glyphSet =
    369         reinterpret_cast<LPGLYPHSET>(glyphSetBuffer.get());
    370     if (GetFontUnicodeRanges(fontHdc, glyphSet) != glyphSetBufferSize) {
    371         return;
    372     }
    373 
    374     glyphToUnicode->setCount(glyphCount);
    375     memset(glyphToUnicode->begin(), 0, glyphCount * sizeof(SkUnichar));
    376     for (DWORD i = 0; i < glyphSet->cRanges; ++i) {
    377         // There is no guarantee that within a Unicode range, the corresponding
    378         // glyph id in a font file are continuous. So, even if we have ranges,
    379         // we can't just use the first and last entry of the range to compute
    380         // result. We need to enumerate them one by one.
    381         int count = glyphSet->ranges[i].cGlyphs;
    382         SkAutoTArray<WCHAR> chars(count + 1);
    383         chars[count] = 0;  // termintate string
    384         SkAutoTArray<WORD> glyph(count);
    385         for (USHORT j = 0; j < count; ++j) {
    386             chars[j] = glyphSet->ranges[i].wcLow + j;
    387         }
    388         GetGlyphIndicesW(fontHdc, chars.get(), count, glyph.get(),
    389                          GGI_MARK_NONEXISTING_GLYPHS);
    390         // If the glyph ID is valid, and the glyph is not mapped, then we will
    391         // fill in the char id into the vector. If the glyph is mapped already,
    392         // skip it.
    393         // TODO(arthurhsu): better improve this. e.g. Get all used char ids from
    394         // font cache, then generate this mapping table from there. It's
    395         // unlikely to have collisions since glyph reuse happens mostly for
    396         // different Unicode pages.
    397         for (USHORT j = 0; j < count; ++j) {
    398             if (glyph[j] != 0xffff && glyph[j] < glyphCount &&
    399                 (*glyphToUnicode)[glyph[j]] == 0) {
    400                 (*glyphToUnicode)[glyph[j]] = chars[j];
    401             }
    402         }
    403     }
    404 }
    405 
    406 //////////////////////////////////////////////////////////////////////////////////////
    407 
    408 static int alignTo32(int n) {
    409     return (n + 31) & ~31;
    410 }
    411 
    412 struct MyBitmapInfo : public BITMAPINFO {
    413     RGBQUAD fMoreSpaceForColors[1];
    414 };
    415 
    416 class HDCOffscreen {
    417 public:
    418     HDCOffscreen() {
    419         fFont = 0;
    420         fDC = 0;
    421         fBM = 0;
    422         fBits = nullptr;
    423         fWidth = fHeight = 0;
    424         fIsBW = false;
    425     }
    426 
    427     ~HDCOffscreen() {
    428         if (fDC) {
    429             DeleteDC(fDC);
    430         }
    431         if (fBM) {
    432             DeleteObject(fBM);
    433         }
    434     }
    435 
    436     void init(HFONT font, const XFORM& xform) {
    437         fFont = font;
    438         fXform = xform;
    439     }
    440 
    441     const void* draw(const SkGlyph&, bool isBW, size_t* srcRBPtr);
    442 
    443 private:
    444     HDC     fDC;
    445     HBITMAP fBM;
    446     HFONT   fFont;
    447     XFORM   fXform;
    448     void*   fBits;  // points into fBM
    449     int     fWidth;
    450     int     fHeight;
    451     bool    fIsBW;
    452 };
    453 
    454 const void* HDCOffscreen::draw(const SkGlyph& glyph, bool isBW,
    455                                size_t* srcRBPtr) {
    456     // Can we share the scalercontext's fDDC, so we don't need to create
    457     // a separate fDC here?
    458     if (0 == fDC) {
    459         fDC = CreateCompatibleDC(0);
    460         if (0 == fDC) {
    461             return nullptr;
    462         }
    463         SetGraphicsMode(fDC, GM_ADVANCED);
    464         SetBkMode(fDC, TRANSPARENT);
    465         SetTextAlign(fDC, TA_LEFT | TA_BASELINE);
    466         SelectObject(fDC, fFont);
    467 
    468         COLORREF color = 0x00FFFFFF;
    469         SkDEBUGCODE(COLORREF prev =) SetTextColor(fDC, color);
    470         SkASSERT(prev != CLR_INVALID);
    471     }
    472 
    473     if (fBM && (fIsBW != isBW || fWidth < glyph.fWidth || fHeight < glyph.fHeight)) {
    474         DeleteObject(fBM);
    475         fBM = 0;
    476     }
    477     fIsBW = isBW;
    478 
    479     fWidth = SkMax32(fWidth, glyph.fWidth);
    480     fHeight = SkMax32(fHeight, glyph.fHeight);
    481 
    482     int biWidth = isBW ? alignTo32(fWidth) : fWidth;
    483 
    484     if (0 == fBM) {
    485         MyBitmapInfo info;
    486         sk_bzero(&info, sizeof(info));
    487         if (isBW) {
    488             RGBQUAD blackQuad = { 0, 0, 0, 0 };
    489             RGBQUAD whiteQuad = { 0xFF, 0xFF, 0xFF, 0 };
    490             info.bmiColors[0] = blackQuad;
    491             info.bmiColors[1] = whiteQuad;
    492         }
    493         info.bmiHeader.biSize = sizeof(info.bmiHeader);
    494         info.bmiHeader.biWidth = biWidth;
    495         info.bmiHeader.biHeight = fHeight;
    496         info.bmiHeader.biPlanes = 1;
    497         info.bmiHeader.biBitCount = isBW ? 1 : 32;
    498         info.bmiHeader.biCompression = BI_RGB;
    499         if (isBW) {
    500             info.bmiHeader.biClrUsed = 2;
    501         }
    502         fBM = CreateDIBSection(fDC, &info, DIB_RGB_COLORS, &fBits, 0, 0);
    503         if (0 == fBM) {
    504             return nullptr;
    505         }
    506         SelectObject(fDC, fBM);
    507     }
    508 
    509     // erase
    510     size_t srcRB = isBW ? (biWidth >> 3) : (fWidth << 2);
    511     size_t size = fHeight * srcRB;
    512     memset(fBits, 0, size);
    513 
    514     XFORM xform = fXform;
    515     xform.eDx = (float)-glyph.fLeft;
    516     xform.eDy = (float)-glyph.fTop;
    517     SetWorldTransform(fDC, &xform);
    518 
    519     uint16_t glyphID = glyph.getGlyphID();
    520     BOOL ret = ExtTextOutW(fDC, 0, 0, ETO_GLYPH_INDEX, nullptr, reinterpret_cast<LPCWSTR>(&glyphID), 1, nullptr);
    521     GdiFlush();
    522     if (0 == ret) {
    523         return nullptr;
    524     }
    525     *srcRBPtr = srcRB;
    526     // offset to the start of the image
    527     return (const char*)fBits + (fHeight - glyph.fHeight) * srcRB;
    528 }
    529 
    530 //////////////////////////////////////////////////////////////////////////////
    531 #define BUFFERSIZE (1 << 13)
    532 
    533 class SkScalerContext_GDI : public SkScalerContext {
    534 public:
    535     SkScalerContext_GDI(SkTypeface*, const SkDescriptor* desc);
    536     virtual ~SkScalerContext_GDI();
    537 
    538     // Returns true if the constructor was able to complete all of its
    539     // initializations (which may include calling GDI).
    540     bool isValid() const;
    541 
    542 protected:
    543     unsigned generateGlyphCount() override;
    544     uint16_t generateCharToGlyph(SkUnichar uni) override;
    545     void generateAdvance(SkGlyph* glyph) override;
    546     void generateMetrics(SkGlyph* glyph) override;
    547     void generateImage(const SkGlyph& glyph) override;
    548     void generatePath(const SkGlyph& glyph, SkPath* path) override;
    549     void generateFontMetrics(SkPaint::FontMetrics*) override;
    550 
    551 private:
    552     DWORD getGDIGlyphPath(const SkGlyph& glyph, UINT flags,
    553                           SkAutoSTMalloc<BUFFERSIZE, uint8_t>* glyphbuf);
    554 
    555     HDCOffscreen fOffscreen;
    556     /** fGsA is the non-rotational part of total matrix without the text height scale.
    557      *  Used to find the magnitude of advances.
    558      */
    559     MAT2         fGsA;
    560     /** The total matrix without the textSize. */
    561     MAT2         fMat22;
    562     /** Scales font to EM size. */
    563     MAT2         fHighResMat22;
    564     HDC          fDDC;
    565     HFONT        fSavefont;
    566     HFONT        fFont;
    567     SCRIPT_CACHE fSC;
    568     int          fGlyphCount;
    569 
    570     /** The total matrix which also removes EM scale. */
    571     SkMatrix     fHiResMatrix;
    572     /** fG_inv is the inverse of the rotational part of the total matrix.
    573      *  Used to set the direction of advances.
    574      */
    575     SkMatrix     fG_inv;
    576     enum Type {
    577         kTrueType_Type, kBitmap_Type, kLine_Type
    578     } fType;
    579     TEXTMETRIC fTM;
    580 };
    581 
    582 static FIXED float2FIXED(float x) {
    583     return SkFixedToFIXED(SkFloatToFixed(x));
    584 }
    585 
    586 static BYTE compute_quality(const SkScalerContext::Rec& rec) {
    587     switch (rec.fMaskFormat) {
    588         case SkMask::kBW_Format:
    589             return NONANTIALIASED_QUALITY;
    590         case SkMask::kLCD16_Format:
    591             return CLEARTYPE_QUALITY;
    592         default:
    593             if (rec.fFlags & SkScalerContext::kGenA8FromLCD_Flag) {
    594                 return CLEARTYPE_QUALITY;
    595             } else {
    596                 return ANTIALIASED_QUALITY;
    597             }
    598     }
    599 }
    600 
    601 SkScalerContext_GDI::SkScalerContext_GDI(SkTypeface* rawTypeface,
    602                                                  const SkDescriptor* desc)
    603         : SkScalerContext(rawTypeface, desc)
    604         , fDDC(0)
    605         , fSavefont(0)
    606         , fFont(0)
    607         , fSC(0)
    608         , fGlyphCount(-1)
    609 {
    610     LogFontTypeface* typeface = reinterpret_cast<LogFontTypeface*>(rawTypeface);
    611 
    612     fDDC = ::CreateCompatibleDC(nullptr);
    613     if (!fDDC) {
    614         return;
    615     }
    616     SetGraphicsMode(fDDC, GM_ADVANCED);
    617     SetBkMode(fDDC, TRANSPARENT);
    618 
    619     // When GDI hinting, remove the entire Y scale from sA and GsA. (Prevents 'linear' metrics.)
    620     // When not hinting, remove only the integer Y scale from sA and GsA. (Applied by GDI.)
    621     SkScalerContextRec::PreMatrixScale scaleConstraints =
    622         (fRec.getHinting() == SkPaint::kNo_Hinting || fRec.getHinting() == SkPaint::kSlight_Hinting)
    623                    ? SkScalerContextRec::kVerticalInteger_PreMatrixScale
    624                    : SkScalerContextRec::kVertical_PreMatrixScale;
    625     SkVector scale;
    626     SkMatrix sA;
    627     SkMatrix GsA;
    628     SkMatrix A;
    629     fRec.computeMatrices(scaleConstraints, &scale, &sA, &GsA, &fG_inv, &A);
    630 
    631     fGsA.eM11 = SkScalarToFIXED(GsA.get(SkMatrix::kMScaleX));
    632     fGsA.eM12 = SkScalarToFIXED(-GsA.get(SkMatrix::kMSkewY)); // This should be ~0.
    633     fGsA.eM21 = SkScalarToFIXED(-GsA.get(SkMatrix::kMSkewX));
    634     fGsA.eM22 = SkScalarToFIXED(GsA.get(SkMatrix::kMScaleY));
    635 
    636     // When not hinting, scale was computed with kVerticalInteger, so is already an integer.
    637     // The sA and GsA transforms will be used to create 'linear' metrics.
    638 
    639     // When hinting, scale was computed with kVertical, stating that our port can handle
    640     // non-integer scales. This is done so that sA and GsA are computed without any 'residual'
    641     // scale in them, preventing 'linear' metrics. However, GDI cannot actually handle non-integer
    642     // scales so we need to round in this case. This is fine, since all of the scale has been
    643     // removed from sA and GsA, so GDI will be handling the scale completely.
    644     SkScalar gdiTextSize = SkScalarRoundToScalar(scale.fY);
    645 
    646     // GDI will not accept a size of zero, so round the range [0, 1] to 1.
    647     // If the size was non-zero, the scale factors will also be non-zero and 1px tall text is drawn.
    648     // If the size actually was zero, the scale factors will also be zero, so GDI will draw nothing.
    649     if (gdiTextSize == 0) {
    650         gdiTextSize = SK_Scalar1;
    651     }
    652 
    653     LOGFONT lf = typeface->fLogFont;
    654     lf.lfHeight = -SkScalarTruncToInt(gdiTextSize);
    655     lf.lfQuality = compute_quality(fRec);
    656     fFont = CreateFontIndirect(&lf);
    657     if (!fFont) {
    658         return;
    659     }
    660 
    661     fSavefont = (HFONT)SelectObject(fDDC, fFont);
    662 
    663     if (0 == GetTextMetrics(fDDC, &fTM)) {
    664         call_ensure_accessible(lf);
    665         if (0 == GetTextMetrics(fDDC, &fTM)) {
    666             fTM.tmPitchAndFamily = TMPF_TRUETYPE;
    667         }
    668     }
    669 
    670     XFORM xform;
    671     if (fTM.tmPitchAndFamily & TMPF_VECTOR) {
    672         // Used a logfont on a memory context, should never get a device font.
    673         // Therefore all TMPF_DEVICE will be PostScript fonts.
    674 
    675         // If TMPF_VECTOR is set, one of TMPF_TRUETYPE or TMPF_DEVICE means that
    676         // we have an outline font. Otherwise we have a vector FON, which is
    677         // scalable, but not an outline font.
    678         // This was determined by testing with Type1 PFM/PFB and
    679         // OpenTypeCFF OTF, as well as looking at Wine bugs and sources.
    680         if (fTM.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_DEVICE)) {
    681             // Truetype or PostScript.
    682             fType = SkScalerContext_GDI::kTrueType_Type;
    683         } else {
    684             // Stroked FON.
    685             fType = SkScalerContext_GDI::kLine_Type;
    686         }
    687 
    688         // fPost2x2 is column-major, left handed (y down).
    689         // XFORM 2x2 is row-major, left handed (y down).
    690         xform.eM11 = SkScalarToFloat(sA.get(SkMatrix::kMScaleX));
    691         xform.eM12 = SkScalarToFloat(sA.get(SkMatrix::kMSkewY));
    692         xform.eM21 = SkScalarToFloat(sA.get(SkMatrix::kMSkewX));
    693         xform.eM22 = SkScalarToFloat(sA.get(SkMatrix::kMScaleY));
    694         xform.eDx = 0;
    695         xform.eDy = 0;
    696 
    697         // MAT2 is row major, right handed (y up).
    698         fMat22.eM11 = float2FIXED(xform.eM11);
    699         fMat22.eM12 = float2FIXED(-xform.eM12);
    700         fMat22.eM21 = float2FIXED(-xform.eM21);
    701         fMat22.eM22 = float2FIXED(xform.eM22);
    702 
    703         if (needToRenderWithSkia(fRec)) {
    704             this->forceGenerateImageFromPath();
    705         }
    706 
    707         // Create a hires matrix if we need linear metrics.
    708         if (this->isSubpixel()) {
    709             OUTLINETEXTMETRIC otm;
    710             UINT success = GetOutlineTextMetrics(fDDC, sizeof(otm), &otm);
    711             if (0 == success) {
    712                 call_ensure_accessible(lf);
    713                 success = GetOutlineTextMetrics(fDDC, sizeof(otm), &otm);
    714             }
    715             if (0 != success) {
    716                 SkScalar upem = SkIntToScalar(otm.otmEMSquare);
    717 
    718                 SkScalar gdiTextSizeToEMScale = upem / gdiTextSize;
    719                 fHighResMat22.eM11 = float2FIXED(gdiTextSizeToEMScale);
    720                 fHighResMat22.eM12 = float2FIXED(0);
    721                 fHighResMat22.eM21 = float2FIXED(0);
    722                 fHighResMat22.eM22 = float2FIXED(gdiTextSizeToEMScale);
    723 
    724                 SkScalar removeEMScale = SkScalarInvert(upem);
    725                 fHiResMatrix = A;
    726                 fHiResMatrix.preScale(removeEMScale, removeEMScale);
    727             }
    728         }
    729 
    730     } else {
    731         // Assume bitmap
    732         fType = SkScalerContext_GDI::kBitmap_Type;
    733 
    734         xform.eM11 = 1.0f;
    735         xform.eM12 = 0.0f;
    736         xform.eM21 = 0.0f;
    737         xform.eM22 = 1.0f;
    738         xform.eDx = 0.0f;
    739         xform.eDy = 0.0f;
    740 
    741         // fPost2x2 is column-major, left handed (y down).
    742         // MAT2 is row major, right handed (y up).
    743         fMat22.eM11 = SkScalarToFIXED(fRec.fPost2x2[0][0]);
    744         fMat22.eM12 = SkScalarToFIXED(-fRec.fPost2x2[1][0]);
    745         fMat22.eM21 = SkScalarToFIXED(-fRec.fPost2x2[0][1]);
    746         fMat22.eM22 = SkScalarToFIXED(fRec.fPost2x2[1][1]);
    747     }
    748 
    749     fOffscreen.init(fFont, xform);
    750 }
    751 
    752 SkScalerContext_GDI::~SkScalerContext_GDI() {
    753     if (fDDC) {
    754         ::SelectObject(fDDC, fSavefont);
    755         ::DeleteDC(fDDC);
    756     }
    757     if (fFont) {
    758         ::DeleteObject(fFont);
    759     }
    760     if (fSC) {
    761         ::ScriptFreeCache(&fSC);
    762     }
    763 }
    764 
    765 bool SkScalerContext_GDI::isValid() const {
    766     return fDDC && fFont;
    767 }
    768 
    769 unsigned SkScalerContext_GDI::generateGlyphCount() {
    770     if (fGlyphCount < 0) {
    771         fGlyphCount = calculateGlyphCount(
    772                           fDDC, static_cast<const LogFontTypeface*>(this->getTypeface())->fLogFont);
    773     }
    774     return fGlyphCount;
    775 }
    776 
    777 uint16_t SkScalerContext_GDI::generateCharToGlyph(SkUnichar utf32) {
    778     uint16_t index = 0;
    779     WCHAR utf16[2];
    780     // TODO(ctguil): Support characters that generate more than one glyph.
    781     if (SkUTF16_FromUnichar(utf32, (uint16_t*)utf16) == 1) {
    782         // Type1 fonts fail with uniscribe API. Use GetGlyphIndices for plane 0.
    783 
    784         /** Real documentation for GetGlyphIndiciesW:
    785          *
    786          *  When GGI_MARK_NONEXISTING_GLYPHS is not specified and a character does not map to a
    787          *  glyph, then the 'default character's glyph is returned instead. The 'default character'
    788          *  is available in fTM.tmDefaultChar. FON fonts have a default character, and there exists
    789          *  a usDefaultChar in the 'OS/2' table, version 2 and later. If there is no
    790          *  'default character' specified by the font, then often the first character found is used.
    791          *
    792          *  When GGI_MARK_NONEXISTING_GLYPHS is specified and a character does not map to a glyph,
    793          *  then the glyph 0xFFFF is used. In Windows XP and earlier, Bitmap/Vector FON usually use
    794          *  glyph 0x1F instead ('Terminal' appears to be special, returning 0xFFFF).
    795          *  Type1 PFM/PFB, TT, OT TT, OT CFF all appear to use 0xFFFF, even on XP.
    796          */
    797         DWORD result = GetGlyphIndicesW(fDDC, utf16, 1, &index, GGI_MARK_NONEXISTING_GLYPHS);
    798         if (result == GDI_ERROR
    799             || 0xFFFF == index
    800             || (0x1F == index &&
    801                (fType == SkScalerContext_GDI::kBitmap_Type ||
    802                 fType == SkScalerContext_GDI::kLine_Type)
    803                /*&& winVer < Vista */)
    804            )
    805         {
    806             index = 0;
    807         }
    808     } else {
    809         // Use uniscribe to detemine glyph index for non-BMP characters.
    810         static const int numWCHAR = 2;
    811         static const int maxItems = 2;
    812         // MSDN states that this can be nullptr, but some things don't work then.
    813         SCRIPT_CONTROL sc = { 0 };
    814         // Add extra item to SCRIPT_ITEM to work around a bug (now documented).
    815         // https://bugzilla.mozilla.org/show_bug.cgi?id=366643
    816         SCRIPT_ITEM si[maxItems + 1];
    817         int numItems;
    818         HRZM(ScriptItemize(utf16, numWCHAR, maxItems, &sc, nullptr, si, &numItems),
    819              "Could not itemize character.");
    820 
    821         // Sometimes ScriptShape cannot find a glyph for a non-BMP and returns 2 space glyphs.
    822         static const int maxGlyphs = 2;
    823         SCRIPT_VISATTR vsa[maxGlyphs];
    824         WORD outGlyphs[maxGlyphs];
    825         WORD logClust[numWCHAR];
    826         int numGlyphs;
    827         HRZM(ScriptShape(fDDC, &fSC, utf16, numWCHAR, maxGlyphs, &si[0].a,
    828                          outGlyphs, logClust, vsa, &numGlyphs),
    829              "Could not shape character.");
    830         if (1 == numGlyphs) {
    831             index = outGlyphs[0];
    832         }
    833     }
    834     return index;
    835 }
    836 
    837 void SkScalerContext_GDI::generateAdvance(SkGlyph* glyph) {
    838     this->generateMetrics(glyph);
    839 }
    840 
    841 void SkScalerContext_GDI::generateMetrics(SkGlyph* glyph) {
    842     SkASSERT(fDDC);
    843 
    844     if (fType == SkScalerContext_GDI::kBitmap_Type || fType == SkScalerContext_GDI::kLine_Type) {
    845         SIZE size;
    846         WORD glyphs = glyph->getGlyphID();
    847         if (0 == GetTextExtentPointI(fDDC, &glyphs, 1, &size)) {
    848             glyph->fWidth = SkToS16(fTM.tmMaxCharWidth);
    849         } else {
    850             glyph->fWidth = SkToS16(size.cx);
    851         }
    852         glyph->fHeight = SkToS16(size.cy);
    853 
    854         glyph->fTop = SkToS16(-fTM.tmAscent);
    855         // Bitmap FON cannot underhang, but vector FON may.
    856         // There appears no means of determining underhang of vector FON.
    857         glyph->fLeft = SkToS16(0);
    858         glyph->fAdvanceX = SkIntToFixed(glyph->fWidth);
    859         glyph->fAdvanceY = 0;
    860 
    861         // Vector FON will transform nicely, but bitmap FON do not.
    862         if (fType == SkScalerContext_GDI::kLine_Type) {
    863             SkRect bounds = SkRect::MakeXYWH(glyph->fLeft, glyph->fTop,
    864                                              glyph->fWidth, glyph->fHeight);
    865             SkMatrix m;
    866             m.setAll(SkFIXEDToScalar(fMat22.eM11), -SkFIXEDToScalar(fMat22.eM21), 0,
    867                      -SkFIXEDToScalar(fMat22.eM12), SkFIXEDToScalar(fMat22.eM22), 0,
    868                      0,  0, 1);
    869             m.mapRect(&bounds);
    870             bounds.roundOut(&bounds);
    871             glyph->fLeft = SkScalarTruncToInt(bounds.fLeft);
    872             glyph->fTop = SkScalarTruncToInt(bounds.fTop);
    873             glyph->fWidth = SkScalarTruncToInt(bounds.width());
    874             glyph->fHeight = SkScalarTruncToInt(bounds.height());
    875         }
    876 
    877         // Apply matrix to advance.
    878         glyph->fAdvanceY = SkFixedMul(-SkFIXEDToFixed(fMat22.eM12), glyph->fAdvanceX);
    879         glyph->fAdvanceX = SkFixedMul(SkFIXEDToFixed(fMat22.eM11), glyph->fAdvanceX);
    880 
    881         return;
    882     }
    883 
    884     UINT glyphId = glyph->getGlyphID();
    885 
    886     GLYPHMETRICS gm;
    887     sk_bzero(&gm, sizeof(gm));
    888 
    889     DWORD status = GetGlyphOutlineW(fDDC, glyphId, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, nullptr, &fMat22);
    890     if (GDI_ERROR == status) {
    891         LogFontTypeface::EnsureAccessible(this->getTypeface());
    892         status = GetGlyphOutlineW(fDDC, glyphId, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, nullptr, &fMat22);
    893         if (GDI_ERROR == status) {
    894             glyph->zeroMetrics();
    895             return;
    896         }
    897     }
    898 
    899     bool empty = false;
    900     // The black box is either the embedded bitmap size or the outline extent.
    901     // It is 1x1 if nothing is to be drawn, but will also be 1x1 if something very small
    902     // is to be drawn, like a '.'. We need to outset '.' but do not wish to outset ' '.
    903     if (1 == gm.gmBlackBoxX && 1 == gm.gmBlackBoxY) {
    904         // If GetGlyphOutline with GGO_NATIVE returns 0, we know there was no outline.
    905         DWORD bufferSize = GetGlyphOutlineW(fDDC, glyphId, GGO_NATIVE | GGO_GLYPH_INDEX, &gm, 0, nullptr, &fMat22);
    906         empty = (0 == bufferSize);
    907     }
    908 
    909     glyph->fTop = SkToS16(-gm.gmptGlyphOrigin.y);
    910     glyph->fLeft = SkToS16(gm.gmptGlyphOrigin.x);
    911     if (empty) {
    912         glyph->fWidth = 0;
    913         glyph->fHeight = 0;
    914     } else {
    915         // Outset, since the image may bleed out of the black box.
    916         // For embedded bitmaps the black box should be exact.
    917         // For outlines we need to outset by 1 in all directions for bleed.
    918         // For ClearType we need to outset by 2 for bleed.
    919         glyph->fWidth = gm.gmBlackBoxX + 4;
    920         glyph->fHeight = gm.gmBlackBoxY + 4;
    921         glyph->fTop -= 2;
    922         glyph->fLeft -= 2;
    923     }
    924     glyph->fAdvanceX = SkIntToFixed(gm.gmCellIncX);
    925     glyph->fAdvanceY = SkIntToFixed(gm.gmCellIncY);
    926     glyph->fRsbDelta = 0;
    927     glyph->fLsbDelta = 0;
    928 
    929     if (this->isSubpixel()) {
    930         sk_bzero(&gm, sizeof(gm));
    931         status = GetGlyphOutlineW(fDDC, glyphId, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, nullptr, &fHighResMat22);
    932         if (GDI_ERROR != status) {
    933             SkPoint advance;
    934             fHiResMatrix.mapXY(SkIntToScalar(gm.gmCellIncX), SkIntToScalar(gm.gmCellIncY), &advance);
    935             glyph->fAdvanceX = SkScalarToFixed(advance.fX);
    936             glyph->fAdvanceY = SkScalarToFixed(advance.fY);
    937         }
    938     } else if (!isAxisAligned(this->fRec)) {
    939         status = GetGlyphOutlineW(fDDC, glyphId, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, nullptr, &fGsA);
    940         if (GDI_ERROR != status) {
    941             SkPoint advance;
    942             fG_inv.mapXY(SkIntToScalar(gm.gmCellIncX), SkIntToScalar(gm.gmCellIncY), &advance);
    943             glyph->fAdvanceX = SkScalarToFixed(advance.fX);
    944             glyph->fAdvanceY = SkScalarToFixed(advance.fY);
    945         }
    946     }
    947 }
    948 
    949 static const MAT2 gMat2Identity = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
    950 void SkScalerContext_GDI::generateFontMetrics(SkPaint::FontMetrics* metrics) {
    951     if (nullptr == metrics) {
    952         return;
    953     }
    954     sk_bzero(metrics, sizeof(*metrics));
    955 
    956     SkASSERT(fDDC);
    957 
    958 #ifndef SK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS
    959     if (fType == SkScalerContext_GDI::kBitmap_Type || fType == SkScalerContext_GDI::kLine_Type) {
    960 #endif
    961         metrics->fTop = SkIntToScalar(-fTM.tmAscent);
    962         metrics->fAscent = SkIntToScalar(-fTM.tmAscent);
    963         metrics->fDescent = SkIntToScalar(fTM.tmDescent);
    964         metrics->fBottom = SkIntToScalar(fTM.tmDescent);
    965         metrics->fLeading = SkIntToScalar(fTM.tmExternalLeading);
    966         metrics->fAvgCharWidth = SkIntToScalar(fTM.tmAveCharWidth);
    967         metrics->fMaxCharWidth = SkIntToScalar(fTM.tmMaxCharWidth);
    968         metrics->fXMin = 0;
    969         metrics->fXMax = metrics->fMaxCharWidth;
    970         //metrics->fXHeight = 0;
    971 #ifndef SK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS
    972         return;
    973     }
    974 #endif
    975 
    976     OUTLINETEXTMETRIC otm;
    977 
    978     uint32_t ret = GetOutlineTextMetrics(fDDC, sizeof(otm), &otm);
    979     if (0 == ret) {
    980         LogFontTypeface::EnsureAccessible(this->getTypeface());
    981         ret = GetOutlineTextMetrics(fDDC, sizeof(otm), &otm);
    982     }
    983     if (0 == ret) {
    984         return;
    985     }
    986 
    987 #ifndef SK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS
    988     metrics->fTop = SkIntToScalar(-otm.otmrcFontBox.top);
    989     metrics->fAscent = SkIntToScalar(-otm.otmAscent);
    990     metrics->fDescent = SkIntToScalar(-otm.otmDescent);
    991     metrics->fBottom = SkIntToScalar(-otm.otmrcFontBox.bottom);
    992     metrics->fLeading = SkIntToScalar(otm.otmLineGap);
    993     metrics->fAvgCharWidth = SkIntToScalar(otm.otmTextMetrics.tmAveCharWidth);
    994     metrics->fMaxCharWidth = SkIntToScalar(otm.otmTextMetrics.tmMaxCharWidth);
    995     metrics->fXMin = SkIntToScalar(otm.otmrcFontBox.left);
    996     metrics->fXMax = SkIntToScalar(otm.otmrcFontBox.right);
    997 #endif
    998     metrics->fUnderlineThickness = SkIntToScalar(otm.otmsUnderscoreSize);
    999     metrics->fUnderlinePosition = -SkIntToScalar(otm.otmsUnderscorePosition);
   1000 
   1001     metrics->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
   1002     metrics->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
   1003 
   1004     metrics->fXHeight = SkIntToScalar(otm.otmsXHeight);
   1005     GLYPHMETRICS gm;
   1006     sk_bzero(&gm, sizeof(gm));
   1007     DWORD len = GetGlyphOutlineW(fDDC, 'x', GGO_METRICS, &gm, 0, 0, &gMat2Identity);
   1008     if (len != GDI_ERROR && gm.gmBlackBoxY > 0) {
   1009         metrics->fXHeight = SkIntToScalar(gm.gmBlackBoxY);
   1010     }
   1011 }
   1012 
   1013 ////////////////////////////////////////////////////////////////////////////////////////
   1014 
   1015 #define SK_SHOW_TEXT_BLIT_COVERAGE 0
   1016 
   1017 static void build_power_table(uint8_t table[], float ee) {
   1018     for (int i = 0; i < 256; i++) {
   1019         float x = i / 255.f;
   1020         x = sk_float_pow(x, ee);
   1021         int xx = SkScalarRoundToInt(x * 255);
   1022         table[i] = SkToU8(xx);
   1023     }
   1024 }
   1025 
   1026 /**
   1027  *  This will invert the gamma applied by GDI (gray-scale antialiased), so we
   1028  *  can get linear values.
   1029  *
   1030  *  GDI grayscale appears to use a hard-coded gamma of 2.3.
   1031  *
   1032  *  GDI grayscale appears to draw using the black and white rasterizer at four
   1033  *  times the size and then downsamples to compute the coverage mask. As a
   1034  *  result there are only seventeen total grays. This lack of fidelity means
   1035  *  that shifting into other color spaces is imprecise.
   1036  */
   1037 static const uint8_t* getInverseGammaTableGDI() {
   1038     // Since build_power_table is idempotent, many threads can build gTableGdi
   1039     // simultaneously.
   1040 
   1041     // Microsoft Specific:
   1042     // Making gInited volatile provides read-aquire and write-release in vc++.
   1043     // In VS2012, see compiler option /volatile:(ms|iso).
   1044     // Replace with C++11 atomics when possible.
   1045     static volatile bool gInited;
   1046     static uint8_t gTableGdi[256];
   1047     if (gInited) {
   1048         // Need a L/L (read) barrier (full acquire not needed). If gInited is observed
   1049         // true then gTableGdi is observable, but it must be requested.
   1050     } else {
   1051         build_power_table(gTableGdi, 2.3f);
   1052         // Need a S/S (write) barrier (full release not needed) here so that this
   1053         // write to gInited becomes observable after gTableGdi.
   1054         gInited = true;
   1055     }
   1056     return gTableGdi;
   1057 }
   1058 
   1059 /**
   1060  *  This will invert the gamma applied by GDI ClearType, so we can get linear
   1061  *  values.
   1062  *
   1063  *  GDI ClearType uses SPI_GETFONTSMOOTHINGCONTRAST / 1000 as the gamma value.
   1064  *  If this value is not specified, the default is a gamma of 1.4.
   1065  */
   1066 static const uint8_t* getInverseGammaTableClearType() {
   1067     // We don't expect SPI_GETFONTSMOOTHINGCONTRAST to ever change, so building
   1068     // gTableClearType with build_power_table is effectively idempotent.
   1069 
   1070     // Microsoft Specific:
   1071     // Making gInited volatile provides read-aquire and write-release in vc++.
   1072     // In VS2012, see compiler option /volatile:(ms|iso).
   1073     // Replace with C++11 atomics when possible.
   1074     static volatile bool gInited;
   1075     static uint8_t gTableClearType[256];
   1076     if (gInited) {
   1077         // Need a L/L (read) barrier (acquire not needed). If gInited is observed
   1078         // true then gTableClearType is observable, but it must be requested.
   1079     } else {
   1080         UINT level = 0;
   1081         if (!SystemParametersInfo(SPI_GETFONTSMOOTHINGCONTRAST, 0, &level, 0) || !level) {
   1082             // can't get the data, so use a default
   1083             level = 1400;
   1084         }
   1085         build_power_table(gTableClearType, level / 1000.0f);
   1086         // Need a S/S (write) barrier (release not needed) here so that this
   1087         // write to gInited becomes observable after gTableClearType.
   1088         gInited = true;
   1089     }
   1090     return gTableClearType;
   1091 }
   1092 
   1093 #include "SkColorPriv.h"
   1094 
   1095 //Cannot assume that the input rgb is gray due to possible setting of kGenA8FromLCD_Flag.
   1096 template<bool APPLY_PREBLEND>
   1097 static inline uint8_t rgb_to_a8(SkGdiRGB rgb, const uint8_t* table8) {
   1098     U8CPU r = (rgb >> 16) & 0xFF;
   1099     U8CPU g = (rgb >>  8) & 0xFF;
   1100     U8CPU b = (rgb >>  0) & 0xFF;
   1101     return sk_apply_lut_if<APPLY_PREBLEND>(SkComputeLuminance(r, g, b), table8);
   1102 }
   1103 
   1104 template<bool APPLY_PREBLEND>
   1105 static inline uint16_t rgb_to_lcd16(SkGdiRGB rgb, const uint8_t* tableR,
   1106                                                   const uint8_t* tableG,
   1107                                                   const uint8_t* tableB) {
   1108     U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 16) & 0xFF, tableR);
   1109     U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>((rgb >>  8) & 0xFF, tableG);
   1110     U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>((rgb >>  0) & 0xFF, tableB);
   1111 #if SK_SHOW_TEXT_BLIT_COVERAGE
   1112     r = SkMax32(r, 10); g = SkMax32(g, 10); b = SkMax32(b, 10);
   1113 #endif
   1114     return SkPack888ToRGB16(r, g, b);
   1115 }
   1116 
   1117 // Is this GDI color neither black nor white? If so, we have to keep this
   1118 // image as is, rather than smashing it down to a BW mask.
   1119 //
   1120 // returns int instead of bool, since we don't want/have to pay to convert
   1121 // the zero/non-zero value into a bool
   1122 static int is_not_black_or_white(SkGdiRGB c) {
   1123     // same as (but faster than)
   1124     //      c &= 0x00FFFFFF;
   1125     //      return 0 == c || 0x00FFFFFF == c;
   1126     return (c + (c & 1)) & 0x00FFFFFF;
   1127 }
   1128 
   1129 static bool is_rgb_really_bw(const SkGdiRGB* src, int width, int height, size_t srcRB) {
   1130     for (int y = 0; y < height; ++y) {
   1131         for (int x = 0; x < width; ++x) {
   1132             if (is_not_black_or_white(src[x])) {
   1133                 return false;
   1134             }
   1135         }
   1136         src = SkTAddOffset<const SkGdiRGB>(src, srcRB);
   1137     }
   1138     return true;
   1139 }
   1140 
   1141 // gdi's bitmap is upside-down, so we reverse dst walking in Y
   1142 // whenever we copy it into skia's buffer
   1143 static void rgb_to_bw(const SkGdiRGB* SK_RESTRICT src, size_t srcRB,
   1144                       const SkGlyph& glyph) {
   1145     const int width = glyph.fWidth;
   1146     const size_t dstRB = (width + 7) >> 3;
   1147     uint8_t* SK_RESTRICT dst = (uint8_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB);
   1148 
   1149     int byteCount = width >> 3;
   1150     int bitCount = width & 7;
   1151 
   1152     // adjust srcRB to skip the values in our byteCount loop,
   1153     // since we increment src locally there
   1154     srcRB -= byteCount * 8 * sizeof(SkGdiRGB);
   1155 
   1156     for (int y = 0; y < glyph.fHeight; ++y) {
   1157         if (byteCount > 0) {
   1158             for (int i = 0; i < byteCount; ++i) {
   1159                 unsigned byte = 0;
   1160                 byte |= src[0] & (1 << 7);
   1161                 byte |= src[1] & (1 << 6);
   1162                 byte |= src[2] & (1 << 5);
   1163                 byte |= src[3] & (1 << 4);
   1164                 byte |= src[4] & (1 << 3);
   1165                 byte |= src[5] & (1 << 2);
   1166                 byte |= src[6] & (1 << 1);
   1167                 byte |= src[7] & (1 << 0);
   1168                 dst[i] = byte;
   1169                 src += 8;
   1170             }
   1171         }
   1172         if (bitCount > 0) {
   1173             unsigned byte = 0;
   1174             unsigned mask = 0x80;
   1175             for (int i = 0; i < bitCount; i++) {
   1176                 byte |= src[i] & mask;
   1177                 mask >>= 1;
   1178             }
   1179             dst[byteCount] = byte;
   1180         }
   1181         src = SkTAddOffset<const SkGdiRGB>(src, srcRB);
   1182         dst -= dstRB;
   1183     }
   1184 #if SK_SHOW_TEXT_BLIT_COVERAGE
   1185     if (glyph.fWidth > 0 && glyph.fHeight > 0) {
   1186         uint8_t* first = (uint8_t*)glyph.fImage;
   1187         uint8_t* last = (uint8_t*)((char*)glyph.fImage + glyph.fHeight * dstRB - 1);
   1188         *first |= 1 << 7;
   1189         *last |= bitCount == 0 ? 1 : 1 << (8 - bitCount);
   1190     }
   1191 #endif
   1192 }
   1193 
   1194 template<bool APPLY_PREBLEND>
   1195 static void rgb_to_a8(const SkGdiRGB* SK_RESTRICT src, size_t srcRB,
   1196                       const SkGlyph& glyph, const uint8_t* table8) {
   1197     const size_t dstRB = glyph.rowBytes();
   1198     const int width = glyph.fWidth;
   1199     uint8_t* SK_RESTRICT dst = (uint8_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB);
   1200 
   1201     for (int y = 0; y < glyph.fHeight; y++) {
   1202         for (int i = 0; i < width; i++) {
   1203             dst[i] = rgb_to_a8<APPLY_PREBLEND>(src[i], table8);
   1204 #if SK_SHOW_TEXT_BLIT_COVERAGE
   1205             dst[i] = SkMax32(dst[i], 10);
   1206 #endif
   1207         }
   1208         src = SkTAddOffset<const SkGdiRGB>(src, srcRB);
   1209         dst -= dstRB;
   1210     }
   1211 }
   1212 
   1213 template<bool APPLY_PREBLEND>
   1214 static void rgb_to_lcd16(const SkGdiRGB* SK_RESTRICT src, size_t srcRB, const SkGlyph& glyph,
   1215                          const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
   1216     const size_t dstRB = glyph.rowBytes();
   1217     const int width = glyph.fWidth;
   1218     uint16_t* SK_RESTRICT dst = (uint16_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB);
   1219 
   1220     for (int y = 0; y < glyph.fHeight; y++) {
   1221         for (int i = 0; i < width; i++) {
   1222             dst[i] = rgb_to_lcd16<APPLY_PREBLEND>(src[i], tableR, tableG, tableB);
   1223         }
   1224         src = SkTAddOffset<const SkGdiRGB>(src, srcRB);
   1225         dst = (uint16_t*)((char*)dst - dstRB);
   1226     }
   1227 }
   1228 
   1229 void SkScalerContext_GDI::generateImage(const SkGlyph& glyph) {
   1230     SkASSERT(fDDC);
   1231 
   1232     const bool isBW = SkMask::kBW_Format == fRec.fMaskFormat;
   1233     const bool isAA = !isLCD(fRec);
   1234 
   1235     size_t srcRB;
   1236     const void* bits = fOffscreen.draw(glyph, isBW, &srcRB);
   1237     if (nullptr == bits) {
   1238         LogFontTypeface::EnsureAccessible(this->getTypeface());
   1239         bits = fOffscreen.draw(glyph, isBW, &srcRB);
   1240         if (nullptr == bits) {
   1241             sk_bzero(glyph.fImage, glyph.computeImageSize());
   1242             return;
   1243         }
   1244     }
   1245 
   1246     if (!isBW) {
   1247         const uint8_t* table;
   1248         //The offscreen contains a GDI blit if isAA and kGenA8FromLCD_Flag is not set.
   1249         //Otherwise the offscreen contains a ClearType blit.
   1250         if (isAA && !(fRec.fFlags & SkScalerContext::kGenA8FromLCD_Flag)) {
   1251             table = getInverseGammaTableGDI();
   1252         } else {
   1253             table = getInverseGammaTableClearType();
   1254         }
   1255         //Note that the following cannot really be integrated into the
   1256         //pre-blend, since we may not be applying the pre-blend; when we aren't
   1257         //applying the pre-blend it means that a filter wants linear anyway.
   1258         //Other code may also be applying the pre-blend, so we'd need another
   1259         //one with this and one without.
   1260         SkGdiRGB* addr = (SkGdiRGB*)bits;
   1261         for (int y = 0; y < glyph.fHeight; ++y) {
   1262             for (int x = 0; x < glyph.fWidth; ++x) {
   1263                 int r = (addr[x] >> 16) & 0xFF;
   1264                 int g = (addr[x] >>  8) & 0xFF;
   1265                 int b = (addr[x] >>  0) & 0xFF;
   1266                 addr[x] = (table[r] << 16) | (table[g] << 8) | table[b];
   1267             }
   1268             addr = SkTAddOffset<SkGdiRGB>(addr, srcRB);
   1269         }
   1270     }
   1271 
   1272     int width = glyph.fWidth;
   1273     size_t dstRB = glyph.rowBytes();
   1274     if (isBW) {
   1275         const uint8_t* src = (const uint8_t*)bits;
   1276         uint8_t* dst = (uint8_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB);
   1277         for (int y = 0; y < glyph.fHeight; y++) {
   1278             memcpy(dst, src, dstRB);
   1279             src += srcRB;
   1280             dst -= dstRB;
   1281         }
   1282 #if SK_SHOW_TEXT_BLIT_COVERAGE
   1283             if (glyph.fWidth > 0 && glyph.fHeight > 0) {
   1284                 int bitCount = width & 7;
   1285                 uint8_t* first = (uint8_t*)glyph.fImage;
   1286                 uint8_t* last = (uint8_t*)((char*)glyph.fImage + glyph.fHeight * dstRB - 1);
   1287                 *first |= 1 << 7;
   1288                 *last |= bitCount == 0 ? 1 : 1 << (8 - bitCount);
   1289             }
   1290 #endif
   1291     } else if (isAA) {
   1292         // since the caller may require A8 for maskfilters, we can't check for BW
   1293         // ... until we have the caller tell us that explicitly
   1294         const SkGdiRGB* src = (const SkGdiRGB*)bits;
   1295         if (fPreBlend.isApplicable()) {
   1296             rgb_to_a8<true>(src, srcRB, glyph, fPreBlend.fG);
   1297         } else {
   1298             rgb_to_a8<false>(src, srcRB, glyph, fPreBlend.fG);
   1299         }
   1300     } else {    // LCD16
   1301         const SkGdiRGB* src = (const SkGdiRGB*)bits;
   1302         if (is_rgb_really_bw(src, width, glyph.fHeight, srcRB)) {
   1303             rgb_to_bw(src, srcRB, glyph);
   1304             ((SkGlyph*)&glyph)->fMaskFormat = SkMask::kBW_Format;
   1305         } else {
   1306             SkASSERT(SkMask::kLCD16_Format == glyph.fMaskFormat);
   1307             if (fPreBlend.isApplicable()) {
   1308                 rgb_to_lcd16<true>(src, srcRB, glyph,
   1309                                    fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
   1310             } else {
   1311                 rgb_to_lcd16<false>(src, srcRB, glyph,
   1312                                     fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
   1313             }
   1314         }
   1315     }
   1316 }
   1317 
   1318 class GDIGlyphbufferPointIter {
   1319 public:
   1320     GDIGlyphbufferPointIter(const uint8_t* glyphbuf, DWORD total_size)
   1321         : fHeaderIter(glyphbuf, total_size), fCurveIter(), fPointIter()
   1322     { }
   1323 
   1324     POINTFX const * next() {
   1325 nextHeader:
   1326         if (!fCurveIter.isSet()) {
   1327             const TTPOLYGONHEADER* header = fHeaderIter.next();
   1328             if (nullptr == header) {
   1329                 return nullptr;
   1330             }
   1331             fCurveIter.set(header);
   1332             const TTPOLYCURVE* curve = fCurveIter.next();
   1333             if (nullptr == curve) {
   1334                 return nullptr;
   1335             }
   1336             fPointIter.set(curve);
   1337             return &header->pfxStart;
   1338         }
   1339 
   1340         const POINTFX* nextPoint = fPointIter.next();
   1341         if (nullptr == nextPoint) {
   1342             const TTPOLYCURVE* curve = fCurveIter.next();
   1343             if (nullptr == curve) {
   1344                 fCurveIter.set();
   1345                 goto nextHeader;
   1346             } else {
   1347                 fPointIter.set(curve);
   1348             }
   1349             nextPoint = fPointIter.next();
   1350         }
   1351         return nextPoint;
   1352     }
   1353 
   1354     WORD currentCurveType() {
   1355         return fPointIter.fCurveType;
   1356     }
   1357 
   1358 private:
   1359     /** Iterates over all of the polygon headers in a glyphbuf. */
   1360     class GDIPolygonHeaderIter {
   1361     public:
   1362         GDIPolygonHeaderIter(const uint8_t* glyphbuf, DWORD total_size)
   1363             : fCurPolygon(reinterpret_cast<const TTPOLYGONHEADER*>(glyphbuf))
   1364             , fEndPolygon(SkTAddOffset<const TTPOLYGONHEADER>(glyphbuf, total_size))
   1365         { }
   1366 
   1367         const TTPOLYGONHEADER* next() {
   1368             if (fCurPolygon >= fEndPolygon) {
   1369                 return nullptr;
   1370             }
   1371             const TTPOLYGONHEADER* thisPolygon = fCurPolygon;
   1372             fCurPolygon = SkTAddOffset<const TTPOLYGONHEADER>(fCurPolygon, fCurPolygon->cb);
   1373             return thisPolygon;
   1374         }
   1375     private:
   1376         const TTPOLYGONHEADER* fCurPolygon;
   1377         const TTPOLYGONHEADER* fEndPolygon;
   1378     };
   1379 
   1380     /** Iterates over all of the polygon curves in a polygon header. */
   1381     class GDIPolygonCurveIter {
   1382     public:
   1383         GDIPolygonCurveIter() : fCurCurve(nullptr), fEndCurve(nullptr) { }
   1384 
   1385         GDIPolygonCurveIter(const TTPOLYGONHEADER* curPolygon)
   1386             : fCurCurve(SkTAddOffset<const TTPOLYCURVE>(curPolygon, sizeof(TTPOLYGONHEADER)))
   1387             , fEndCurve(SkTAddOffset<const TTPOLYCURVE>(curPolygon, curPolygon->cb))
   1388         { }
   1389 
   1390         bool isSet() { return fCurCurve != nullptr; }
   1391 
   1392         void set(const TTPOLYGONHEADER* curPolygon) {
   1393             fCurCurve = SkTAddOffset<const TTPOLYCURVE>(curPolygon, sizeof(TTPOLYGONHEADER));
   1394             fEndCurve = SkTAddOffset<const TTPOLYCURVE>(curPolygon, curPolygon->cb);
   1395         }
   1396         void set() {
   1397             fCurCurve = nullptr;
   1398             fEndCurve = nullptr;
   1399         }
   1400 
   1401         const TTPOLYCURVE* next() {
   1402             if (fCurCurve >= fEndCurve) {
   1403                 return nullptr;
   1404             }
   1405             const TTPOLYCURVE* thisCurve = fCurCurve;
   1406             fCurCurve = SkTAddOffset<const TTPOLYCURVE>(fCurCurve, size_of_TTPOLYCURVE(*fCurCurve));
   1407             return thisCurve;
   1408         }
   1409     private:
   1410         size_t size_of_TTPOLYCURVE(const TTPOLYCURVE& curve) {
   1411             return 2*sizeof(WORD) + curve.cpfx*sizeof(POINTFX);
   1412         }
   1413         const TTPOLYCURVE* fCurCurve;
   1414         const TTPOLYCURVE* fEndCurve;
   1415     };
   1416 
   1417     /** Iterates over all of the polygon points in a polygon curve. */
   1418     class GDIPolygonCurvePointIter {
   1419     public:
   1420         GDIPolygonCurvePointIter() : fCurveType(0), fCurPoint(nullptr), fEndPoint(nullptr) { }
   1421 
   1422         GDIPolygonCurvePointIter(const TTPOLYCURVE* curPolygon)
   1423             : fCurveType(curPolygon->wType)
   1424             , fCurPoint(&curPolygon->apfx[0])
   1425             , fEndPoint(&curPolygon->apfx[curPolygon->cpfx])
   1426         { }
   1427 
   1428         bool isSet() { return fCurPoint != nullptr; }
   1429 
   1430         void set(const TTPOLYCURVE* curPolygon) {
   1431             fCurveType = curPolygon->wType;
   1432             fCurPoint = &curPolygon->apfx[0];
   1433             fEndPoint = &curPolygon->apfx[curPolygon->cpfx];
   1434         }
   1435         void set() {
   1436             fCurPoint = nullptr;
   1437             fEndPoint = nullptr;
   1438         }
   1439 
   1440         const POINTFX* next() {
   1441             if (fCurPoint >= fEndPoint) {
   1442                 return nullptr;
   1443             }
   1444             const POINTFX* thisPoint = fCurPoint;
   1445             ++fCurPoint;
   1446             return thisPoint;
   1447         }
   1448 
   1449         WORD fCurveType;
   1450     private:
   1451         const POINTFX* fCurPoint;
   1452         const POINTFX* fEndPoint;
   1453     };
   1454 
   1455     GDIPolygonHeaderIter fHeaderIter;
   1456     GDIPolygonCurveIter fCurveIter;
   1457     GDIPolygonCurvePointIter fPointIter;
   1458 };
   1459 
   1460 static void sk_path_from_gdi_path(SkPath* path, const uint8_t* glyphbuf, DWORD total_size) {
   1461     const uint8_t* cur_glyph = glyphbuf;
   1462     const uint8_t* end_glyph = glyphbuf + total_size;
   1463 
   1464     while (cur_glyph < end_glyph) {
   1465         const TTPOLYGONHEADER* th = (TTPOLYGONHEADER*)cur_glyph;
   1466 
   1467         const uint8_t* end_poly = cur_glyph + th->cb;
   1468         const uint8_t* cur_poly = cur_glyph + sizeof(TTPOLYGONHEADER);
   1469 
   1470         path->moveTo(SkFixedToScalar( SkFIXEDToFixed(th->pfxStart.x)),
   1471                      SkFixedToScalar(-SkFIXEDToFixed(th->pfxStart.y)));
   1472 
   1473         while (cur_poly < end_poly) {
   1474             const TTPOLYCURVE* pc = (const TTPOLYCURVE*)cur_poly;
   1475 
   1476             if (pc->wType == TT_PRIM_LINE) {
   1477                 for (uint16_t i = 0; i < pc->cpfx; i++) {
   1478                     path->lineTo(SkFixedToScalar( SkFIXEDToFixed(pc->apfx[i].x)),
   1479                                  SkFixedToScalar(-SkFIXEDToFixed(pc->apfx[i].y)));
   1480                 }
   1481             }
   1482 
   1483             if (pc->wType == TT_PRIM_QSPLINE) {
   1484                 for (uint16_t u = 0; u < pc->cpfx - 1; u++) { // Walk through points in spline
   1485                     POINTFX pnt_b = pc->apfx[u];    // B is always the current point
   1486                     POINTFX pnt_c = pc->apfx[u+1];
   1487 
   1488                     if (u < pc->cpfx - 2) {          // If not on last spline, compute C
   1489                         pnt_c.x = SkFixedToFIXED(SkFixedAve(SkFIXEDToFixed(pnt_b.x),
   1490                                                             SkFIXEDToFixed(pnt_c.x)));
   1491                         pnt_c.y = SkFixedToFIXED(SkFixedAve(SkFIXEDToFixed(pnt_b.y),
   1492                                                             SkFIXEDToFixed(pnt_c.y)));
   1493                     }
   1494 
   1495                     path->quadTo(SkFixedToScalar( SkFIXEDToFixed(pnt_b.x)),
   1496                                  SkFixedToScalar(-SkFIXEDToFixed(pnt_b.y)),
   1497                                  SkFixedToScalar( SkFIXEDToFixed(pnt_c.x)),
   1498                                  SkFixedToScalar(-SkFIXEDToFixed(pnt_c.y)));
   1499                 }
   1500             }
   1501             // Advance past this TTPOLYCURVE.
   1502             cur_poly += sizeof(WORD) * 2 + sizeof(POINTFX) * pc->cpfx;
   1503         }
   1504         cur_glyph += th->cb;
   1505         path->close();
   1506     }
   1507 }
   1508 
   1509 #define move_next_expected_hinted_point(iter, pElem) do {\
   1510     pElem = iter.next(); \
   1511     if (nullptr == pElem) return false; \
   1512 } while(0)
   1513 
   1514 // It is possible for the hinted and unhinted versions of the same path to have
   1515 // a different number of points due to GDI's handling of flipped points.
   1516 // If this is detected, this will return false.
   1517 static bool sk_path_from_gdi_paths(SkPath* path, const uint8_t* glyphbuf, DWORD total_size,
   1518                                    GDIGlyphbufferPointIter hintedYs) {
   1519     const uint8_t* cur_glyph = glyphbuf;
   1520     const uint8_t* end_glyph = glyphbuf + total_size;
   1521 
   1522     POINTFX const * hintedPoint;
   1523 
   1524     while (cur_glyph < end_glyph) {
   1525         const TTPOLYGONHEADER* th = (TTPOLYGONHEADER*)cur_glyph;
   1526 
   1527         const uint8_t* end_poly = cur_glyph + th->cb;
   1528         const uint8_t* cur_poly = cur_glyph + sizeof(TTPOLYGONHEADER);
   1529 
   1530         move_next_expected_hinted_point(hintedYs, hintedPoint);
   1531         path->moveTo(SkFixedToScalar( SkFIXEDToFixed(th->pfxStart.x)),
   1532                      SkFixedToScalar(-SkFIXEDToFixed(hintedPoint->y)));
   1533 
   1534         while (cur_poly < end_poly) {
   1535             const TTPOLYCURVE* pc = (const TTPOLYCURVE*)cur_poly;
   1536 
   1537             if (pc->wType == TT_PRIM_LINE) {
   1538                 for (uint16_t i = 0; i < pc->cpfx; i++) {
   1539                     move_next_expected_hinted_point(hintedYs, hintedPoint);
   1540                     path->lineTo(SkFixedToScalar( SkFIXEDToFixed(pc->apfx[i].x)),
   1541                                  SkFixedToScalar(-SkFIXEDToFixed(hintedPoint->y)));
   1542                 }
   1543             }
   1544 
   1545             if (pc->wType == TT_PRIM_QSPLINE) {
   1546                 POINTFX currentPoint = pc->apfx[0];
   1547                 move_next_expected_hinted_point(hintedYs, hintedPoint);
   1548                 // only take the hinted y if it wasn't flipped
   1549                 if (hintedYs.currentCurveType() == TT_PRIM_QSPLINE) {
   1550                     currentPoint.y = hintedPoint->y;
   1551                 }
   1552                 for (uint16_t u = 0; u < pc->cpfx - 1; u++) { // Walk through points in spline
   1553                     POINTFX pnt_b = currentPoint;//pc->apfx[u]; // B is always the current point
   1554                     POINTFX pnt_c = pc->apfx[u+1];
   1555                     move_next_expected_hinted_point(hintedYs, hintedPoint);
   1556                     // only take the hinted y if it wasn't flipped
   1557                     if (hintedYs.currentCurveType() == TT_PRIM_QSPLINE) {
   1558                         pnt_c.y = hintedPoint->y;
   1559                     }
   1560                     currentPoint.x = pnt_c.x;
   1561                     currentPoint.y = pnt_c.y;
   1562 
   1563                     if (u < pc->cpfx - 2) {          // If not on last spline, compute C
   1564                         pnt_c.x = SkFixedToFIXED(SkFixedAve(SkFIXEDToFixed(pnt_b.x),
   1565                                                             SkFIXEDToFixed(pnt_c.x)));
   1566                         pnt_c.y = SkFixedToFIXED(SkFixedAve(SkFIXEDToFixed(pnt_b.y),
   1567                                                             SkFIXEDToFixed(pnt_c.y)));
   1568                     }
   1569 
   1570                     path->quadTo(SkFixedToScalar( SkFIXEDToFixed(pnt_b.x)),
   1571                                  SkFixedToScalar(-SkFIXEDToFixed(pnt_b.y)),
   1572                                  SkFixedToScalar( SkFIXEDToFixed(pnt_c.x)),
   1573                                  SkFixedToScalar(-SkFIXEDToFixed(pnt_c.y)));
   1574                 }
   1575             }
   1576             // Advance past this TTPOLYCURVE.
   1577             cur_poly += sizeof(WORD) * 2 + sizeof(POINTFX) * pc->cpfx;
   1578         }
   1579         cur_glyph += th->cb;
   1580         path->close();
   1581     }
   1582     return true;
   1583 }
   1584 
   1585 DWORD SkScalerContext_GDI::getGDIGlyphPath(const SkGlyph& glyph, UINT flags,
   1586                                                SkAutoSTMalloc<BUFFERSIZE, uint8_t>* glyphbuf)
   1587 {
   1588     GLYPHMETRICS gm;
   1589 
   1590     DWORD total_size = GetGlyphOutlineW(fDDC, glyph.getGlyphID(), flags, &gm, BUFFERSIZE, glyphbuf->get(), &fMat22);
   1591     // Sometimes GetGlyphOutlineW returns a number larger than BUFFERSIZE even if BUFFERSIZE > 0.
   1592     // It has been verified that this does not involve a buffer overrun.
   1593     if (GDI_ERROR == total_size || total_size > BUFFERSIZE) {
   1594         // GDI_ERROR because the BUFFERSIZE was too small, or because the data was not accessible.
   1595         // When the data is not accessable GetGlyphOutlineW fails rather quickly,
   1596         // so just try to get the size. If that fails then ensure the data is accessible.
   1597         total_size = GetGlyphOutlineW(fDDC, glyph.getGlyphID(), flags, &gm, 0, nullptr, &fMat22);
   1598         if (GDI_ERROR == total_size) {
   1599             LogFontTypeface::EnsureAccessible(this->getTypeface());
   1600             total_size = GetGlyphOutlineW(fDDC, glyph.getGlyphID(), flags, &gm, 0, nullptr, &fMat22);
   1601             if (GDI_ERROR == total_size) {
   1602                 // GetGlyphOutlineW is known to fail for some characters, such as spaces.
   1603                 // In these cases, just return that the glyph does not have a shape.
   1604                 return 0;
   1605             }
   1606         }
   1607 
   1608         glyphbuf->reset(total_size);
   1609 
   1610         DWORD ret = GetGlyphOutlineW(fDDC, glyph.getGlyphID(), flags, &gm, total_size, glyphbuf->get(), &fMat22);
   1611         if (GDI_ERROR == ret) {
   1612             LogFontTypeface::EnsureAccessible(this->getTypeface());
   1613             ret = GetGlyphOutlineW(fDDC, glyph.getGlyphID(), flags, &gm, total_size, glyphbuf->get(), &fMat22);
   1614             if (GDI_ERROR == ret) {
   1615                 SkASSERT(false);
   1616                 return 0;
   1617             }
   1618         }
   1619     }
   1620     return total_size;
   1621 }
   1622 
   1623 void SkScalerContext_GDI::generatePath(const SkGlyph& glyph, SkPath* path) {
   1624     SkASSERT(path);
   1625     SkASSERT(fDDC);
   1626 
   1627     path->reset();
   1628 
   1629     // Out of all the fonts on a typical Windows box,
   1630     // 25% of glyphs require more than 2KB.
   1631     // 1% of glyphs require more than 4KB.
   1632     // 0.01% of glyphs require more than 8KB.
   1633     // 8KB is less than 1% of the normal 1MB stack on Windows.
   1634     // Note that some web fonts glyphs require more than 20KB.
   1635     //static const DWORD BUFFERSIZE = (1 << 13);
   1636 
   1637     //GDI only uses hinted outlines when axis aligned.
   1638     UINT format = GGO_NATIVE | GGO_GLYPH_INDEX;
   1639     if (fRec.getHinting() == SkPaint::kNo_Hinting || fRec.getHinting() == SkPaint::kSlight_Hinting){
   1640         format |= GGO_UNHINTED;
   1641     }
   1642     SkAutoSTMalloc<BUFFERSIZE, uint8_t> glyphbuf(BUFFERSIZE);
   1643     DWORD total_size = getGDIGlyphPath(glyph, format, &glyphbuf);
   1644     if (0 == total_size) {
   1645         return;
   1646     }
   1647 
   1648     if (fRec.getHinting() != SkPaint::kSlight_Hinting) {
   1649         sk_path_from_gdi_path(path, glyphbuf, total_size);
   1650     } else {
   1651         //GDI only uses hinted outlines when axis aligned.
   1652         UINT format = GGO_NATIVE | GGO_GLYPH_INDEX;
   1653 
   1654         SkAutoSTMalloc<BUFFERSIZE, uint8_t> hintedGlyphbuf(BUFFERSIZE);
   1655         DWORD hinted_total_size = getGDIGlyphPath(glyph, format, &hintedGlyphbuf);
   1656         if (0 == hinted_total_size) {
   1657             return;
   1658         }
   1659 
   1660         if (!sk_path_from_gdi_paths(path, glyphbuf, total_size,
   1661                                     GDIGlyphbufferPointIter(hintedGlyphbuf, hinted_total_size)))
   1662         {
   1663             path->reset();
   1664             sk_path_from_gdi_path(path, glyphbuf, total_size);
   1665         }
   1666     }
   1667 }
   1668 
   1669 static void logfont_for_name(const char* familyName, LOGFONT* lf) {
   1670     sk_bzero(lf, sizeof(LOGFONT));
   1671 #ifdef UNICODE
   1672     // Get the buffer size needed first.
   1673     size_t str_len = ::MultiByteToWideChar(CP_UTF8, 0, familyName,
   1674                                             -1, nullptr, 0);
   1675     // Allocate a buffer (str_len already has terminating null
   1676     // accounted for).
   1677     wchar_t *wideFamilyName = new wchar_t[str_len];
   1678     // Now actually convert the string.
   1679     ::MultiByteToWideChar(CP_UTF8, 0, familyName, -1,
   1680                             wideFamilyName, str_len);
   1681     ::wcsncpy(lf->lfFaceName, wideFamilyName, LF_FACESIZE - 1);
   1682     delete [] wideFamilyName;
   1683     lf->lfFaceName[LF_FACESIZE-1] = L'\0';
   1684 #else
   1685     ::strncpy(lf->lfFaceName, familyName, LF_FACESIZE - 1);
   1686     lf->lfFaceName[LF_FACESIZE - 1] = '\0';
   1687 #endif
   1688 }
   1689 
   1690 void LogFontTypeface::onGetFamilyName(SkString* familyName) const {
   1691     // Get the actual name of the typeface. The logfont may not know this.
   1692     HFONT font = CreateFontIndirect(&fLogFont);
   1693 
   1694     HDC deviceContext = ::CreateCompatibleDC(nullptr);
   1695     HFONT savefont = (HFONT)SelectObject(deviceContext, font);
   1696 
   1697     dcfontname_to_skstring(deviceContext, fLogFont, familyName);
   1698 
   1699     if (deviceContext) {
   1700         ::SelectObject(deviceContext, savefont);
   1701         ::DeleteDC(deviceContext);
   1702     }
   1703     if (font) {
   1704         ::DeleteObject(font);
   1705     }
   1706 }
   1707 
   1708 void LogFontTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
   1709                                           bool* isLocalStream) const {
   1710     SkString familyName;
   1711     this->onGetFamilyName(&familyName);
   1712     desc->setFamilyName(familyName.c_str());
   1713     *isLocalStream = this->fSerializeAsStream;
   1714 }
   1715 
   1716 static bool getWidthAdvance(HDC hdc, int gId, int16_t* advance) {
   1717     // Initialize the MAT2 structure to the identify transformation matrix.
   1718     static const MAT2 mat2 = {SkScalarToFIXED(1), SkScalarToFIXED(0),
   1719                         SkScalarToFIXED(0), SkScalarToFIXED(1)};
   1720     int flags = GGO_METRICS | GGO_GLYPH_INDEX;
   1721     GLYPHMETRICS gm;
   1722     if (GDI_ERROR == GetGlyphOutline(hdc, gId, flags, &gm, 0, nullptr, &mat2)) {
   1723         return false;
   1724     }
   1725     SkASSERT(advance);
   1726     *advance = gm.gmCellIncX;
   1727     return true;
   1728 }
   1729 
   1730 SkAdvancedTypefaceMetrics* LogFontTypeface::onGetAdvancedTypefaceMetrics(
   1731         PerGlyphInfo perGlyphInfo,
   1732         const uint32_t* glyphIDs,
   1733         uint32_t glyphIDsCount) const {
   1734     LOGFONT lf = fLogFont;
   1735     SkAdvancedTypefaceMetrics* info = nullptr;
   1736 
   1737     HDC hdc = CreateCompatibleDC(nullptr);
   1738     HFONT font = CreateFontIndirect(&lf);
   1739     HFONT savefont = (HFONT)SelectObject(hdc, font);
   1740     HFONT designFont = nullptr;
   1741 
   1742     const char stem_chars[] = {'i', 'I', '!', '1'};
   1743     int16_t min_width;
   1744     unsigned glyphCount;
   1745 
   1746     // To request design units, create a logical font whose height is specified
   1747     // as unitsPerEm.
   1748     OUTLINETEXTMETRIC otm;
   1749     unsigned int otmRet = GetOutlineTextMetrics(hdc, sizeof(otm), &otm);
   1750     if (0 == otmRet) {
   1751         call_ensure_accessible(lf);
   1752         otmRet = GetOutlineTextMetrics(hdc, sizeof(otm), &otm);
   1753     }
   1754     if (!otmRet || !GetTextFace(hdc, LF_FACESIZE, lf.lfFaceName)) {
   1755         goto Error;
   1756     }
   1757     lf.lfHeight = -SkToS32(otm.otmEMSquare);
   1758     designFont = CreateFontIndirect(&lf);
   1759     SelectObject(hdc, designFont);
   1760     if (!GetOutlineTextMetrics(hdc, sizeof(otm), &otm)) {
   1761         goto Error;
   1762     }
   1763     glyphCount = calculateGlyphCount(hdc, fLogFont);
   1764 
   1765     info = new SkAdvancedTypefaceMetrics;
   1766     info->fEmSize = otm.otmEMSquare;
   1767     info->fLastGlyphID = SkToU16(glyphCount - 1);
   1768     tchar_to_skstring(lf.lfFaceName, &info->fFontName);
   1769     // If bit 1 is set, the font may not be embedded in a document.
   1770     // If bit 1 is clear, the font can be embedded.
   1771     // If bit 2 is set, the embedding is read-only.
   1772     if (otm.otmfsType & 0x1) {
   1773         info->fFlags = SkTBitOr<SkAdvancedTypefaceMetrics::FontFlags>(
   1774                 info->fFlags,
   1775                 SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag);
   1776     }
   1777 
   1778     if (perGlyphInfo & kToUnicode_PerGlyphInfo) {
   1779         populate_glyph_to_unicode(hdc, glyphCount, &(info->fGlyphToUnicode));
   1780     }
   1781 
   1782     if (glyphCount > 0 &&
   1783         (otm.otmTextMetrics.tmPitchAndFamily & TMPF_TRUETYPE)) {
   1784         info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font;
   1785     } else {
   1786         goto ReturnInfo;
   1787     }
   1788 
   1789     // If this bit is clear the font is a fixed pitch font.
   1790     if (!(otm.otmTextMetrics.tmPitchAndFamily & TMPF_FIXED_PITCH)) {
   1791         info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;
   1792     }
   1793     if (otm.otmTextMetrics.tmItalic) {
   1794         info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style;
   1795     }
   1796     if (otm.otmTextMetrics.tmPitchAndFamily & FF_ROMAN) {
   1797         info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;
   1798     } else if (otm.otmTextMetrics.tmPitchAndFamily & FF_SCRIPT) {
   1799             info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;
   1800     }
   1801 
   1802     // The main italic angle of the font, in tenths of a degree counterclockwise
   1803     // from vertical.
   1804     info->fItalicAngle = otm.otmItalicAngle / 10;
   1805     info->fAscent = SkToS16(otm.otmTextMetrics.tmAscent);
   1806     info->fDescent = SkToS16(-otm.otmTextMetrics.tmDescent);
   1807     // TODO(ctguil): Use alternate cap height calculation.
   1808     // MSDN says otmsCapEmHeight is not support but it is returning a value on
   1809     // my Win7 box.
   1810     info->fCapHeight = otm.otmsCapEmHeight;
   1811     info->fBBox =
   1812         SkIRect::MakeLTRB(otm.otmrcFontBox.left, otm.otmrcFontBox.top,
   1813                           otm.otmrcFontBox.right, otm.otmrcFontBox.bottom);
   1814 
   1815     // Figure out a good guess for StemV - Min width of i, I, !, 1.
   1816     // This probably isn't very good with an italic font.
   1817     min_width = SHRT_MAX;
   1818     info->fStemV = 0;
   1819     for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) {
   1820         ABC abcWidths;
   1821         if (GetCharABCWidths(hdc, stem_chars[i], stem_chars[i], &abcWidths)) {
   1822             int16_t width = abcWidths.abcB;
   1823             if (width > 0 && width < min_width) {
   1824                 min_width = width;
   1825                 info->fStemV = min_width;
   1826             }
   1827         }
   1828     }
   1829 
   1830     if (perGlyphInfo & kHAdvance_PerGlyphInfo) {
   1831         if (info->fStyle & SkAdvancedTypefaceMetrics::kFixedPitch_Style) {
   1832             appendRange(&info->fGlyphWidths, 0);
   1833             info->fGlyphWidths->fAdvance.append(1, &min_width);
   1834             finishRange(info->fGlyphWidths.get(), 0,
   1835                         SkAdvancedTypefaceMetrics::WidthRange::kDefault);
   1836         } else {
   1837             info->fGlyphWidths.reset(
   1838                 getAdvanceData(hdc,
   1839                                glyphCount,
   1840                                glyphIDs,
   1841                                glyphIDsCount,
   1842                                &getWidthAdvance));
   1843         }
   1844     }
   1845 
   1846 Error:
   1847 ReturnInfo:
   1848     SelectObject(hdc, savefont);
   1849     DeleteObject(designFont);
   1850     DeleteObject(font);
   1851     DeleteDC(hdc);
   1852 
   1853     return info;
   1854 }
   1855 
   1856 //Dummy representation of a Base64 encoded GUID from create_unique_font_name.
   1857 #define BASE64_GUID_ID "XXXXXXXXXXXXXXXXXXXXXXXX"
   1858 //Length of GUID representation from create_id, including nullptr terminator.
   1859 #define BASE64_GUID_ID_LEN SK_ARRAY_COUNT(BASE64_GUID_ID)
   1860 
   1861 static_assert(BASE64_GUID_ID_LEN < LF_FACESIZE, "GUID_longer_than_facesize");
   1862 
   1863 /**
   1864    NameID 6 Postscript names cannot have the character '/'.
   1865    It would be easier to hex encode the GUID, but that is 32 bytes,
   1866    and many systems have issues with names longer than 28 bytes.
   1867    The following need not be any standard base64 encoding.
   1868    The encoded value is never decoded.
   1869 */
   1870 static const char postscript_safe_base64_encode[] =
   1871     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
   1872     "abcdefghijklmnopqrstuvwxyz"
   1873     "0123456789-_=";
   1874 
   1875 /**
   1876    Formats a GUID into Base64 and places it into buffer.
   1877    buffer should have space for at least BASE64_GUID_ID_LEN characters.
   1878    The string will always be null terminated.
   1879    XXXXXXXXXXXXXXXXXXXXXXXX0
   1880  */
   1881 static void format_guid_b64(const GUID& guid, char* buffer, size_t bufferSize) {
   1882     SkASSERT(bufferSize >= BASE64_GUID_ID_LEN);
   1883     size_t written = SkBase64::Encode(&guid, sizeof(guid), buffer, postscript_safe_base64_encode);
   1884     SkASSERT(written < LF_FACESIZE);
   1885     buffer[written] = '\0';
   1886 }
   1887 
   1888 /**
   1889    Creates a Base64 encoded GUID and places it into buffer.
   1890    buffer should have space for at least BASE64_GUID_ID_LEN characters.
   1891    The string will always be null terminated.
   1892    XXXXXXXXXXXXXXXXXXXXXXXX0
   1893  */
   1894 static HRESULT create_unique_font_name(char* buffer, size_t bufferSize) {
   1895     GUID guid = {};
   1896     if (FAILED(CoCreateGuid(&guid))) {
   1897         return E_UNEXPECTED;
   1898     }
   1899     format_guid_b64(guid, buffer, bufferSize);
   1900 
   1901     return S_OK;
   1902 }
   1903 
   1904 /**
   1905    Introduces a font to GDI. On failure will return nullptr. The returned handle
   1906    should eventually be passed to RemoveFontMemResourceEx.
   1907 */
   1908 static HANDLE activate_font(SkData* fontData) {
   1909     DWORD numFonts = 0;
   1910     //AddFontMemResourceEx just copies the data, but does not specify const.
   1911     HANDLE fontHandle = AddFontMemResourceEx(const_cast<void*>(fontData->data()),
   1912                                              static_cast<DWORD>(fontData->size()),
   1913                                              0,
   1914                                              &numFonts);
   1915 
   1916     if (fontHandle != nullptr && numFonts < 1) {
   1917         RemoveFontMemResourceEx(fontHandle);
   1918         return nullptr;
   1919     }
   1920 
   1921     return fontHandle;
   1922 }
   1923 
   1924 // Does not affect ownership of stream.
   1925 static SkTypeface* create_from_stream(SkStreamAsset* stream) {
   1926     // Create a unique and unpredictable font name.
   1927     // Avoids collisions and access from CSS.
   1928     char familyName[BASE64_GUID_ID_LEN];
   1929     const int familyNameSize = SK_ARRAY_COUNT(familyName);
   1930     if (FAILED(create_unique_font_name(familyName, familyNameSize))) {
   1931         return nullptr;
   1932     }
   1933 
   1934     // Change the name of the font.
   1935     SkAutoTUnref<SkData> rewrittenFontData(SkOTUtils::RenameFont(stream, familyName, familyNameSize-1));
   1936     if (nullptr == rewrittenFontData.get()) {
   1937         return nullptr;
   1938     }
   1939 
   1940     // Register the font with GDI.
   1941     HANDLE fontReference = activate_font(rewrittenFontData.get());
   1942     if (nullptr == fontReference) {
   1943         return nullptr;
   1944     }
   1945 
   1946     // Create the typeface.
   1947     LOGFONT lf;
   1948     logfont_for_name(familyName, &lf);
   1949 
   1950     return SkCreateFontMemResourceTypefaceFromLOGFONT(lf, fontReference);
   1951 }
   1952 
   1953 SkStreamAsset* LogFontTypeface::onOpenStream(int* ttcIndex) const {
   1954     *ttcIndex = 0;
   1955 
   1956     const DWORD kTTCTag =
   1957         SkEndian_SwapBE32(SkSetFourByteTag('t', 't', 'c', 'f'));
   1958     LOGFONT lf = fLogFont;
   1959 
   1960     HDC hdc = ::CreateCompatibleDC(nullptr);
   1961     HFONT font = CreateFontIndirect(&lf);
   1962     HFONT savefont = (HFONT)SelectObject(hdc, font);
   1963 
   1964     SkMemoryStream* stream = nullptr;
   1965     DWORD tables[2] = {kTTCTag, 0};
   1966     for (int i = 0; i < SK_ARRAY_COUNT(tables); i++) {
   1967         DWORD bufferSize = GetFontData(hdc, tables[i], 0, nullptr, 0);
   1968         if (bufferSize == GDI_ERROR) {
   1969             call_ensure_accessible(lf);
   1970             bufferSize = GetFontData(hdc, tables[i], 0, nullptr, 0);
   1971         }
   1972         if (bufferSize != GDI_ERROR) {
   1973             stream = new SkMemoryStream(bufferSize);
   1974             if (GetFontData(hdc, tables[i], 0, (void*)stream->getMemoryBase(), bufferSize)) {
   1975                 break;
   1976             } else {
   1977                 delete stream;
   1978                 stream = nullptr;
   1979             }
   1980         }
   1981     }
   1982 
   1983     SelectObject(hdc, savefont);
   1984     DeleteObject(font);
   1985     DeleteDC(hdc);
   1986 
   1987     return stream;
   1988 }
   1989 
   1990 static void bmpCharsToGlyphs(HDC hdc, const WCHAR* bmpChars, int count, uint16_t* glyphs,
   1991                              bool Ox1FHack)
   1992 {
   1993     DWORD result = GetGlyphIndicesW(hdc, bmpChars, count, glyphs, GGI_MARK_NONEXISTING_GLYPHS);
   1994     if (GDI_ERROR == result) {
   1995         for (int i = 0; i < count; ++i) {
   1996             glyphs[i] = 0;
   1997         }
   1998         return;
   1999     }
   2000 
   2001     if (Ox1FHack) {
   2002         for (int i = 0; i < count; ++i) {
   2003             if (0xFFFF == glyphs[i] || 0x1F == glyphs[i]) {
   2004                 glyphs[i] = 0;
   2005             }
   2006         }
   2007     } else {
   2008         for (int i = 0; i < count; ++i) {
   2009             if (0xFFFF == glyphs[i]){
   2010                 glyphs[i] = 0;
   2011             }
   2012         }
   2013     }
   2014 }
   2015 
   2016 static uint16_t nonBmpCharToGlyph(HDC hdc, SCRIPT_CACHE* scriptCache, const WCHAR utf16[2]) {
   2017     uint16_t index = 0;
   2018     // Use uniscribe to detemine glyph index for non-BMP characters.
   2019     static const int numWCHAR = 2;
   2020     static const int maxItems = 2;
   2021     // MSDN states that this can be nullptr, but some things don't work then.
   2022     SCRIPT_CONTROL scriptControl = { 0 };
   2023     // Add extra item to SCRIPT_ITEM to work around a bug (now documented).
   2024     // https://bugzilla.mozilla.org/show_bug.cgi?id=366643
   2025     SCRIPT_ITEM si[maxItems + 1];
   2026     int numItems;
   2027     HRZM(ScriptItemize(utf16, numWCHAR, maxItems, &scriptControl, nullptr, si, &numItems),
   2028          "Could not itemize character.");
   2029 
   2030     // Sometimes ScriptShape cannot find a glyph for a non-BMP and returns 2 space glyphs.
   2031     static const int maxGlyphs = 2;
   2032     SCRIPT_VISATTR vsa[maxGlyphs];
   2033     WORD outGlyphs[maxGlyphs];
   2034     WORD logClust[numWCHAR];
   2035     int numGlyphs;
   2036     HRZM(ScriptShape(hdc, scriptCache, utf16, numWCHAR, maxGlyphs, &si[0].a,
   2037                      outGlyphs, logClust, vsa, &numGlyphs),
   2038          "Could not shape character.");
   2039     if (1 == numGlyphs) {
   2040         index = outGlyphs[0];
   2041     }
   2042     return index;
   2043 }
   2044 
   2045 class SkAutoHDC {
   2046 public:
   2047     SkAutoHDC(const LOGFONT& lf)
   2048         : fHdc(::CreateCompatibleDC(nullptr))
   2049         , fFont(::CreateFontIndirect(&lf))
   2050         , fSavefont((HFONT)SelectObject(fHdc, fFont))
   2051     { }
   2052     ~SkAutoHDC() {
   2053         SelectObject(fHdc, fSavefont);
   2054         DeleteObject(fFont);
   2055         DeleteDC(fHdc);
   2056     }
   2057     operator HDC() { return fHdc; }
   2058 private:
   2059     HDC fHdc;
   2060     HFONT fFont;
   2061     HFONT fSavefont;
   2062 };
   2063 #define SkAutoHDC(...) SK_REQUIRE_LOCAL_VAR(SkAutoHDC)
   2064 
   2065 int LogFontTypeface::onCharsToGlyphs(const void* chars, Encoding encoding,
   2066                                      uint16_t userGlyphs[], int glyphCount) const
   2067 {
   2068     SkAutoHDC hdc(fLogFont);
   2069 
   2070     TEXTMETRIC tm;
   2071     if (0 == GetTextMetrics(hdc, &tm)) {
   2072         call_ensure_accessible(fLogFont);
   2073         if (0 == GetTextMetrics(hdc, &tm)) {
   2074             tm.tmPitchAndFamily = TMPF_TRUETYPE;
   2075         }
   2076     }
   2077     bool Ox1FHack = !(tm.tmPitchAndFamily & TMPF_VECTOR) /*&& winVer < Vista */;
   2078 
   2079     SkAutoSTMalloc<256, uint16_t> scratchGlyphs;
   2080     uint16_t* glyphs;
   2081     if (userGlyphs != nullptr) {
   2082         glyphs = userGlyphs;
   2083     } else {
   2084         glyphs = scratchGlyphs.reset(glyphCount);
   2085     }
   2086 
   2087     SCRIPT_CACHE sc = 0;
   2088     switch (encoding) {
   2089     case SkTypeface::kUTF8_Encoding: {
   2090         static const int scratchCount = 256;
   2091         WCHAR scratch[scratchCount];
   2092         int glyphIndex = 0;
   2093         const char* currentUtf8 = reinterpret_cast<const char*>(chars);
   2094         SkUnichar currentChar;
   2095         if (glyphCount) {
   2096             currentChar = SkUTF8_NextUnichar(&currentUtf8);
   2097         }
   2098         while (glyphIndex < glyphCount) {
   2099             // Try a run of bmp.
   2100             int glyphsLeft = SkTMin(glyphCount - glyphIndex, scratchCount);
   2101             int runLength = 0;
   2102             while (runLength < glyphsLeft && currentChar <= 0xFFFF) {
   2103                 scratch[runLength] = static_cast<WCHAR>(currentChar);
   2104                 ++runLength;
   2105                 if (runLength < glyphsLeft) {
   2106                     currentChar = SkUTF8_NextUnichar(&currentUtf8);
   2107                 }
   2108             }
   2109             if (runLength) {
   2110                 bmpCharsToGlyphs(hdc, scratch, runLength, &glyphs[glyphIndex], Ox1FHack);
   2111                 glyphIndex += runLength;
   2112             }
   2113 
   2114             // Try a run of non-bmp.
   2115             while (glyphIndex < glyphCount && currentChar > 0xFFFF) {
   2116                 SkUTF16_FromUnichar(currentChar, reinterpret_cast<uint16_t*>(scratch));
   2117                 glyphs[glyphIndex] = nonBmpCharToGlyph(hdc, &sc, scratch);
   2118                 ++glyphIndex;
   2119                 if (glyphIndex < glyphCount) {
   2120                     currentChar = SkUTF8_NextUnichar(&currentUtf8);
   2121                 }
   2122             }
   2123         }
   2124         break;
   2125     }
   2126     case SkTypeface::kUTF16_Encoding: {
   2127         int glyphIndex = 0;
   2128         const WCHAR* currentUtf16 = reinterpret_cast<const WCHAR*>(chars);
   2129         while (glyphIndex < glyphCount) {
   2130             // Try a run of bmp.
   2131             int glyphsLeft = glyphCount - glyphIndex;
   2132             int runLength = 0;
   2133             while (runLength < glyphsLeft && !SkUTF16_IsHighSurrogate(currentUtf16[runLength])) {
   2134                 ++runLength;
   2135             }
   2136             if (runLength) {
   2137                 bmpCharsToGlyphs(hdc, currentUtf16, runLength, &glyphs[glyphIndex], Ox1FHack);
   2138                 glyphIndex += runLength;
   2139                 currentUtf16 += runLength;
   2140             }
   2141 
   2142             // Try a run of non-bmp.
   2143             while (glyphIndex < glyphCount && SkUTF16_IsHighSurrogate(*currentUtf16)) {
   2144                 glyphs[glyphIndex] = nonBmpCharToGlyph(hdc, &sc, currentUtf16);
   2145                 ++glyphIndex;
   2146                 currentUtf16 += 2;
   2147             }
   2148         }
   2149         break;
   2150     }
   2151     case SkTypeface::kUTF32_Encoding: {
   2152         static const int scratchCount = 256;
   2153         WCHAR scratch[scratchCount];
   2154         int glyphIndex = 0;
   2155         const uint32_t* utf32 = reinterpret_cast<const uint32_t*>(chars);
   2156         while (glyphIndex < glyphCount) {
   2157             // Try a run of bmp.
   2158             int glyphsLeft = SkTMin(glyphCount - glyphIndex, scratchCount);
   2159             int runLength = 0;
   2160             while (runLength < glyphsLeft && utf32[glyphIndex + runLength] <= 0xFFFF) {
   2161                 scratch[runLength] = static_cast<WCHAR>(utf32[glyphIndex + runLength]);
   2162                 ++runLength;
   2163             }
   2164             if (runLength) {
   2165                 bmpCharsToGlyphs(hdc, scratch, runLength, &glyphs[glyphIndex], Ox1FHack);
   2166                 glyphIndex += runLength;
   2167             }
   2168 
   2169             // Try a run of non-bmp.
   2170             while (glyphIndex < glyphCount && utf32[glyphIndex] > 0xFFFF) {
   2171                 SkUTF16_FromUnichar(utf32[glyphIndex], reinterpret_cast<uint16_t*>(scratch));
   2172                 glyphs[glyphIndex] = nonBmpCharToGlyph(hdc, &sc, scratch);
   2173                 ++glyphIndex;
   2174             }
   2175         }
   2176         break;
   2177     }
   2178     default:
   2179         SK_ABORT("Invalid Text Encoding");
   2180     }
   2181 
   2182     if (sc) {
   2183         ::ScriptFreeCache(&sc);
   2184     }
   2185 
   2186     for (int i = 0; i < glyphCount; ++i) {
   2187         if (0 == glyphs[i]) {
   2188             return i;
   2189         }
   2190     }
   2191     return glyphCount;
   2192 }
   2193 
   2194 int LogFontTypeface::onCountGlyphs() const {
   2195     HDC hdc = ::CreateCompatibleDC(nullptr);
   2196     HFONT font = CreateFontIndirect(&fLogFont);
   2197     HFONT savefont = (HFONT)SelectObject(hdc, font);
   2198 
   2199     unsigned int glyphCount = calculateGlyphCount(hdc, fLogFont);
   2200 
   2201     SelectObject(hdc, savefont);
   2202     DeleteObject(font);
   2203     DeleteDC(hdc);
   2204 
   2205     return glyphCount;
   2206 }
   2207 
   2208 int LogFontTypeface::onGetUPEM() const {
   2209     HDC hdc = ::CreateCompatibleDC(nullptr);
   2210     HFONT font = CreateFontIndirect(&fLogFont);
   2211     HFONT savefont = (HFONT)SelectObject(hdc, font);
   2212 
   2213     unsigned int upem = calculateUPEM(hdc, fLogFont);
   2214 
   2215     SelectObject(hdc, savefont);
   2216     DeleteObject(font);
   2217     DeleteDC(hdc);
   2218 
   2219     return upem;
   2220 }
   2221 
   2222 SkTypeface::LocalizedStrings* LogFontTypeface::onCreateFamilyNameIterator() const {
   2223     SkTypeface::LocalizedStrings* nameIter =
   2224         SkOTUtils::LocalizedStrings_NameTable::CreateForFamilyNames(*this);
   2225     if (nullptr == nameIter) {
   2226         SkString familyName;
   2227         this->getFamilyName(&familyName);
   2228         SkString language("und"); //undetermined
   2229         nameIter = new SkOTUtils::LocalizedStrings_SingleName(familyName, language);
   2230     }
   2231     return nameIter;
   2232 }
   2233 
   2234 int LogFontTypeface::onGetTableTags(SkFontTableTag tags[]) const {
   2235     SkSFNTHeader header;
   2236     if (sizeof(header) != this->onGetTableData(0, 0, sizeof(header), &header)) {
   2237         return 0;
   2238     }
   2239 
   2240     int numTables = SkEndian_SwapBE16(header.numTables);
   2241 
   2242     if (tags) {
   2243         size_t size = numTables * sizeof(SkSFNTHeader::TableDirectoryEntry);
   2244         SkAutoSTMalloc<0x20, SkSFNTHeader::TableDirectoryEntry> dir(numTables);
   2245         if (size != this->onGetTableData(0, sizeof(header), size, dir.get())) {
   2246             return 0;
   2247         }
   2248 
   2249         for (int i = 0; i < numTables; ++i) {
   2250             tags[i] = SkEndian_SwapBE32(dir[i].tag);
   2251         }
   2252     }
   2253     return numTables;
   2254 }
   2255 
   2256 size_t LogFontTypeface::onGetTableData(SkFontTableTag tag, size_t offset,
   2257                                        size_t length, void* data) const
   2258 {
   2259     LOGFONT lf = fLogFont;
   2260 
   2261     HDC hdc = ::CreateCompatibleDC(nullptr);
   2262     HFONT font = CreateFontIndirect(&lf);
   2263     HFONT savefont = (HFONT)SelectObject(hdc, font);
   2264 
   2265     tag = SkEndian_SwapBE32(tag);
   2266     if (nullptr == data) {
   2267         length = 0;
   2268     }
   2269     DWORD bufferSize = GetFontData(hdc, tag, (DWORD) offset, data, (DWORD) length);
   2270     if (bufferSize == GDI_ERROR) {
   2271         call_ensure_accessible(lf);
   2272         bufferSize = GetFontData(hdc, tag, (DWORD) offset, data, (DWORD) length);
   2273     }
   2274 
   2275     SelectObject(hdc, savefont);
   2276     DeleteObject(font);
   2277     DeleteDC(hdc);
   2278 
   2279     return bufferSize == GDI_ERROR ? 0 : bufferSize;
   2280 }
   2281 
   2282 SkScalerContext* LogFontTypeface::onCreateScalerContext(const SkDescriptor* desc) const {
   2283     SkScalerContext_GDI* ctx = new SkScalerContext_GDI(const_cast<LogFontTypeface*>(this), desc);
   2284     if (!ctx->isValid()) {
   2285         delete ctx;
   2286         ctx = nullptr;
   2287     }
   2288     return ctx;
   2289 }
   2290 
   2291 void LogFontTypeface::onFilterRec(SkScalerContextRec* rec) const {
   2292     if (rec->fFlags & SkScalerContext::kLCD_BGROrder_Flag ||
   2293         rec->fFlags & SkScalerContext::kLCD_Vertical_Flag)
   2294     {
   2295         rec->fMaskFormat = SkMask::kA8_Format;
   2296         rec->fFlags |= SkScalerContext::kGenA8FromLCD_Flag;
   2297     }
   2298 
   2299     unsigned flagsWeDontSupport = SkScalerContext::kVertical_Flag |
   2300                                   SkScalerContext::kDevKernText_Flag |
   2301                                   SkScalerContext::kForceAutohinting_Flag |
   2302                                   SkScalerContext::kEmbeddedBitmapText_Flag |
   2303                                   SkScalerContext::kEmbolden_Flag |
   2304                                   SkScalerContext::kLCD_BGROrder_Flag |
   2305                                   SkScalerContext::kLCD_Vertical_Flag;
   2306     rec->fFlags &= ~flagsWeDontSupport;
   2307 
   2308     SkPaint::Hinting h = rec->getHinting();
   2309     switch (h) {
   2310         case SkPaint::kNo_Hinting:
   2311             break;
   2312         case SkPaint::kSlight_Hinting:
   2313             // Only do slight hinting when axis aligned.
   2314             // TODO: re-enable slight hinting when FontHostTest can pass.
   2315             //if (!isAxisAligned(*rec)) {
   2316                 h = SkPaint::kNo_Hinting;
   2317             //}
   2318             break;
   2319         case SkPaint::kNormal_Hinting:
   2320         case SkPaint::kFull_Hinting:
   2321             // TODO: need to be able to distinguish subpixel positioned glyphs
   2322             // and linear metrics.
   2323             //rec->fFlags &= ~SkScalerContext::kSubpixelPositioning_Flag;
   2324             h = SkPaint::kNormal_Hinting;
   2325             break;
   2326         default:
   2327             SkDEBUGFAIL("unknown hinting");
   2328     }
   2329     //TODO: if this is a bitmap font, squash hinting and subpixel.
   2330     rec->setHinting(h);
   2331 
   2332 // turn this off since GDI might turn A8 into BW! Need a bigger fix.
   2333 #if 0
   2334     // Disable LCD when rotated, since GDI's output is ugly
   2335     if (isLCD(*rec) && !isAxisAligned(*rec)) {
   2336         rec->fMaskFormat = SkMask::kA8_Format;
   2337     }
   2338 #endif
   2339 
   2340     if (!fCanBeLCD && isLCD(*rec)) {
   2341         rec->fMaskFormat = SkMask::kA8_Format;
   2342         rec->fFlags &= ~SkScalerContext::kGenA8FromLCD_Flag;
   2343     }
   2344 }
   2345 
   2346 ///////////////////////////////////////////////////////////////////////////////
   2347 
   2348 #include "SkFontMgr.h"
   2349 #include "SkDataTable.h"
   2350 
   2351 static bool valid_logfont_for_enum(const LOGFONT& lf) {
   2352     // TODO: Vector FON is unsupported and should not be listed.
   2353     return
   2354         // Ignore implicit vertical variants.
   2355         lf.lfFaceName[0] && lf.lfFaceName[0] != '@'
   2356 
   2357         // DEFAULT_CHARSET is used to get all fonts, but also implies all
   2358         // character sets. Filter assuming all fonts support ANSI_CHARSET.
   2359         && ANSI_CHARSET == lf.lfCharSet
   2360     ;
   2361 }
   2362 
   2363 /** An EnumFontFamExProc implementation which interprets builderParam as
   2364  *  an SkTDArray<ENUMLOGFONTEX>* and appends logfonts which
   2365  *  pass the valid_logfont_for_enum predicate.
   2366  */
   2367 static int CALLBACK enum_family_proc(const LOGFONT* lf, const TEXTMETRIC*,
   2368                                      DWORD fontType, LPARAM builderParam) {
   2369     if (valid_logfont_for_enum(*lf)) {
   2370         SkTDArray<ENUMLOGFONTEX>* array = (SkTDArray<ENUMLOGFONTEX>*)builderParam;
   2371         *array->append() = *(ENUMLOGFONTEX*)lf;
   2372     }
   2373     return 1; // non-zero means continue
   2374 }
   2375 
   2376 class SkFontStyleSetGDI : public SkFontStyleSet {
   2377 public:
   2378     SkFontStyleSetGDI(const TCHAR familyName[]) {
   2379         LOGFONT lf;
   2380         sk_bzero(&lf, sizeof(lf));
   2381         lf.lfCharSet = DEFAULT_CHARSET;
   2382         _tcscpy_s(lf.lfFaceName, familyName);
   2383 
   2384         HDC hdc = ::CreateCompatibleDC(nullptr);
   2385         ::EnumFontFamiliesEx(hdc, &lf, enum_family_proc, (LPARAM)&fArray, 0);
   2386         ::DeleteDC(hdc);
   2387     }
   2388 
   2389     int count() override {
   2390         return fArray.count();
   2391     }
   2392 
   2393     void getStyle(int index, SkFontStyle* fs, SkString* styleName) override {
   2394         if (fs) {
   2395             *fs = get_style(fArray[index].elfLogFont);
   2396         }
   2397         if (styleName) {
   2398             const ENUMLOGFONTEX& ref = fArray[index];
   2399             // For some reason, ENUMLOGFONTEX and LOGFONT disagree on their type in the
   2400             // non-unicode version.
   2401             //      ENUMLOGFONTEX uses BYTE
   2402             //      LOGFONT uses CHAR
   2403             // Here we assert they that the style name is logically the same (size) as
   2404             // a TCHAR, so we can use the same converter function.
   2405             SkASSERT(sizeof(TCHAR) == sizeof(ref.elfStyle[0]));
   2406             tchar_to_skstring((const TCHAR*)ref.elfStyle, styleName);
   2407         }
   2408     }
   2409 
   2410     SkTypeface* createTypeface(int index) override {
   2411         return SkCreateTypefaceFromLOGFONT(fArray[index].elfLogFont);
   2412     }
   2413 
   2414     SkTypeface* matchStyle(const SkFontStyle& pattern) override {
   2415         return this->matchStyleCSS3(pattern);
   2416     }
   2417 
   2418 private:
   2419     SkTDArray<ENUMLOGFONTEX> fArray;
   2420 };
   2421 
   2422 class SkFontMgrGDI : public SkFontMgr {
   2423 public:
   2424     SkFontMgrGDI() {
   2425         LOGFONT lf;
   2426         sk_bzero(&lf, sizeof(lf));
   2427         lf.lfCharSet = DEFAULT_CHARSET;
   2428 
   2429         HDC hdc = ::CreateCompatibleDC(nullptr);
   2430         ::EnumFontFamiliesEx(hdc, &lf, enum_family_proc, (LPARAM)&fLogFontArray, 0);
   2431         ::DeleteDC(hdc);
   2432     }
   2433 
   2434 protected:
   2435     int onCountFamilies() const override {
   2436         return fLogFontArray.count();
   2437     }
   2438 
   2439     void onGetFamilyName(int index, SkString* familyName) const override {
   2440         SkASSERT((unsigned)index < (unsigned)fLogFontArray.count());
   2441         tchar_to_skstring(fLogFontArray[index].elfLogFont.lfFaceName, familyName);
   2442     }
   2443 
   2444     SkFontStyleSet* onCreateStyleSet(int index) const override {
   2445         SkASSERT((unsigned)index < (unsigned)fLogFontArray.count());
   2446         return new SkFontStyleSetGDI(fLogFontArray[index].elfLogFont.lfFaceName);
   2447     }
   2448 
   2449     SkFontStyleSet* onMatchFamily(const char familyName[]) const override {
   2450         if (nullptr == familyName) {
   2451             familyName = "";    // do we need this check???
   2452         }
   2453         LOGFONT lf;
   2454         logfont_for_name(familyName, &lf);
   2455         return new SkFontStyleSetGDI(lf.lfFaceName);
   2456     }
   2457 
   2458     virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
   2459                                            const SkFontStyle& fontstyle) const override {
   2460         // could be in base impl
   2461         SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
   2462         return sset->matchStyle(fontstyle);
   2463     }
   2464 
   2465     virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], const SkFontStyle&,
   2466                                                     const char* bcp47[], int bcp47Count,
   2467                                                     SkUnichar character) const override {
   2468         return nullptr;
   2469     }
   2470 
   2471     virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
   2472                                          const SkFontStyle& fontstyle) const override {
   2473         // could be in base impl
   2474         SkString familyName;
   2475         ((LogFontTypeface*)familyMember)->getFamilyName(&familyName);
   2476         return this->matchFamilyStyle(familyName.c_str(), fontstyle);
   2477     }
   2478 
   2479     SkTypeface* onCreateFromStream(SkStreamAsset* bareStream, int ttcIndex) const override {
   2480         SkAutoTDelete<SkStreamAsset> stream(bareStream);
   2481         return create_from_stream(stream);
   2482     }
   2483 
   2484     SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const override {
   2485         // could be in base impl
   2486         return this->createFromStream(new SkMemoryStream(data));
   2487     }
   2488 
   2489     SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override {
   2490         // could be in base impl
   2491         return this->createFromStream(SkStream::NewFromFile(path));
   2492     }
   2493 
   2494     virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
   2495                                                unsigned styleBits) const override {
   2496         LOGFONT lf;
   2497         if (nullptr == familyName) {
   2498             lf = get_default_font();
   2499         } else {
   2500             logfont_for_name(familyName, &lf);
   2501         }
   2502 
   2503         SkTypeface::Style style = (SkTypeface::Style)styleBits;
   2504         lf.lfWeight = (style & SkTypeface::kBold) != 0 ? FW_BOLD : FW_NORMAL;
   2505         lf.lfItalic = ((style & SkTypeface::kItalic) != 0);
   2506         return SkCreateTypefaceFromLOGFONT(lf);
   2507     }
   2508 
   2509 private:
   2510     SkTDArray<ENUMLOGFONTEX> fLogFontArray;
   2511 };
   2512 
   2513 ///////////////////////////////////////////////////////////////////////////////
   2514 
   2515 SkFontMgr* SkFontMgr_New_GDI() { return new SkFontMgrGDI; }
   2516 
   2517 #endif//defined(SK_BUILD_FOR_WIN32)
   2518