Home | History | Annotate | Download | only in ports
      1 
      2 /*
      3  * Copyright 2006 The Android Open Source Project
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 #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 "SkMaskGamma.h"
     18 #include "SkOTUtils.h"
     19 #include "SkPath.h"
     20 #include "SkStream.h"
     21 #include "SkString.h"
     22 #include "SkThread.h"
     23 #include "SkTypeface_win.h"
     24 #include "SkTypefaceCache.h"
     25 #include "SkUtils.h"
     26 
     27 #include "SkTypes.h"
     28 #include <tchar.h>
     29 #include <usp10.h>
     30 #include <objbase.h>
     31 
     32 static bool compute_bounds_outset(const LOGFONT& lf, SkIRect* outset) {
     33 
     34     static const struct {
     35         const char* fUCName;    // UTF8 encoded, ascii is upper-case
     36         SkIRect     fOutset;    // these are deltas for the glyph's bounds
     37     } gData[] = {
     38         // http://code.google.com/p/chromium/issues/detail?id=130842
     39         { "DOTUM", { 0, 0, 0, 1 } },
     40         { "DOTUMCHE", { 0, 0, 0, 1 } },
     41         { "\xEB\x8F\x8B\xEC\x9B\x80", { 0, 0, 0, 1 } },
     42         { "\xEB\x8F\x8B\xEC\x9B\x80\xEC\xB2\xB4", { 0, 0, 0, 1 } },
     43         { "MS UI GOTHIC", { 1, 0, 0, 0 } },
     44     };
     45 
     46     /**
     47      *  We convert the target name into upper-case (for ascii chars) UTF8.
     48      *  Our database is already stored in this fashion, and it allows us to
     49      *  search it with straight memcmp, since everyone is in this canonical
     50      *  form.
     51      */
     52 
     53     // temp storage is max # TCHARs * max expantion for UTF8 + null
     54     char name[kMaxBytesInUTF8Sequence * LF_FACESIZE + 1];
     55     int index = 0;
     56     for (int i = 0; i < LF_FACESIZE; ++i) {
     57         uint16_t c = lf.lfFaceName[i];
     58         if (c >= 'a' && c <= 'z') {
     59             c = c - 'a' + 'A';
     60         }
     61         size_t n = SkUTF16_ToUTF8(&c, 1, &name[index]);
     62         index += n;
     63         if (0 == c) {
     64             break;
     65         }
     66     }
     67 
     68     for (size_t j = 0; j < SK_ARRAY_COUNT(gData); ++j) {
     69         if (!strcmp(gData[j].fUCName, name)) {
     70             *outset = gData[j].fOutset;
     71             return true;
     72         }
     73     }
     74     return false;
     75 }
     76 
     77 // outset isn't really a rect, but 4 (non-negative) values to outset the
     78 // glyph's metrics by. For "normal" fonts, all these values should be 0.
     79 static void apply_outset(SkGlyph* glyph, const SkIRect& outset) {
     80     SkASSERT(outset.fLeft >= 0);
     81     SkASSERT(outset.fTop >= 0);
     82     SkASSERT(outset.fRight >= 0);
     83     SkASSERT(outset.fBottom >= 0);
     84 
     85     glyph->fLeft -= outset.fLeft;
     86     glyph->fTop -= outset.fTop;
     87     glyph->fWidth += outset.fLeft + outset.fRight;
     88     glyph->fHeight += outset.fTop + outset.fBottom;
     89 }
     90 
     91 // always packed xxRRGGBB
     92 typedef uint32_t SkGdiRGB;
     93 
     94 template <typename T> T* SkTAddByteOffset(T* ptr, size_t byteOffset) {
     95     return (T*)((char*)ptr + byteOffset);
     96 }
     97 
     98 // define this in your Makefile or .gyp to enforce AA requests
     99 // which GDI ignores at small sizes. This flag guarantees AA
    100 // for rotated text, regardless of GDI's notions.
    101 //#define SK_ENFORCE_ROTATED_TEXT_AA_ON_WINDOWS
    102 
    103 // client3d has to undefine this for now
    104 #define CAN_USE_LOGFONT_NAME
    105 
    106 static bool isLCD(const SkScalerContext::Rec& rec) {
    107     return SkMask::kLCD16_Format == rec.fMaskFormat ||
    108            SkMask::kLCD32_Format == rec.fMaskFormat;
    109 }
    110 
    111 static bool bothZero(SkScalar a, SkScalar b) {
    112     return 0 == a && 0 == b;
    113 }
    114 
    115 // returns false if there is any non-90-rotation or skew
    116 static bool isAxisAligned(const SkScalerContext::Rec& rec) {
    117     return 0 == rec.fPreSkewX &&
    118            (bothZero(rec.fPost2x2[0][1], rec.fPost2x2[1][0]) ||
    119             bothZero(rec.fPost2x2[0][0], rec.fPost2x2[1][1]));
    120 }
    121 
    122 static bool needToRenderWithSkia(const SkScalerContext::Rec& rec) {
    123 #ifdef SK_ENFORCE_ROTATED_TEXT_AA_ON_WINDOWS
    124     // What we really want to catch is when GDI will ignore the AA request and give
    125     // us BW instead. Smallish rotated text is one heuristic, so this code is just
    126     // an approximation. We shouldn't need to do this for larger sizes, but at those
    127     // sizes, the quality difference gets less and less between our general
    128     // scanconverter and GDI's.
    129     if (SkMask::kA8_Format == rec.fMaskFormat && !isAxisAligned(rec)) {
    130         return true;
    131     }
    132 #endif
    133     // false means allow GDI to generate the bits
    134     return false;
    135 }
    136 
    137 using namespace skia_advanced_typeface_metrics_utils;
    138 
    139 static const uint16_t BUFFERSIZE = (16384 - 32);
    140 static uint8_t glyphbuf[BUFFERSIZE];
    141 
    142 /**
    143  *  Since LOGFONT wants its textsize as an int, and we support fractional sizes,
    144  *  and since we have a cache of LOGFONTs for our tyepfaces, we always set the
    145  *  lfHeight to a canonical size, and then we use the 2x2 matrix to achieve the
    146  *  actual requested size.
    147  */
    148 static const int gCanonicalTextSize = 64;
    149 
    150 static void make_canonical(LOGFONT* lf) {
    151     lf->lfHeight = -gCanonicalTextSize;
    152     lf->lfQuality = CLEARTYPE_QUALITY;//PROOF_QUALITY;
    153     lf->lfCharSet = DEFAULT_CHARSET;
    154 //    lf->lfClipPrecision = 64;
    155 }
    156 
    157 static SkTypeface::Style get_style(const LOGFONT& lf) {
    158     unsigned style = 0;
    159     if (lf.lfWeight >= FW_BOLD) {
    160         style |= SkTypeface::kBold;
    161     }
    162     if (lf.lfItalic) {
    163         style |= SkTypeface::kItalic;
    164     }
    165     return static_cast<SkTypeface::Style>(style);
    166 }
    167 
    168 static void setStyle(LOGFONT* lf, SkTypeface::Style style) {
    169     lf->lfWeight = (style & SkTypeface::kBold) != 0 ? FW_BOLD : FW_NORMAL ;
    170     lf->lfItalic = ((style & SkTypeface::kItalic) != 0);
    171 }
    172 
    173 static inline FIXED SkFixedToFIXED(SkFixed x) {
    174     return *(FIXED*)(&x);
    175 }
    176 static inline SkFixed SkFIXEDToFixed(FIXED x) {
    177     return *(SkFixed*)(&x);
    178 }
    179 
    180 static inline FIXED SkScalarToFIXED(SkScalar x) {
    181     return SkFixedToFIXED(SkScalarToFixed(x));
    182 }
    183 
    184 static unsigned calculateOutlineGlyphCount(HDC hdc) {
    185     // The 'maxp' table stores the number of glyphs at offset 4, in 2 bytes.
    186     const DWORD maxpTag =
    187         SkEndian_SwapBE32(SkSetFourByteTag('m', 'a', 'x', 'p'));
    188     uint16_t glyphs;
    189     if (GetFontData(hdc, maxpTag, 4, &glyphs, sizeof(glyphs)) != GDI_ERROR) {
    190         return SkEndian_SwapBE16(glyphs);
    191     }
    192 
    193     // Binary search for glyph count.
    194     static const MAT2 mat2 = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
    195     int32_t max = SK_MaxU16 + 1;
    196     int32_t min = 0;
    197     GLYPHMETRICS gm;
    198     while (min < max) {
    199         int32_t mid = min + ((max - min) / 2);
    200         if (GetGlyphOutlineW(hdc, mid, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0,
    201                              NULL, &mat2) == GDI_ERROR) {
    202             max = mid;
    203         } else {
    204             min = mid + 1;
    205         }
    206     }
    207     SkASSERT(min == max);
    208     return min;
    209 }
    210 
    211 class LogFontTypeface : public SkTypeface {
    212 public:
    213     LogFontTypeface(SkTypeface::Style style, SkFontID fontID, const LOGFONT& lf, bool serializeAsStream = false) :
    214         SkTypeface(style, fontID, false), fLogFont(lf), fSerializeAsStream(serializeAsStream) {
    215 
    216         // If the font has cubic outlines, it will not be rendered with ClearType.
    217         HFONT font = CreateFontIndirect(&lf);
    218 
    219         HDC deviceContext = ::CreateCompatibleDC(NULL);
    220         HFONT savefont = (HFONT)SelectObject(deviceContext, font);
    221 
    222         TEXTMETRIC textMetric;
    223         if (0 == GetTextMetrics(deviceContext, &textMetric)) {
    224             SkFontHost::EnsureTypefaceAccessible(*this);
    225             if (0 == GetTextMetrics(deviceContext, &textMetric)) {
    226                 textMetric.tmPitchAndFamily = TMPF_TRUETYPE;
    227             }
    228         }
    229         if (deviceContext) {
    230             ::SelectObject(deviceContext, savefont);
    231             ::DeleteDC(deviceContext);
    232         }
    233         if (font) {
    234             ::DeleteObject(font);
    235         }
    236 
    237         // Used a logfont on a memory context, should never get a device font.
    238         // Therefore all TMPF_DEVICE will be PostScript (cubic) fonts.
    239         fCanBeLCD = !((textMetric.tmPitchAndFamily & TMPF_VECTOR) &&
    240                       (textMetric.tmPitchAndFamily & TMPF_DEVICE));
    241     }
    242 
    243     LOGFONT fLogFont;
    244     bool fSerializeAsStream;
    245     bool fCanBeLCD;
    246 
    247     static LogFontTypeface* Create(const LOGFONT& lf) {
    248         SkTypeface::Style style = get_style(lf);
    249         SkFontID fontID = SkTypefaceCache::NewFontID();
    250         return new LogFontTypeface(style, fontID, lf);
    251     }
    252 };
    253 
    254 class FontMemResourceTypeface : public LogFontTypeface {
    255 public:
    256     /**
    257      *  Takes ownership of fontMemResource.
    258      */
    259     FontMemResourceTypeface(SkTypeface::Style style, SkFontID fontID, const LOGFONT& lf, HANDLE fontMemResource) :
    260         LogFontTypeface(style, fontID, lf, true), fFontMemResource(fontMemResource) {
    261     }
    262 
    263     HANDLE fFontMemResource;
    264 
    265     /**
    266      *  The created FontMemResourceTypeface takes ownership of fontMemResource.
    267      */
    268     static FontMemResourceTypeface* Create(const LOGFONT& lf, HANDLE fontMemResource) {
    269         SkTypeface::Style style = get_style(lf);
    270         SkFontID fontID = SkTypefaceCache::NewFontID();
    271         return new FontMemResourceTypeface(style, fontID, lf, fontMemResource);
    272     }
    273 
    274 protected:
    275     virtual void weak_dispose() const SK_OVERRIDE {
    276         RemoveFontMemResourceEx(fFontMemResource);
    277         //SkTypefaceCache::Remove(this);
    278         INHERITED::weak_dispose();
    279     }
    280 
    281 private:
    282     typedef LogFontTypeface INHERITED;
    283 };
    284 
    285 static const LOGFONT& get_default_font() {
    286     static LOGFONT gDefaultFont;
    287     return gDefaultFont;
    288 }
    289 
    290 static bool FindByLogFont(SkTypeface* face, SkTypeface::Style requestedStyle, void* ctx) {
    291     LogFontTypeface* lface = static_cast<LogFontTypeface*>(face);
    292     const LOGFONT* lf = reinterpret_cast<const LOGFONT*>(ctx);
    293 
    294     return lface &&
    295            get_style(lface->fLogFont) == requestedStyle &&
    296            !memcmp(&lface->fLogFont, lf, sizeof(LOGFONT));
    297 }
    298 
    299 /**
    300  *  This guy is public. It first searches the cache, and if a match is not found,
    301  *  it creates a new face.
    302  */
    303 SkTypeface* SkCreateTypefaceFromLOGFONT(const LOGFONT& origLF) {
    304     LOGFONT lf = origLF;
    305     make_canonical(&lf);
    306     SkTypeface* face = SkTypefaceCache::FindByProcAndRef(FindByLogFont, &lf);
    307     if (NULL == face) {
    308         face = LogFontTypeface::Create(lf);
    309         SkTypefaceCache::Add(face, get_style(lf));
    310     }
    311     return face;
    312 }
    313 
    314 /**
    315  *  The created SkTypeface takes ownership of fontMemResource.
    316  */
    317 SkTypeface* SkCreateFontMemResourceTypefaceFromLOGFONT(const LOGFONT& origLF, HANDLE fontMemResource) {
    318     LOGFONT lf = origLF;
    319     make_canonical(&lf);
    320     FontMemResourceTypeface* face = FontMemResourceTypeface::Create(lf, fontMemResource);
    321     SkTypefaceCache::Add(face, get_style(lf), false);
    322     return face;
    323 }
    324 
    325 /**
    326  *  This guy is public
    327  */
    328 void SkLOGFONTFromTypeface(const SkTypeface* face, LOGFONT* lf) {
    329     if (NULL == face) {
    330         *lf = get_default_font();
    331     } else {
    332         *lf = static_cast<const LogFontTypeface*>(face)->fLogFont;
    333     }
    334 }
    335 
    336 SkFontID SkFontHost::NextLogicalFont(SkFontID currFontID, SkFontID origFontID) {
    337   // Zero means that we don't have any fallback fonts for this fontID.
    338   // This function is implemented on Android, but doesn't have much
    339   // meaning here.
    340   return 0;
    341 }
    342 
    343 static void ensure_typeface_accessible(SkFontID fontID) {
    344     LogFontTypeface* face = static_cast<LogFontTypeface*>(SkTypefaceCache::FindByID(fontID));
    345     if (face) {
    346         SkFontHost::EnsureTypefaceAccessible(*face);
    347     }
    348 }
    349 
    350 static void GetLogFontByID(SkFontID fontID, LOGFONT* lf) {
    351     LogFontTypeface* face = static_cast<LogFontTypeface*>(SkTypefaceCache::FindByID(fontID));
    352     if (face) {
    353         *lf = face->fLogFont;
    354     } else {
    355         sk_bzero(lf, sizeof(LOGFONT));
    356     }
    357 }
    358 
    359 // Construct Glyph to Unicode table.
    360 // Unicode code points that require conjugate pairs in utf16 are not
    361 // supported.
    362 // TODO(arthurhsu): Add support for conjugate pairs. It looks like that may
    363 // require parsing the TTF cmap table (platform 4, encoding 12) directly instead
    364 // of calling GetFontUnicodeRange().
    365 static void populate_glyph_to_unicode(HDC fontHdc, const unsigned glyphCount,
    366                                       SkTDArray<SkUnichar>* glyphToUnicode) {
    367     DWORD glyphSetBufferSize = GetFontUnicodeRanges(fontHdc, NULL);
    368     if (!glyphSetBufferSize) {
    369         return;
    370     }
    371 
    372     SkAutoTDeleteArray<BYTE> glyphSetBuffer(new BYTE[glyphSetBufferSize]);
    373     GLYPHSET* glyphSet =
    374         reinterpret_cast<LPGLYPHSET>(glyphSetBuffer.get());
    375     if (GetFontUnicodeRanges(fontHdc, glyphSet) != glyphSetBufferSize) {
    376         return;
    377     }
    378 
    379     glyphToUnicode->setCount(glyphCount);
    380     memset(glyphToUnicode->begin(), 0, glyphCount * sizeof(SkUnichar));
    381     for (DWORD i = 0; i < glyphSet->cRanges; ++i) {
    382         // There is no guarantee that within a Unicode range, the corresponding
    383         // glyph id in a font file are continuous. So, even if we have ranges,
    384         // we can't just use the first and last entry of the range to compute
    385         // result. We need to enumerate them one by one.
    386         int count = glyphSet->ranges[i].cGlyphs;
    387         SkAutoTArray<WCHAR> chars(count + 1);
    388         chars[count] = 0;  // termintate string
    389         SkAutoTArray<WORD> glyph(count);
    390         for (USHORT j = 0; j < count; ++j) {
    391             chars[j] = glyphSet->ranges[i].wcLow + j;
    392         }
    393         GetGlyphIndicesW(fontHdc, chars.get(), count, glyph.get(),
    394                          GGI_MARK_NONEXISTING_GLYPHS);
    395         // If the glyph ID is valid, and the glyph is not mapped, then we will
    396         // fill in the char id into the vector. If the glyph is mapped already,
    397         // skip it.
    398         // TODO(arthurhsu): better improve this. e.g. Get all used char ids from
    399         // font cache, then generate this mapping table from there. It's
    400         // unlikely to have collisions since glyph reuse happens mostly for
    401         // different Unicode pages.
    402         for (USHORT j = 0; j < count; ++j) {
    403             if (glyph[j] != 0xffff && glyph[j] < glyphCount &&
    404                 (*glyphToUnicode)[glyph[j]] == 0) {
    405                 (*glyphToUnicode)[glyph[j]] = chars[j];
    406             }
    407         }
    408     }
    409 }
    410 
    411 //////////////////////////////////////////////////////////////////////////////////////
    412 
    413 static int alignTo32(int n) {
    414     return (n + 31) & ~31;
    415 }
    416 
    417 struct MyBitmapInfo : public BITMAPINFO {
    418     RGBQUAD fMoreSpaceForColors[1];
    419 };
    420 
    421 class HDCOffscreen {
    422 public:
    423     HDCOffscreen() {
    424         fFont = 0;
    425         fDC = 0;
    426         fBM = 0;
    427         fBits = NULL;
    428         fWidth = fHeight = 0;
    429         fIsBW = false;
    430     }
    431 
    432     ~HDCOffscreen() {
    433         if (fDC) {
    434             DeleteDC(fDC);
    435         }
    436         if (fBM) {
    437             DeleteObject(fBM);
    438         }
    439     }
    440 
    441     void init(HFONT font, const XFORM& xform) {
    442         fFont = font;
    443         fXform = xform;
    444     }
    445 
    446     const void* draw(const SkGlyph&, bool isBW, size_t* srcRBPtr);
    447 
    448 private:
    449     HDC     fDC;
    450     HBITMAP fBM;
    451     HFONT   fFont;
    452     XFORM   fXform;
    453     void*   fBits;  // points into fBM
    454     int     fWidth;
    455     int     fHeight;
    456     bool    fIsBW;
    457 
    458     enum {
    459         // will always trigger us to reset the color, since we
    460         // should only store 0 or 0x00FFFFFF or gray (0x007F7F7F)
    461         kInvalid_Color = 12345
    462     };
    463 };
    464 
    465 const void* HDCOffscreen::draw(const SkGlyph& glyph, bool isBW,
    466                                size_t* srcRBPtr) {
    467     if (0 == fDC) {
    468         fDC = CreateCompatibleDC(0);
    469         if (0 == fDC) {
    470             return NULL;
    471         }
    472         SetGraphicsMode(fDC, GM_ADVANCED);
    473         SetBkMode(fDC, TRANSPARENT);
    474         SetTextAlign(fDC, TA_LEFT | TA_BASELINE);
    475         SelectObject(fDC, fFont);
    476 
    477         COLORREF color = 0x00FFFFFF;
    478         COLORREF prev = SetTextColor(fDC, color);
    479         SkASSERT(prev != CLR_INVALID);
    480     }
    481 
    482     if (fBM && (fIsBW != isBW || fWidth < glyph.fWidth || fHeight < glyph.fHeight)) {
    483         DeleteObject(fBM);
    484         fBM = 0;
    485     }
    486     fIsBW = isBW;
    487 
    488     fWidth = SkMax32(fWidth, glyph.fWidth);
    489     fHeight = SkMax32(fHeight, glyph.fHeight);
    490 
    491     int biWidth = isBW ? alignTo32(fWidth) : fWidth;
    492 
    493     if (0 == fBM) {
    494         MyBitmapInfo info;
    495         sk_bzero(&info, sizeof(info));
    496         if (isBW) {
    497             RGBQUAD blackQuad = { 0, 0, 0, 0 };
    498             RGBQUAD whiteQuad = { 0xFF, 0xFF, 0xFF, 0 };
    499             info.bmiColors[0] = blackQuad;
    500             info.bmiColors[1] = whiteQuad;
    501         }
    502         info.bmiHeader.biSize = sizeof(info.bmiHeader);
    503         info.bmiHeader.biWidth = biWidth;
    504         info.bmiHeader.biHeight = fHeight;
    505         info.bmiHeader.biPlanes = 1;
    506         info.bmiHeader.biBitCount = isBW ? 1 : 32;
    507         info.bmiHeader.biCompression = BI_RGB;
    508         if (isBW) {
    509             info.bmiHeader.biClrUsed = 2;
    510         }
    511         fBM = CreateDIBSection(fDC, &info, DIB_RGB_COLORS, &fBits, 0, 0);
    512         if (0 == fBM) {
    513             return NULL;
    514         }
    515         SelectObject(fDC, fBM);
    516     }
    517 
    518     // erase
    519     size_t srcRB = isBW ? (biWidth >> 3) : (fWidth << 2);
    520     size_t size = fHeight * srcRB;
    521     memset(fBits, 0, size);
    522 
    523     XFORM xform = fXform;
    524     xform.eDx = (float)-glyph.fLeft;
    525     xform.eDy = (float)-glyph.fTop;
    526     SetWorldTransform(fDC, &xform);
    527 
    528     uint16_t glyphID = glyph.getGlyphID();
    529     BOOL ret = ExtTextOutW(fDC, 0, 0, ETO_GLYPH_INDEX, NULL, reinterpret_cast<LPCWSTR>(&glyphID), 1, NULL);
    530     GdiFlush();
    531     if (0 == ret) {
    532         return NULL;
    533     }
    534     *srcRBPtr = srcRB;
    535     // offset to the start of the image
    536     return (const char*)fBits + (fHeight - glyph.fHeight) * srcRB;
    537 }
    538 
    539 //////////////////////////////////////////////////////////////////////////////
    540 
    541 class SkScalerContext_Windows : public SkScalerContext {
    542 public:
    543     SkScalerContext_Windows(const SkDescriptor* desc);
    544     virtual ~SkScalerContext_Windows();
    545 
    546 protected:
    547     virtual unsigned generateGlyphCount() SK_OVERRIDE;
    548     virtual uint16_t generateCharToGlyph(SkUnichar uni) SK_OVERRIDE;
    549     virtual void generateAdvance(SkGlyph* glyph) SK_OVERRIDE;
    550     virtual void generateMetrics(SkGlyph* glyph) SK_OVERRIDE;
    551     virtual void generateImage(const SkGlyph& glyph) SK_OVERRIDE;
    552     virtual void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE;
    553     virtual void generateFontMetrics(SkPaint::FontMetrics* mX,
    554                                      SkPaint::FontMetrics* mY) SK_OVERRIDE;
    555 
    556 private:
    557     HDCOffscreen fOffscreen;
    558     SkScalar     fScale;  // to get from canonical size to real size
    559     MAT2         fMat22;
    560     XFORM        fXform;
    561     HDC          fDDC;
    562     HFONT        fSavefont;
    563     HFONT        fFont;
    564     SCRIPT_CACHE fSC;
    565     int          fGlyphCount;
    566 
    567     /**
    568      *  Some fonts need extra pixels added to avoid clipping, as the bounds
    569      *  returned by getOutlineMetrics does not match what GDI draws. Since
    570      *  this costs more RAM and therefore slower blits, we have a table to
    571      *  only do this for known "bad" fonts.
    572      */
    573     SkIRect      fOutset;
    574 
    575     HFONT        fHiResFont;
    576     MAT2         fMat22Identity;
    577     SkMatrix     fHiResMatrix;
    578     enum Type {
    579         kTrueType_Type, kBitmap_Type,
    580     } fType;
    581     TEXTMETRIC fTM;
    582 };
    583 
    584 static float mul2float(SkScalar a, SkScalar b) {
    585     return SkScalarToFloat(SkScalarMul(a, b));
    586 }
    587 
    588 static FIXED float2FIXED(float x) {
    589     return SkFixedToFIXED(SkFloatToFixed(x));
    590 }
    591 
    592 SK_DECLARE_STATIC_MUTEX(gFTMutex);
    593 
    594 #define HIRES_TEXTSIZE  2048
    595 #define HIRES_SHIFT     11
    596 static inline SkFixed HiResToFixed(int value) {
    597     return value << (16 - HIRES_SHIFT);
    598 }
    599 
    600 static bool needHiResMetrics(const SkScalar mat[2][2]) {
    601     return mat[1][0] || mat[0][1];
    602 }
    603 
    604 static BYTE compute_quality(const SkScalerContext::Rec& rec) {
    605     switch (rec.fMaskFormat) {
    606         case SkMask::kBW_Format:
    607             return NONANTIALIASED_QUALITY;
    608         case SkMask::kLCD16_Format:
    609         case SkMask::kLCD32_Format:
    610             return CLEARTYPE_QUALITY;
    611         default:
    612             if (rec.fFlags & SkScalerContext::kGenA8FromLCD_Flag) {
    613                 return CLEARTYPE_QUALITY;
    614             } else {
    615                 return ANTIALIASED_QUALITY;
    616             }
    617     }
    618 }
    619 
    620 SkScalerContext_Windows::SkScalerContext_Windows(const SkDescriptor* desc)
    621         : SkScalerContext(desc), fDDC(0), fFont(0), fSavefont(0), fSC(0)
    622         , fGlyphCount(-1) {
    623     SkAutoMutexAcquire  ac(gFTMutex);
    624 
    625     fDDC = ::CreateCompatibleDC(NULL);
    626     SetGraphicsMode(fDDC, GM_ADVANCED);
    627     SetBkMode(fDDC, TRANSPARENT);
    628 
    629     // Scaling by the DPI is inconsistent with how Skia draws elsewhere
    630     //SkScalar height = -(fRec.fTextSize * GetDeviceCaps(ddc, LOGPIXELSY) / 72);
    631     LOGFONT lf;
    632     GetLogFontByID(fRec.fFontID, &lf);
    633     lf.lfHeight = -gCanonicalTextSize;
    634     lf.lfQuality = compute_quality(fRec);
    635     fFont = CreateFontIndirect(&lf);
    636 
    637     if (!compute_bounds_outset(lf, &fOutset)) {
    638         fOutset.setEmpty();
    639     }
    640 
    641     // if we're rotated, or want fractional widths, create a hires font
    642     fHiResFont = 0;
    643     if (needHiResMetrics(fRec.fPost2x2)) {
    644         lf.lfHeight = -HIRES_TEXTSIZE;
    645         fHiResFont = CreateFontIndirect(&lf);
    646 
    647         fMat22Identity.eM11 = fMat22Identity.eM22 = SkFixedToFIXED(SK_Fixed1);
    648         fMat22Identity.eM12 = fMat22Identity.eM21 = SkFixedToFIXED(0);
    649 
    650         // construct a matrix to go from HIRES logical units to our device units
    651         fRec.getSingleMatrix(&fHiResMatrix);
    652         SkScalar scale = SkScalarInvert(SkIntToScalar(HIRES_TEXTSIZE));
    653         fHiResMatrix.preScale(scale, scale);
    654     }
    655     fSavefont = (HFONT)SelectObject(fDDC, fFont);
    656 
    657     if (0 == GetTextMetrics(fDDC, &fTM)) {
    658         ensure_typeface_accessible(fRec.fFontID);
    659         if (0 == GetTextMetrics(fDDC, &fTM)) {
    660             fTM.tmPitchAndFamily = TMPF_TRUETYPE;
    661         }
    662     }
    663     // Used a logfont on a memory context, should never get a device font.
    664     // Therefore all TMPF_DEVICE will be PostScript fonts.
    665 
    666     // If TMPF_VECTOR is set, one of TMPF_TRUETYPE or TMPF_DEVICE must be set,
    667     // otherwise we have a vector FON, which we don't support.
    668     // This was determined by testing with Type1 PFM/PFB and OpenTypeCFF OTF,
    669     // as well as looking at Wine bugs and sources.
    670     SkASSERT(!(fTM.tmPitchAndFamily & TMPF_VECTOR) ||
    671               (fTM.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_DEVICE)));
    672 
    673     if (fTM.tmPitchAndFamily & TMPF_VECTOR) {
    674         // Truetype or PostScript.
    675         // Stroked FON also gets here (TMPF_VECTOR), but we don't handle it.
    676         fType = SkScalerContext_Windows::kTrueType_Type;
    677         fScale = fRec.fTextSize / gCanonicalTextSize;
    678 
    679         fXform.eM11 = mul2float(fScale, fRec.fPost2x2[0][0]);
    680         fXform.eM12 = mul2float(fScale, fRec.fPost2x2[1][0]);
    681         fXform.eM21 = mul2float(fScale, fRec.fPost2x2[0][1]);
    682         fXform.eM22 = mul2float(fScale, fRec.fPost2x2[1][1]);
    683         fXform.eDx = 0;
    684         fXform.eDy = 0;
    685 
    686         fMat22.eM11 = float2FIXED(fXform.eM11);
    687         fMat22.eM12 = float2FIXED(fXform.eM12);
    688         fMat22.eM21 = float2FIXED(-fXform.eM21);
    689         fMat22.eM22 = float2FIXED(-fXform.eM22);
    690 
    691         if (needToRenderWithSkia(fRec)) {
    692             this->forceGenerateImageFromPath();
    693         }
    694 
    695     } else {
    696         // Assume bitmap
    697         fType = SkScalerContext_Windows::kBitmap_Type;
    698         fScale = SK_Scalar1;
    699 
    700         fXform.eM11 = 1.0f;
    701         fXform.eM12 = 0.0f;
    702         fXform.eM21 = 0.0f;
    703         fXform.eM22 = 1.0f;
    704         fXform.eDx = 0.0f;
    705         fXform.eDy = 0.0f;
    706 
    707         fMat22.eM11 = SkScalarToFIXED(fRec.fPost2x2[0][0]);
    708         fMat22.eM12 = SkScalarToFIXED(fRec.fPost2x2[1][0]);
    709         fMat22.eM21 = SkScalarToFIXED(-fRec.fPost2x2[0][1]);
    710         fMat22.eM22 = SkScalarToFIXED(-fRec.fPost2x2[1][1]);
    711 
    712         lf.lfHeight = -SkScalarCeilToInt(fRec.fTextSize);
    713         HFONT bitmapFont = CreateFontIndirect(&lf);
    714         SelectObject(fDDC, bitmapFont);
    715         ::DeleteObject(fFont);
    716         fFont = bitmapFont;
    717 
    718         if (0 == GetTextMetrics(fDDC, &fTM)) {
    719             ensure_typeface_accessible(fRec.fFontID);
    720             //if the following fails, we'll just draw at gCanonicalTextSize.
    721             GetTextMetrics(fDDC, &fTM);
    722         }
    723     }
    724 
    725     fOffscreen.init(fFont, fXform);
    726 }
    727 
    728 SkScalerContext_Windows::~SkScalerContext_Windows() {
    729     if (fDDC) {
    730         ::SelectObject(fDDC, fSavefont);
    731         ::DeleteDC(fDDC);
    732     }
    733     if (fFont) {
    734         ::DeleteObject(fFont);
    735     }
    736     if (fHiResFont) {
    737         ::DeleteObject(fHiResFont);
    738     }
    739     if (fSC) {
    740         ::ScriptFreeCache(&fSC);
    741     }
    742 }
    743 
    744 unsigned SkScalerContext_Windows::generateGlyphCount() {
    745     if (fGlyphCount < 0) {
    746         if (fType == SkScalerContext_Windows::kBitmap_Type) {
    747            return fTM.tmLastChar;
    748         }
    749         fGlyphCount = calculateOutlineGlyphCount(fDDC);
    750     }
    751     return fGlyphCount;
    752 }
    753 
    754 uint16_t SkScalerContext_Windows::generateCharToGlyph(SkUnichar uni) {
    755     uint16_t index = 0;
    756     WCHAR c[2];
    757     // TODO(ctguil): Support characters that generate more than one glyph.
    758     if (SkUTF16_FromUnichar(uni, (uint16_t*)c) == 1) {
    759         // Type1 fonts fail with uniscribe API. Use GetGlyphIndices for plane 0.
    760         SkAssertResult(GetGlyphIndicesW(fDDC, c, 1, &index, 0));
    761     } else {
    762         // Use uniscribe to detemine glyph index for non-BMP characters.
    763         // Need to add extra item to SCRIPT_ITEM to work around a bug in older
    764         // windows versions. https://bugzilla.mozilla.org/show_bug.cgi?id=366643
    765         SCRIPT_ITEM si[2 + 1];
    766         int items;
    767         SkAssertResult(
    768             SUCCEEDED(ScriptItemize(c, 2, 2, NULL, NULL, si, &items)));
    769 
    770         WORD log[2];
    771         SCRIPT_VISATTR vsa;
    772         int glyphs;
    773         SkAssertResult(SUCCEEDED(ScriptShape(
    774             fDDC, &fSC, c, 2, 1, &si[0].a, &index, log, &vsa, &glyphs)));
    775     }
    776     return index;
    777 }
    778 
    779 void SkScalerContext_Windows::generateAdvance(SkGlyph* glyph) {
    780     this->generateMetrics(glyph);
    781 }
    782 
    783 void SkScalerContext_Windows::generateMetrics(SkGlyph* glyph) {
    784 
    785     SkASSERT(fDDC);
    786 
    787     if (fType == SkScalerContext_Windows::kBitmap_Type) {
    788         SIZE size;
    789         WORD glyphs = glyph->getGlyphID(0);
    790         if (0 == GetTextExtentPointI(fDDC, &glyphs, 1, &size)) {
    791             glyph->fWidth = SkToS16(fTM.tmMaxCharWidth);
    792         } else {
    793             glyph->fWidth = SkToS16(size.cx);
    794         }
    795         glyph->fHeight = SkToS16(size.cy);
    796 
    797         glyph->fTop = SkToS16(-fTM.tmAscent);
    798         glyph->fLeft = SkToS16(0);
    799         glyph->fAdvanceX = SkIntToFixed(glyph->fWidth);
    800         glyph->fAdvanceY = 0;
    801 
    802         //Apply matrix to values.
    803         glyph->fAdvanceY = SkFixedMul(SkFIXEDToFixed(fMat22.eM21), glyph->fAdvanceX);
    804         glyph->fAdvanceX = SkFixedMul(SkFIXEDToFixed(fMat22.eM11), glyph->fAdvanceX);
    805 
    806         apply_outset(glyph, fOutset);
    807         return;
    808     }
    809 
    810     GLYPHMETRICS gm;
    811     sk_bzero(&gm, sizeof(gm));
    812 
    813     glyph->fRsbDelta = 0;
    814     glyph->fLsbDelta = 0;
    815 
    816     // Note: need to use GGO_GRAY8_BITMAP instead of GGO_METRICS because GGO_METRICS returns a smaller
    817     // BlackBlox; we need the bigger one in case we need the image.  fAdvance is the same.
    818     uint32_t ret = GetGlyphOutlineW(fDDC, glyph->getGlyphID(0), GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX, &gm, 0, NULL, &fMat22);
    819     if (GDI_ERROR == ret) {
    820         ensure_typeface_accessible(fRec.fFontID);
    821         ret = GetGlyphOutlineW(fDDC, glyph->getGlyphID(0), GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX, &gm, 0, NULL, &fMat22);
    822     }
    823 
    824     if (GDI_ERROR != ret) {
    825         if (ret == 0) {
    826             // for white space, ret is zero and gmBlackBoxX, gmBlackBoxY are 1 incorrectly!
    827             gm.gmBlackBoxX = gm.gmBlackBoxY = 0;
    828         }
    829         glyph->fWidth   = gm.gmBlackBoxX;
    830         glyph->fHeight  = gm.gmBlackBoxY;
    831         glyph->fTop     = SkToS16(gm.gmptGlyphOrigin.y - gm.gmBlackBoxY);
    832         glyph->fLeft    = SkToS16(gm.gmptGlyphOrigin.x);
    833         glyph->fAdvanceX = SkIntToFixed(gm.gmCellIncX);
    834         glyph->fAdvanceY = -SkIntToFixed(gm.gmCellIncY);
    835 
    836         // we outset in all dimensions, since the image may bleed outside
    837         // of the computed bounds returned by GetGlyphOutline.
    838         // This was deduced by trial and error for small text (e.g. 8pt), so there
    839         // maybe a more precise way to make this adjustment...
    840         //
    841         // This test shows us clipping the tops of some of the CJK fonts unless we
    842         // increase the top of the box by 2, hence the height by 4. This seems to
    843         // correspond to an embedded bitmap font, but not sure.
    844         //     LayoutTests/fast/text/backslash-to-yen-sign-euc.html
    845         //
    846         if (glyph->fWidth) {    // don't outset an empty glyph
    847             glyph->fWidth += 4;
    848             glyph->fHeight += 4;
    849             glyph->fTop -= 2;
    850             glyph->fLeft -= 2;
    851 
    852             apply_outset(glyph, fOutset);
    853         }
    854 
    855         if (fHiResFont) {
    856             SelectObject(fDDC, fHiResFont);
    857             sk_bzero(&gm, sizeof(gm));
    858             ret = GetGlyphOutlineW(fDDC, glyph->getGlyphID(0), GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, NULL, &fMat22Identity);
    859             if (GDI_ERROR != ret) {
    860                 SkPoint advance;
    861                 fHiResMatrix.mapXY(SkIntToScalar(gm.gmCellIncX), SkIntToScalar(gm.gmCellIncY), &advance);
    862                 glyph->fAdvanceX = SkScalarToFixed(advance.fX);
    863                 glyph->fAdvanceY = SkScalarToFixed(advance.fY);
    864             }
    865             SelectObject(fDDC, fFont);
    866         }
    867     } else {
    868         glyph->zeroMetrics();
    869     }
    870 }
    871 
    872 void SkScalerContext_Windows::generateFontMetrics(SkPaint::FontMetrics* mx, SkPaint::FontMetrics* my) {
    873 // Note: This code was borrowed from generateLineHeight, which has a note
    874 // stating that it may be incorrect.
    875     if (!(mx || my))
    876       return;
    877 
    878     SkASSERT(fDDC);
    879 
    880     if (fType == SkScalerContext_Windows::kBitmap_Type) {
    881         if (mx) {
    882             mx->fTop = SkIntToScalar(-fTM.tmAscent);
    883             mx->fAscent = SkIntToScalar(-fTM.tmAscent);
    884             mx->fDescent = -SkIntToScalar(fTM.tmDescent);
    885             mx->fBottom = SkIntToScalar(fTM.tmDescent);
    886             mx->fLeading = SkIntToScalar(fTM.tmInternalLeading
    887                                          + fTM.tmExternalLeading);
    888         }
    889 
    890         if (my) {
    891             my->fTop = SkIntToScalar(-fTM.tmAscent);
    892             my->fAscent = SkIntToScalar(-fTM.tmAscent);
    893             my->fDescent = SkIntToScalar(-fTM.tmDescent);
    894             my->fBottom = SkIntToScalar(fTM.tmDescent);
    895             my->fLeading = SkIntToScalar(fTM.tmInternalLeading
    896                                          + fTM.tmExternalLeading);
    897         }
    898         return;
    899     }
    900 
    901     OUTLINETEXTMETRIC otm;
    902 
    903     uint32_t ret = GetOutlineTextMetrics(fDDC, sizeof(otm), &otm);
    904     if (GDI_ERROR == ret) {
    905         ensure_typeface_accessible(fRec.fFontID);
    906         ret = GetOutlineTextMetrics(fDDC, sizeof(otm), &otm);
    907     }
    908     if (sizeof(otm) != ret) {
    909         return;
    910     }
    911 
    912     if (mx) {
    913         mx->fTop = -fScale * otm.otmTextMetrics.tmAscent;
    914         mx->fAscent = -fScale * otm.otmAscent;
    915         mx->fDescent = -fScale * otm.otmDescent;
    916         mx->fBottom = fScale * otm.otmTextMetrics.tmDescent;
    917         mx->fLeading = fScale * (otm.otmTextMetrics.tmInternalLeading
    918                                  + otm.otmTextMetrics.tmExternalLeading);
    919     }
    920 
    921     if (my) {
    922         my->fTop = -fScale * otm.otmTextMetrics.tmAscent;
    923         my->fAscent = -fScale * otm.otmAscent;
    924         my->fDescent = -fScale * otm.otmDescent;
    925         my->fBottom = fScale * otm.otmTextMetrics.tmDescent;
    926         my->fLeading = fScale * (otm.otmTextMetrics.tmInternalLeading
    927                                  + otm.otmTextMetrics.tmExternalLeading);
    928     }
    929 }
    930 
    931 ////////////////////////////////////////////////////////////////////////////////////////
    932 
    933 static void build_power_table(uint8_t table[], float ee) {
    934     for (int i = 0; i < 256; i++) {
    935         float x = i / 255.f;
    936         x = sk_float_pow(x, ee);
    937         int xx = SkScalarRound(SkFloatToScalar(x * 255));
    938         table[i] = SkToU8(xx);
    939     }
    940 }
    941 
    942 /**
    943  *  This will invert the gamma applied by GDI (gray-scale antialiased), so we
    944  *  can get linear values.
    945  *
    946  *  GDI grayscale appears to use a hard-coded gamma of 2.3.
    947  *
    948  *  GDI grayscale appears to draw using the black and white rasterizer at four
    949  *  times the size and then downsamples to compute the coverage mask. As a
    950  *  result there are only seventeen total grays. This lack of fidelity means
    951  *  that shifting into other color spaces is imprecise.
    952  */
    953 static const uint8_t* getInverseGammaTableGDI() {
    954     static bool gInited;
    955     static uint8_t gTableGdi[256];
    956     if (!gInited) {
    957         build_power_table(gTableGdi, 2.3f);
    958         gInited = true;
    959     }
    960     return gTableGdi;
    961 }
    962 
    963 /**
    964  *  This will invert the gamma applied by GDI ClearType, so we can get linear
    965  *  values.
    966  *
    967  *  GDI ClearType uses SPI_GETFONTSMOOTHINGCONTRAST / 1000 as the gamma value.
    968  *  If this value is not specified, the default is a gamma of 1.4.
    969  */
    970 static const uint8_t* getInverseGammaTableClearType() {
    971     static bool gInited;
    972     static uint8_t gTableClearType[256];
    973     if (!gInited) {
    974         UINT level = 0;
    975         if (!SystemParametersInfo(SPI_GETFONTSMOOTHINGCONTRAST, 0, &level, 0) || !level) {
    976             // can't get the data, so use a default
    977             level = 1400;
    978         }
    979         build_power_table(gTableClearType, level / 1000.0f);
    980         gInited = true;
    981     }
    982     return gTableClearType;
    983 }
    984 
    985 #include "SkColorPriv.h"
    986 
    987 //Cannot assume that the input rgb is gray due to possible setting of kGenA8FromLCD_Flag.
    988 template<bool APPLY_PREBLEND>
    989 static inline uint8_t rgb_to_a8(SkGdiRGB rgb, const uint8_t* table8) {
    990     U8CPU r = (rgb >> 16) & 0xFF;
    991     U8CPU g = (rgb >>  8) & 0xFF;
    992     U8CPU b = (rgb >>  0) & 0xFF;
    993     return sk_apply_lut_if<APPLY_PREBLEND>(SkComputeLuminance(r, g, b), table8);
    994 }
    995 
    996 template<bool APPLY_PREBLEND>
    997 static inline uint16_t rgb_to_lcd16(SkGdiRGB rgb, const uint8_t* tableR,
    998                                                   const uint8_t* tableG,
    999                                                   const uint8_t* tableB) {
   1000     U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 16) & 0xFF, tableR);
   1001     U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>((rgb >>  8) & 0xFF, tableG);
   1002     U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>((rgb >>  0) & 0xFF, tableB);
   1003     return SkPack888ToRGB16(r, g, b);
   1004 }
   1005 
   1006 template<bool APPLY_PREBLEND>
   1007 static inline SkPMColor rgb_to_lcd32(SkGdiRGB rgb, const uint8_t* tableR,
   1008                                                    const uint8_t* tableG,
   1009                                                    const uint8_t* tableB) {
   1010     U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 16) & 0xFF, tableR);
   1011     U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>((rgb >>  8) & 0xFF, tableG);
   1012     U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>((rgb >>  0) & 0xFF, tableB);
   1013     return SkPackARGB32(0xFF, r, g, b);
   1014 }
   1015 
   1016 // Is this GDI color neither black nor white? If so, we have to keep this
   1017 // image as is, rather than smashing it down to a BW mask.
   1018 //
   1019 // returns int instead of bool, since we don't want/have to pay to convert
   1020 // the zero/non-zero value into a bool
   1021 static int is_not_black_or_white(SkGdiRGB c) {
   1022     // same as (but faster than)
   1023     //      c &= 0x00FFFFFF;
   1024     //      return 0 == c || 0x00FFFFFF == c;
   1025     return (c + (c & 1)) & 0x00FFFFFF;
   1026 }
   1027 
   1028 static bool is_rgb_really_bw(const SkGdiRGB* src, int width, int height, int srcRB) {
   1029     for (int y = 0; y < height; ++y) {
   1030         for (int x = 0; x < width; ++x) {
   1031             if (is_not_black_or_white(src[x])) {
   1032                 return false;
   1033             }
   1034         }
   1035         src = SkTAddByteOffset(src, srcRB);
   1036     }
   1037     return true;
   1038 }
   1039 
   1040 // gdi's bitmap is upside-down, so we reverse dst walking in Y
   1041 // whenever we copy it into skia's buffer
   1042 static void rgb_to_bw(const SkGdiRGB* SK_RESTRICT src, size_t srcRB,
   1043                       const SkGlyph& glyph) {
   1044     const int width = glyph.fWidth;
   1045     const size_t dstRB = (width + 7) >> 3;
   1046     uint8_t* SK_RESTRICT dst = (uint8_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB);
   1047 
   1048     int byteCount = width >> 3;
   1049     int bitCount = width & 7;
   1050 
   1051     // adjust srcRB to skip the values in our byteCount loop,
   1052     // since we increment src locally there
   1053     srcRB -= byteCount * 8 * sizeof(SkGdiRGB);
   1054 
   1055     for (int y = 0; y < glyph.fHeight; ++y) {
   1056         if (byteCount > 0) {
   1057             for (int i = 0; i < byteCount; ++i) {
   1058                 unsigned byte = 0;
   1059                 byte |= src[0] & (1 << 7);
   1060                 byte |= src[1] & (1 << 6);
   1061                 byte |= src[2] & (1 << 5);
   1062                 byte |= src[3] & (1 << 4);
   1063                 byte |= src[4] & (1 << 3);
   1064                 byte |= src[5] & (1 << 2);
   1065                 byte |= src[6] & (1 << 1);
   1066                 byte |= src[7] & (1 << 0);
   1067                 dst[i] = byte;
   1068                 src += 8;
   1069             }
   1070         }
   1071         if (bitCount > 0) {
   1072             unsigned byte = 0;
   1073             unsigned mask = 0x80;
   1074             for (int i = 0; i < bitCount; i++) {
   1075                 byte |= src[i] & mask;
   1076                 mask >>= 1;
   1077             }
   1078             dst[byteCount] = byte;
   1079         }
   1080         src = SkTAddByteOffset(src, srcRB);
   1081         dst -= dstRB;
   1082     }
   1083 }
   1084 
   1085 template<bool APPLY_PREBLEND>
   1086 static void rgb_to_a8(const SkGdiRGB* SK_RESTRICT src, size_t srcRB,
   1087                       const SkGlyph& glyph, const uint8_t* table8) {
   1088     const size_t dstRB = glyph.rowBytes();
   1089     const int width = glyph.fWidth;
   1090     uint8_t* SK_RESTRICT dst = (uint8_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB);
   1091 
   1092     for (int y = 0; y < glyph.fHeight; y++) {
   1093         for (int i = 0; i < width; i++) {
   1094             dst[i] = rgb_to_a8<APPLY_PREBLEND>(src[i], table8);
   1095         }
   1096         src = SkTAddByteOffset(src, srcRB);
   1097         dst -= dstRB;
   1098     }
   1099 }
   1100 
   1101 template<bool APPLY_PREBLEND>
   1102 static void rgb_to_lcd16(const SkGdiRGB* SK_RESTRICT src, size_t srcRB, const SkGlyph& glyph,
   1103                          const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
   1104     const size_t dstRB = glyph.rowBytes();
   1105     const int width = glyph.fWidth;
   1106     uint16_t* SK_RESTRICT dst = (uint16_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB);
   1107 
   1108     for (int y = 0; y < glyph.fHeight; y++) {
   1109         for (int i = 0; i < width; i++) {
   1110             dst[i] = rgb_to_lcd16<APPLY_PREBLEND>(src[i], tableR, tableG, tableB);
   1111         }
   1112         src = SkTAddByteOffset(src, srcRB);
   1113         dst = (uint16_t*)((char*)dst - dstRB);
   1114     }
   1115 }
   1116 
   1117 template<bool APPLY_PREBLEND>
   1118 static void rgb_to_lcd32(const SkGdiRGB* SK_RESTRICT src, size_t srcRB, const SkGlyph& glyph,
   1119                          const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
   1120     const size_t dstRB = glyph.rowBytes();
   1121     const int width = glyph.fWidth;
   1122     uint32_t* SK_RESTRICT dst = (uint32_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB);
   1123 
   1124     for (int y = 0; y < glyph.fHeight; y++) {
   1125         for (int i = 0; i < width; i++) {
   1126             dst[i] = rgb_to_lcd32<APPLY_PREBLEND>(src[i], tableR, tableG, tableB);
   1127         }
   1128         src = SkTAddByteOffset(src, srcRB);
   1129         dst = (uint32_t*)((char*)dst - dstRB);
   1130     }
   1131 }
   1132 
   1133 static inline unsigned clamp255(unsigned x) {
   1134     SkASSERT(x <= 256);
   1135     return x - (x >> 8);
   1136 }
   1137 
   1138 void SkScalerContext_Windows::generateImage(const SkGlyph& glyph) {
   1139     SkAutoMutexAcquire ac(gFTMutex);
   1140     SkASSERT(fDDC);
   1141 
   1142     const bool isBW = SkMask::kBW_Format == fRec.fMaskFormat;
   1143     const bool isAA = !isLCD(fRec);
   1144 
   1145     size_t srcRB;
   1146     const void* bits = fOffscreen.draw(glyph, isBW, &srcRB);
   1147     if (NULL == bits) {
   1148         ensure_typeface_accessible(fRec.fFontID);
   1149         bits = fOffscreen.draw(glyph, isBW, &srcRB);
   1150         if (NULL == bits) {
   1151             sk_bzero(glyph.fImage, glyph.computeImageSize());
   1152             return;
   1153         }
   1154     }
   1155 
   1156     if (!isBW) {
   1157         const uint8_t* table;
   1158         //The offscreen contains a GDI blit if isAA and kGenA8FromLCD_Flag is not set.
   1159         //Otherwise the offscreen contains a ClearType blit.
   1160         if (isAA && !(fRec.fFlags & SkScalerContext::kGenA8FromLCD_Flag)) {
   1161             table = getInverseGammaTableGDI();
   1162         } else {
   1163             table = getInverseGammaTableClearType();
   1164         }
   1165         //Note that the following cannot really be integrated into the
   1166         //pre-blend, since we may not be applying the pre-blend; when we aren't
   1167         //applying the pre-blend it means that a filter wants linear anyway.
   1168         //Other code may also be applying the pre-blend, so we'd need another
   1169         //one with this and one without.
   1170         SkGdiRGB* addr = (SkGdiRGB*)bits;
   1171         for (int y = 0; y < glyph.fHeight; ++y) {
   1172             for (int x = 0; x < glyph.fWidth; ++x) {
   1173                 int r = (addr[x] >> 16) & 0xFF;
   1174                 int g = (addr[x] >>  8) & 0xFF;
   1175                 int b = (addr[x] >>  0) & 0xFF;
   1176                 addr[x] = (table[r] << 16) | (table[g] << 8) | table[b];
   1177             }
   1178             addr = SkTAddByteOffset(addr, srcRB);
   1179         }
   1180     }
   1181 
   1182     int width = glyph.fWidth;
   1183     size_t dstRB = glyph.rowBytes();
   1184     if (isBW) {
   1185         const uint8_t* src = (const uint8_t*)bits;
   1186         uint8_t* dst = (uint8_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB);
   1187         for (int y = 0; y < glyph.fHeight; y++) {
   1188             memcpy(dst, src, dstRB);
   1189             src += srcRB;
   1190             dst -= dstRB;
   1191         }
   1192     } else if (isAA) {
   1193         // since the caller may require A8 for maskfilters, we can't check for BW
   1194         // ... until we have the caller tell us that explicitly
   1195         const SkGdiRGB* src = (const SkGdiRGB*)bits;
   1196         if (fPreBlend.isApplicable()) {
   1197             rgb_to_a8<true>(src, srcRB, glyph, fPreBlend.fG);
   1198         } else {
   1199             rgb_to_a8<false>(src, srcRB, glyph, fPreBlend.fG);
   1200         }
   1201     } else {    // LCD16
   1202         const SkGdiRGB* src = (const SkGdiRGB*)bits;
   1203         if (is_rgb_really_bw(src, width, glyph.fHeight, srcRB)) {
   1204             rgb_to_bw(src, srcRB, glyph);
   1205             ((SkGlyph*)&glyph)->fMaskFormat = SkMask::kBW_Format;
   1206         } else {
   1207             if (SkMask::kLCD16_Format == glyph.fMaskFormat) {
   1208                 if (fPreBlend.isApplicable()) {
   1209                     rgb_to_lcd16<true>(src, srcRB, glyph,
   1210                                        fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
   1211                 } else {
   1212                     rgb_to_lcd16<false>(src, srcRB, glyph,
   1213                                         fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
   1214                 }
   1215             } else {
   1216                 SkASSERT(SkMask::kLCD32_Format == glyph.fMaskFormat);
   1217                 if (fPreBlend.isApplicable()) {
   1218                     rgb_to_lcd32<true>(src, srcRB, glyph,
   1219                                        fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
   1220                 } else {
   1221                     rgb_to_lcd32<false>(src, srcRB, glyph,
   1222                                         fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
   1223                 }
   1224             }
   1225         }
   1226     }
   1227 }
   1228 
   1229 void SkScalerContext_Windows::generatePath(const SkGlyph& glyph, SkPath* path) {
   1230 
   1231     SkAutoMutexAcquire  ac(gFTMutex);
   1232 
   1233     SkASSERT(&glyph && path);
   1234     SkASSERT(fDDC);
   1235 
   1236     path->reset();
   1237 
   1238 #if 0
   1239     char buf[1024];
   1240     sprintf(buf, "generatePath: id:%d, w=%d, h=%d, font:%s,fh:%d\n", glyph.fID, glyph.fWidth, glyph.fHeight, lf.lfFaceName, lf.lfHeight);
   1241     OutputDebugString(buf);
   1242 #endif
   1243 
   1244     GLYPHMETRICS gm;
   1245     uint32_t total_size = GetGlyphOutlineW(fDDC, glyph.fID, GGO_NATIVE | GGO_GLYPH_INDEX, &gm, BUFFERSIZE, glyphbuf, &fMat22);
   1246     if (GDI_ERROR == total_size) {
   1247         ensure_typeface_accessible(fRec.fFontID);
   1248         total_size = GetGlyphOutlineW(fDDC, glyph.fID, GGO_NATIVE | GGO_GLYPH_INDEX, &gm, BUFFERSIZE, glyphbuf, &fMat22);
   1249     }
   1250 
   1251     if (GDI_ERROR != total_size) {
   1252 
   1253         const uint8_t* cur_glyph = glyphbuf;
   1254         const uint8_t* end_glyph = glyphbuf + total_size;
   1255 
   1256         while(cur_glyph < end_glyph) {
   1257             const TTPOLYGONHEADER* th = (TTPOLYGONHEADER*)cur_glyph;
   1258 
   1259             const uint8_t* end_poly = cur_glyph + th->cb;
   1260             const uint8_t* cur_poly = cur_glyph + sizeof(TTPOLYGONHEADER);
   1261 
   1262             path->moveTo(SkFixedToScalar(*(SkFixed*)(&th->pfxStart.x)), SkFixedToScalar(*(SkFixed*)(&th->pfxStart.y)));
   1263 
   1264             while(cur_poly < end_poly) {
   1265                 const TTPOLYCURVE* pc = (const TTPOLYCURVE*)cur_poly;
   1266 
   1267                 if (pc->wType == TT_PRIM_LINE) {
   1268                     for (uint16_t i = 0; i < pc->cpfx; i++) {
   1269                         path->lineTo(SkFixedToScalar(*(SkFixed*)(&pc->apfx[i].x)), SkFixedToScalar(*(SkFixed*)(&pc->apfx[i].y)));
   1270                     }
   1271                 }
   1272 
   1273                 if (pc->wType == TT_PRIM_QSPLINE) {
   1274                     for (uint16_t u = 0; u < pc->cpfx - 1; u++) { // Walk through points in spline
   1275                         POINTFX pnt_b = pc->apfx[u];    // B is always the current point
   1276                         POINTFX pnt_c = pc->apfx[u+1];
   1277 
   1278                         if (u < pc->cpfx - 2) {          // If not on last spline, compute C
   1279                             pnt_c.x = SkFixedToFIXED(SkFixedAve(*(SkFixed*)(&pnt_b.x), *(SkFixed*)(&pnt_c.x)));
   1280                             pnt_c.y = SkFixedToFIXED(SkFixedAve(*(SkFixed*)(&pnt_b.y), *(SkFixed*)(&pnt_c.y)));
   1281                         }
   1282 
   1283                         path->quadTo(SkFixedToScalar(*(SkFixed*)(&pnt_b.x)), SkFixedToScalar(*(SkFixed*)(&pnt_b.y)), SkFixedToScalar(*(SkFixed*)(&pnt_c.x)), SkFixedToScalar(*(SkFixed*)(&pnt_c.y)));
   1284                     }
   1285                 }
   1286                 cur_poly += sizeof(uint16_t) * 2 + sizeof(POINTFX) * pc->cpfx;
   1287             }
   1288             cur_glyph += th->cb;
   1289             path->close();
   1290         }
   1291     }
   1292     else {
   1293         SkASSERT(false);
   1294     }
   1295     //char buf[1024];
   1296     //sprintf(buf, "generatePath: count:%d\n", count);
   1297     //OutputDebugString(buf);
   1298 }
   1299 
   1300 static void logfont_for_name(const char* familyName, LOGFONT& lf) {
   1301         memset(&lf, 0, sizeof(LOGFONT));
   1302 #ifdef UNICODE
   1303         // Get the buffer size needed first.
   1304         size_t str_len = ::MultiByteToWideChar(CP_UTF8, 0, familyName,
   1305                                                 -1, NULL, 0);
   1306         // Allocate a buffer (str_len already has terminating null
   1307         // accounted for).
   1308         wchar_t *wideFamilyName = new wchar_t[str_len];
   1309         // Now actually convert the string.
   1310         ::MultiByteToWideChar(CP_UTF8, 0, familyName, -1,
   1311                                 wideFamilyName, str_len);
   1312         ::wcsncpy(lf.lfFaceName, wideFamilyName, LF_FACESIZE - 1);
   1313         delete [] wideFamilyName;
   1314         lf.lfFaceName[LF_FACESIZE-1] = L'\0';
   1315 #else
   1316         ::strncpy(lf.lfFaceName, familyName, LF_FACESIZE - 1);
   1317         lf.lfFaceName[LF_FACESIZE - 1] = '\0';
   1318 #endif
   1319 }
   1320 
   1321 static void tchar_to_skstring(const TCHAR* t, SkString* s) {
   1322 #ifdef UNICODE
   1323     size_t sSize = WideCharToMultiByte(CP_UTF8, 0, t, -1, NULL, 0, NULL, NULL);
   1324     s->resize(sSize);
   1325     WideCharToMultiByte(CP_UTF8, 0, t, -1, s->writable_str(), sSize, NULL, NULL);
   1326 #else
   1327     s->set(t);
   1328 #endif
   1329 }
   1330 
   1331 void SkFontHost::Serialize(const SkTypeface* rawFace, SkWStream* stream) {
   1332     const LogFontTypeface* face = static_cast<const LogFontTypeface*>(rawFace);
   1333     SkFontDescriptor descriptor(face->style());
   1334 
   1335     // Get the actual name of the typeface. The logfont may not know this.
   1336     HFONT font = CreateFontIndirect(&face->fLogFont);
   1337 
   1338     HDC deviceContext = ::CreateCompatibleDC(NULL);
   1339     HFONT savefont = (HFONT)SelectObject(deviceContext, font);
   1340 
   1341     int fontNameLen; //length of fontName in TCHARS.
   1342     if (0 == (fontNameLen = GetTextFace(deviceContext, 0, NULL))) {
   1343         SkFontHost::EnsureTypefaceAccessible(*rawFace);
   1344         if (0 == (fontNameLen = GetTextFace(deviceContext, 0, NULL))) {
   1345             fontNameLen = 0;
   1346         }
   1347     }
   1348 
   1349     SkAutoSTArray<LF_FULLFACESIZE, TCHAR> fontName(fontNameLen+1);
   1350     if (0 == GetTextFace(deviceContext, fontNameLen, fontName.get())) {
   1351         SkFontHost::EnsureTypefaceAccessible(*rawFace);
   1352         if (0 == GetTextFace(deviceContext, fontNameLen, fontName.get())) {
   1353             fontName[0] = 0;
   1354         }
   1355     }
   1356 
   1357     if (deviceContext) {
   1358         ::SelectObject(deviceContext, savefont);
   1359         ::DeleteDC(deviceContext);
   1360     }
   1361     if (font) {
   1362         ::DeleteObject(font);
   1363     }
   1364 
   1365     SkString familyName;
   1366     tchar_to_skstring(fontName.get(), &familyName);
   1367     descriptor.setFamilyName(familyName.c_str());
   1368     //TODO: FileName and PostScriptName currently unsupported.
   1369 
   1370     descriptor.serialize(stream);
   1371 
   1372     if (face->fSerializeAsStream) {
   1373         // store the entire font in the fontData
   1374         SkAutoTUnref<SkStream> fontStream(SkFontHost::OpenStream(face->uniqueID()));
   1375         const uint32_t length = fontStream->getLength();
   1376 
   1377         stream->writePackedUInt(length);
   1378         stream->writeStream(fontStream, length);
   1379     } else {
   1380         stream->writePackedUInt(0);
   1381     }
   1382 }
   1383 
   1384 SkTypeface* SkFontHost::Deserialize(SkStream* stream) {
   1385     SkFontDescriptor descriptor(stream);
   1386 
   1387     const uint32_t customFontDataLength = stream->readPackedUInt();
   1388     if (customFontDataLength > 0) {
   1389         // generate a new stream to store the custom typeface
   1390         SkAutoTUnref<SkMemoryStream> fontStream(SkNEW_ARGS(SkMemoryStream, (customFontDataLength - 1)));
   1391         stream->read((void*)fontStream->getMemoryBase(), customFontDataLength - 1);
   1392 
   1393         return CreateTypefaceFromStream(fontStream.get());
   1394     }
   1395 
   1396     return SkFontHost::CreateTypeface(NULL, descriptor.getFamilyName(), descriptor.getStyle());
   1397 }
   1398 
   1399 static bool getWidthAdvance(HDC hdc, int gId, int16_t* advance) {
   1400     // Initialize the MAT2 structure to the identify transformation matrix.
   1401     static const MAT2 mat2 = {SkScalarToFIXED(1), SkScalarToFIXED(0),
   1402                         SkScalarToFIXED(0), SkScalarToFIXED(1)};
   1403     int flags = GGO_METRICS | GGO_GLYPH_INDEX;
   1404     GLYPHMETRICS gm;
   1405     if (GDI_ERROR == GetGlyphOutline(hdc, gId, flags, &gm, 0, NULL, &mat2)) {
   1406         return false;
   1407     }
   1408     SkASSERT(advance);
   1409     *advance = gm.gmCellIncX;
   1410     return true;
   1411 }
   1412 
   1413 // static
   1414 SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
   1415         uint32_t fontID,
   1416         SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo,
   1417         const uint32_t* glyphIDs,
   1418         uint32_t glyphIDsCount) {
   1419     LOGFONT lf;
   1420     GetLogFontByID(fontID, &lf);
   1421     SkAdvancedTypefaceMetrics* info = NULL;
   1422 
   1423     HDC hdc = CreateCompatibleDC(NULL);
   1424     HFONT font = CreateFontIndirect(&lf);
   1425     HFONT savefont = (HFONT)SelectObject(hdc, font);
   1426     HFONT designFont = NULL;
   1427 
   1428     const char stem_chars[] = {'i', 'I', '!', '1'};
   1429     int16_t min_width;
   1430     unsigned glyphCount;
   1431 
   1432     // To request design units, create a logical font whose height is specified
   1433     // as unitsPerEm.
   1434     OUTLINETEXTMETRIC otm;
   1435     unsigned int otmRet = GetOutlineTextMetrics(hdc, sizeof(otm), &otm);
   1436     if (0 == otmRet) {
   1437         ensure_typeface_accessible(fontID);
   1438         otmRet = GetOutlineTextMetrics(hdc, sizeof(otm), &otm);
   1439     }
   1440     if (!otmRet || !GetTextFace(hdc, LF_FACESIZE, lf.lfFaceName)) {
   1441         goto Error;
   1442     }
   1443     lf.lfHeight = -SkToS32(otm.otmEMSquare);
   1444     designFont = CreateFontIndirect(&lf);
   1445     SelectObject(hdc, designFont);
   1446     if (!GetOutlineTextMetrics(hdc, sizeof(otm), &otm)) {
   1447         goto Error;
   1448     }
   1449     glyphCount = calculateOutlineGlyphCount(hdc);
   1450 
   1451     info = new SkAdvancedTypefaceMetrics;
   1452     info->fEmSize = otm.otmEMSquare;
   1453     info->fMultiMaster = false;
   1454     info->fLastGlyphID = SkToU16(glyphCount - 1);
   1455     info->fStyle = 0;
   1456     tchar_to_skstring(lf.lfFaceName, &info->fFontName);
   1457 
   1458     if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo) {
   1459         populate_glyph_to_unicode(hdc, glyphCount, &(info->fGlyphToUnicode));
   1460     }
   1461 
   1462     if (glyphCount > 0 &&
   1463         (otm.otmTextMetrics.tmPitchAndFamily & TMPF_TRUETYPE)) {
   1464         info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font;
   1465     } else {
   1466         info->fType = SkAdvancedTypefaceMetrics::kOther_Font;
   1467         info->fItalicAngle = 0;
   1468         info->fAscent = 0;
   1469         info->fDescent = 0;
   1470         info->fStemV = 0;
   1471         info->fCapHeight = 0;
   1472         info->fBBox = SkIRect::MakeEmpty();
   1473         return info;
   1474     }
   1475 
   1476     // If this bit is clear the font is a fixed pitch font.
   1477     if (!(otm.otmTextMetrics.tmPitchAndFamily & TMPF_FIXED_PITCH)) {
   1478         info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;
   1479     }
   1480     if (otm.otmTextMetrics.tmItalic) {
   1481         info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style;
   1482     }
   1483     // Setting symbolic style by default for now.
   1484     info->fStyle |= SkAdvancedTypefaceMetrics::kSymbolic_Style;
   1485     if (otm.otmTextMetrics.tmPitchAndFamily & FF_ROMAN) {
   1486         info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;
   1487     } else if (otm.otmTextMetrics.tmPitchAndFamily & FF_SCRIPT) {
   1488             info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;
   1489     }
   1490 
   1491     // The main italic angle of the font, in tenths of a degree counterclockwise
   1492     // from vertical.
   1493     info->fItalicAngle = otm.otmItalicAngle / 10;
   1494     info->fAscent = SkToS16(otm.otmTextMetrics.tmAscent);
   1495     info->fDescent = SkToS16(-otm.otmTextMetrics.tmDescent);
   1496     // TODO(ctguil): Use alternate cap height calculation.
   1497     // MSDN says otmsCapEmHeight is not support but it is returning a value on
   1498     // my Win7 box.
   1499     info->fCapHeight = otm.otmsCapEmHeight;
   1500     info->fBBox =
   1501         SkIRect::MakeLTRB(otm.otmrcFontBox.left, otm.otmrcFontBox.top,
   1502                           otm.otmrcFontBox.right, otm.otmrcFontBox.bottom);
   1503 
   1504     // Figure out a good guess for StemV - Min width of i, I, !, 1.
   1505     // This probably isn't very good with an italic font.
   1506     min_width = SHRT_MAX;
   1507     info->fStemV = 0;
   1508     for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) {
   1509         ABC abcWidths;
   1510         if (GetCharABCWidths(hdc, stem_chars[i], stem_chars[i], &abcWidths)) {
   1511             int16_t width = abcWidths.abcB;
   1512             if (width > 0 && width < min_width) {
   1513                 min_width = width;
   1514                 info->fStemV = min_width;
   1515             }
   1516         }
   1517     }
   1518 
   1519     // If bit 1 is set, the font may not be embedded in a document.
   1520     // If bit 1 is clear, the font can be embedded.
   1521     // If bit 2 is set, the embedding is read-only.
   1522     if (otm.otmfsType & 0x1) {
   1523         info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font;
   1524     } else if (perGlyphInfo &
   1525                SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo) {
   1526         if (info->fStyle & SkAdvancedTypefaceMetrics::kFixedPitch_Style) {
   1527             appendRange(&info->fGlyphWidths, 0);
   1528             info->fGlyphWidths->fAdvance.append(1, &min_width);
   1529             finishRange(info->fGlyphWidths.get(), 0,
   1530                         SkAdvancedTypefaceMetrics::WidthRange::kDefault);
   1531         } else {
   1532             info->fGlyphWidths.reset(
   1533                 getAdvanceData(hdc,
   1534                                glyphCount,
   1535                                glyphIDs,
   1536                                glyphIDsCount,
   1537                                &getWidthAdvance));
   1538         }
   1539     }
   1540 
   1541 Error:
   1542     SelectObject(hdc, savefont);
   1543     DeleteObject(designFont);
   1544     DeleteObject(font);
   1545     DeleteDC(hdc);
   1546 
   1547     return info;
   1548 }
   1549 
   1550 //Dummy representation of a Base64 encoded GUID from create_unique_font_name.
   1551 #define BASE64_GUID_ID "XXXXXXXXXXXXXXXXXXXXXXXX"
   1552 //Length of GUID representation from create_id, including NULL terminator.
   1553 #define BASE64_GUID_ID_LEN SK_ARRAY_COUNT(BASE64_GUID_ID)
   1554 
   1555 SK_COMPILE_ASSERT(BASE64_GUID_ID_LEN < LF_FACESIZE, GUID_longer_than_facesize);
   1556 
   1557 /**
   1558    NameID 6 Postscript names cannot have the character '/'.
   1559    It would be easier to hex encode the GUID, but that is 32 bytes,
   1560    and many systems have issues with names longer than 28 bytes.
   1561    The following need not be any standard base64 encoding.
   1562    The encoded value is never decoded.
   1563 */
   1564 static const char postscript_safe_base64_encode[] =
   1565     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
   1566     "abcdefghijklmnopqrstuvwxyz"
   1567     "0123456789-_=";
   1568 
   1569 /**
   1570    Formats a GUID into Base64 and places it into buffer.
   1571    buffer should have space for at least BASE64_GUID_ID_LEN characters.
   1572    The string will always be null terminated.
   1573    XXXXXXXXXXXXXXXXXXXXXXXX0
   1574  */
   1575 static void format_guid_b64(const GUID& guid, char* buffer, size_t bufferSize) {
   1576     SkASSERT(bufferSize >= BASE64_GUID_ID_LEN);
   1577     size_t written = SkBase64::Encode(&guid, sizeof(guid), buffer, postscript_safe_base64_encode);
   1578     SkASSERT(written < LF_FACESIZE);
   1579     buffer[written] = '\0';
   1580 }
   1581 
   1582 /**
   1583    Creates a Base64 encoded GUID and places it into buffer.
   1584    buffer should have space for at least BASE64_GUID_ID_LEN characters.
   1585    The string will always be null terminated.
   1586    XXXXXXXXXXXXXXXXXXXXXXXX0
   1587  */
   1588 static HRESULT create_unique_font_name(char* buffer, size_t bufferSize) {
   1589     GUID guid = {};
   1590     if (FAILED(CoCreateGuid(&guid))) {
   1591         return E_UNEXPECTED;
   1592     }
   1593     format_guid_b64(guid, buffer, bufferSize);
   1594 
   1595     return S_OK;
   1596 }
   1597 
   1598 /**
   1599    Introduces a font to GDI. On failure will return NULL. The returned handle
   1600    should eventually be passed to RemoveFontMemResourceEx.
   1601 */
   1602 static HANDLE activate_font(SkData* fontData) {
   1603     DWORD numFonts = 0;
   1604     //AddFontMemResourceEx just copies the data, but does not specify const.
   1605     HANDLE fontHandle = AddFontMemResourceEx(const_cast<void*>(fontData->data()),
   1606                                              fontData->size(),
   1607                                              0,
   1608                                              &numFonts);
   1609 
   1610     if (fontHandle != NULL && numFonts < 1) {
   1611         RemoveFontMemResourceEx(fontHandle);
   1612         return NULL;
   1613     }
   1614 
   1615     return fontHandle;
   1616 }
   1617 
   1618 SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
   1619     // Create a unique and unpredictable font name.
   1620     // Avoids collisions and access from CSS.
   1621     char familyName[BASE64_GUID_ID_LEN];
   1622     const int familyNameSize = SK_ARRAY_COUNT(familyName);
   1623     if (FAILED(create_unique_font_name(familyName, familyNameSize))) {
   1624         return NULL;
   1625     }
   1626 
   1627     // Change the name of the font.
   1628     SkAutoTUnref<SkData> rewrittenFontData(SkOTUtils::RenameFont(stream, familyName, familyNameSize-1));
   1629     if (NULL == rewrittenFontData.get()) {
   1630         return NULL;
   1631     }
   1632 
   1633     // Register the font with GDI.
   1634     HANDLE fontReference = activate_font(rewrittenFontData.get());
   1635     if (NULL == fontReference) {
   1636         return NULL;
   1637     }
   1638 
   1639     // Create the typeface.
   1640     LOGFONT lf;
   1641     logfont_for_name(familyName, lf);
   1642 
   1643     return SkCreateFontMemResourceTypefaceFromLOGFONT(lf, fontReference);
   1644 }
   1645 
   1646 SkStream* SkFontHost::OpenStream(SkFontID uniqueID) {
   1647     const DWORD kTTCTag =
   1648         SkEndian_SwapBE32(SkSetFourByteTag('t', 't', 'c', 'f'));
   1649     LOGFONT lf;
   1650     GetLogFontByID(uniqueID, &lf);
   1651 
   1652     HDC hdc = ::CreateCompatibleDC(NULL);
   1653     HFONT font = CreateFontIndirect(&lf);
   1654     HFONT savefont = (HFONT)SelectObject(hdc, font);
   1655 
   1656     SkMemoryStream* stream = NULL;
   1657     DWORD tables[2] = {kTTCTag, 0};
   1658     for (int i = 0; i < SK_ARRAY_COUNT(tables); i++) {
   1659         size_t bufferSize = GetFontData(hdc, tables[i], 0, NULL, 0);
   1660         if (bufferSize == GDI_ERROR) {
   1661             ensure_typeface_accessible(uniqueID);
   1662             bufferSize = GetFontData(hdc, tables[i], 0, NULL, 0);
   1663         }
   1664         if (bufferSize != GDI_ERROR) {
   1665             stream = new SkMemoryStream(bufferSize);
   1666             if (GetFontData(hdc, tables[i], 0, (void*)stream->getMemoryBase(),
   1667                             bufferSize)) {
   1668                 break;
   1669             } else {
   1670                 delete stream;
   1671                 stream = NULL;
   1672             }
   1673         }
   1674     }
   1675 
   1676     SelectObject(hdc, savefont);
   1677     DeleteObject(font);
   1678     DeleteDC(hdc);
   1679 
   1680     return stream;
   1681 }
   1682 
   1683 SkScalerContext* SkFontHost::CreateScalerContext(const SkDescriptor* desc) {
   1684     return SkNEW_ARGS(SkScalerContext_Windows, (desc));
   1685 }
   1686 
   1687 /** Return the closest matching typeface given either an existing family
   1688  (specified by a typeface in that family) or by a familyName, and a
   1689  requested style.
   1690  1) If familyFace is null, use familyName.
   1691  2) If familyName is null, use familyFace.
   1692  3) If both are null, return the default font that best matches style
   1693  This MUST not return NULL.
   1694  */
   1695 
   1696 SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
   1697                                        const char familyName[],
   1698                                        SkTypeface::Style style) {
   1699     LOGFONT lf;
   1700     if (NULL == familyFace && NULL == familyName) {
   1701         lf = get_default_font();
   1702     } else if (familyFace) {
   1703         LogFontTypeface* face = (LogFontTypeface*)familyFace;
   1704         lf = face->fLogFont;
   1705     } else {
   1706         logfont_for_name(familyName, lf);
   1707     }
   1708     setStyle(&lf, style);
   1709     return SkCreateTypefaceFromLOGFONT(lf);
   1710 }
   1711 
   1712 SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
   1713     SkTypeface* face = NULL;
   1714     SkAutoTUnref<SkFILEStream> stream(SkNEW_ARGS(SkFILEStream, (path)));
   1715 
   1716     if (stream->isValid()) {
   1717         face = CreateTypefaceFromStream(stream);
   1718     }
   1719     return face;
   1720 }
   1721 
   1722 void SkFontHost::FilterRec(SkScalerContext::Rec* rec, SkTypeface* typeface) {
   1723     unsigned flagsWeDontSupport = SkScalerContext::kDevKernText_Flag |
   1724                                   SkScalerContext::kAutohinting_Flag |
   1725                                   SkScalerContext::kEmbeddedBitmapText_Flag |
   1726                                   SkScalerContext::kEmbolden_Flag |
   1727                                   SkScalerContext::kSubpixelPositioning_Flag |
   1728                                   SkScalerContext::kLCD_BGROrder_Flag |
   1729                                   SkScalerContext::kLCD_Vertical_Flag;
   1730     rec->fFlags &= ~flagsWeDontSupport;
   1731 
   1732     SkPaint::Hinting h = rec->getHinting();
   1733 
   1734     // I think we can support no-hinting, if we get hires outlines and just
   1735     // use skia to rasterize into a gray-scale mask...
   1736 #if 0
   1737     switch (h) {
   1738         case SkPaint::kNo_Hinting:
   1739         case SkPaint::kSlight_Hinting:
   1740             h = SkPaint::kNo_Hinting;
   1741             break;
   1742         case SkPaint::kNormal_Hinting:
   1743         case SkPaint::kFull_Hinting:
   1744             h = SkPaint::kNormal_Hinting;
   1745             break;
   1746         default:
   1747             SkDEBUGFAIL("unknown hinting");
   1748     }
   1749 #else
   1750     h = SkPaint::kNormal_Hinting;
   1751 #endif
   1752     rec->setHinting(h);
   1753 
   1754 // turn this off since GDI might turn A8 into BW! Need a bigger fix.
   1755 #if 0
   1756     // Disable LCD when rotated, since GDI's output is ugly
   1757     if (isLCD(*rec) && !isAxisAligned(*rec)) {
   1758         rec->fMaskFormat = SkMask::kA8_Format;
   1759     }
   1760 #endif
   1761 
   1762     LogFontTypeface* logfontTypeface = static_cast<LogFontTypeface*>(typeface);
   1763     if (!logfontTypeface->fCanBeLCD && isLCD(*rec)) {
   1764         rec->fMaskFormat = SkMask::kA8_Format;
   1765         rec->fFlags &= ~SkScalerContext::kGenA8FromLCD_Flag;
   1766     }
   1767 }
   1768