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