gfx/skia/trunk/src/ports/SkFontHost_win.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rwxr-xr-x

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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

mercurial