Home | History | Annotate | Download | only in ports
      1 /*
      2  * Copyright 2011 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkTypes.h"
      9 #if defined(SK_BUILD_FOR_WIN32)
     10 
     11 #undef GetGlyphIndices
     12 
     13 #include "SkDWrite.h"
     14 #include "SkDWriteGeometrySink.h"
     15 #include "SkEndian.h"
     16 #include "SkGlyph.h"
     17 #include "SkHRESULT.h"
     18 #include "SkMaskGamma.h"
     19 #include "SkMatrix22.h"
     20 #include "SkMutex.h"
     21 #include "SkOTTable_EBLC.h"
     22 #include "SkOTTable_EBSC.h"
     23 #include "SkOTTable_gasp.h"
     24 #include "SkOTTable_maxp.h"
     25 #include "SkPath.h"
     26 #include "SkScalerContext.h"
     27 #include "SkScalerContext_win_dw.h"
     28 #include "SkSharedMutex.h"
     29 #include "SkTScopedComPtr.h"
     30 #include "SkTypeface_win_dw.h"
     31 
     32 #include <dwrite.h>
     33 #if SK_HAS_DWRITE_1_H
     34 #  include <dwrite_1.h>
     35 #endif
     36 
     37 /* Note:
     38  * In versions 8 and 8.1 of Windows, some calls in DWrite are not thread safe.
     39  * The DWriteFactoryMutex protects the calls that are problematic.
     40  */
     41 static SkSharedMutex DWriteFactoryMutex;
     42 
     43 typedef SkAutoTExclusive<SkSharedMutex> Exclusive;
     44 typedef SkAutoSharedMutexShared Shared;
     45 
     46 static bool isLCD(const SkScalerContext::Rec& rec) {
     47     return SkMask::kLCD16_Format == rec.fMaskFormat;
     48 }
     49 
     50 static bool is_hinted_without_gasp(DWriteFontTypeface* typeface) {
     51     Exclusive l(DWriteFactoryMutex);
     52     AutoTDWriteTable<SkOTTableMaximumProfile> maxp(typeface->fDWriteFontFace.get());
     53     if (!maxp.fExists) {
     54         return false;
     55     }
     56     if (maxp.fSize < sizeof(SkOTTableMaximumProfile::Version::TT)) {
     57         return false;
     58     }
     59     if (maxp->version.version != SkOTTableMaximumProfile::Version::TT::VERSION) {
     60         return false;
     61     }
     62 
     63     if (0 == maxp->version.tt.maxSizeOfInstructions) {
     64         // No hints.
     65         return false;
     66     }
     67 
     68     AutoTDWriteTable<SkOTTableGridAndScanProcedure> gasp(typeface->fDWriteFontFace.get());
     69     return !gasp.fExists;
     70 }
     71 
     72 /** A PPEMRange is inclusive, [min, max]. */
     73 struct PPEMRange {
     74     int min;
     75     int max;
     76 };
     77 
     78 /** If the rendering mode for the specified 'size' is gridfit, then place
     79  *  the gridfit range into 'range'. Otherwise, leave 'range' alone.
     80  */
     81 static void expand_range_if_gridfit_only(DWriteFontTypeface* typeface, int size, PPEMRange* range) {
     82     AutoTDWriteTable<SkOTTableGridAndScanProcedure> gasp(typeface->fDWriteFontFace.get());
     83     if (!gasp.fExists) {
     84         return;
     85     }
     86     if (gasp.fSize < sizeof(SkOTTableGridAndScanProcedure)) {
     87         return;
     88     }
     89     if (gasp->version != SkOTTableGridAndScanProcedure::version0 &&
     90         gasp->version != SkOTTableGridAndScanProcedure::version1)
     91     {
     92         return;
     93     }
     94 
     95     uint16_t numRanges = SkEndianSwap16(gasp->numRanges);
     96     if (numRanges > 1024 ||
     97         gasp.fSize < sizeof(SkOTTableGridAndScanProcedure) +
     98                      sizeof(SkOTTableGridAndScanProcedure::GaspRange) * numRanges)
     99     {
    100         return;
    101     }
    102 
    103     const SkOTTableGridAndScanProcedure::GaspRange* rangeTable =
    104             SkTAfter<const SkOTTableGridAndScanProcedure::GaspRange>(gasp.get());
    105     int minPPEM = -1;
    106     for (uint16_t i = 0; i < numRanges; ++i, ++rangeTable) {
    107         int maxPPEM = SkEndianSwap16(rangeTable->maxPPEM);
    108         // Test that the size is in range and the range is gridfit only.
    109         if (minPPEM < size && size <= maxPPEM &&
    110             rangeTable->flags.raw.value == SkOTTableGridAndScanProcedure::GaspRange::behavior::Raw::GridfitMask)
    111         {
    112             range->min = minPPEM + 1;
    113             range->max = maxPPEM;
    114             return;
    115         }
    116         minPPEM = maxPPEM;
    117     }
    118 }
    119 
    120 static bool has_bitmap_strike(DWriteFontTypeface* typeface, PPEMRange range) {
    121     Exclusive l(DWriteFactoryMutex);
    122     {
    123         AutoTDWriteTable<SkOTTableEmbeddedBitmapLocation> eblc(typeface->fDWriteFontFace.get());
    124         if (!eblc.fExists) {
    125             return false;
    126         }
    127         if (eblc.fSize < sizeof(SkOTTableEmbeddedBitmapLocation)) {
    128             return false;
    129         }
    130         if (eblc->version != SkOTTableEmbeddedBitmapLocation::version_initial) {
    131             return false;
    132         }
    133 
    134         uint32_t numSizes = SkEndianSwap32(eblc->numSizes);
    135         if (numSizes > 1024 ||
    136             eblc.fSize < sizeof(SkOTTableEmbeddedBitmapLocation) +
    137                          sizeof(SkOTTableEmbeddedBitmapLocation::BitmapSizeTable) * numSizes)
    138         {
    139             return false;
    140         }
    141 
    142         const SkOTTableEmbeddedBitmapLocation::BitmapSizeTable* sizeTable =
    143                 SkTAfter<const SkOTTableEmbeddedBitmapLocation::BitmapSizeTable>(eblc.get());
    144         for (uint32_t i = 0; i < numSizes; ++i, ++sizeTable) {
    145             if (sizeTable->ppemX == sizeTable->ppemY &&
    146                 range.min <= sizeTable->ppemX && sizeTable->ppemX <= range.max)
    147             {
    148                 // TODO: determine if we should dig through IndexSubTableArray/IndexSubTable
    149                 // to determine the actual number of glyphs with bitmaps.
    150 
    151                 // TODO: Ensure that the bitmaps actually cover a significant portion of the strike.
    152 
    153                 // TODO: Ensure that the bitmaps are bi-level?
    154                 if (sizeTable->endGlyphIndex >= sizeTable->startGlyphIndex + 3) {
    155                     return true;
    156                 }
    157             }
    158         }
    159     }
    160 
    161     {
    162         AutoTDWriteTable<SkOTTableEmbeddedBitmapScaling> ebsc(typeface->fDWriteFontFace.get());
    163         if (!ebsc.fExists) {
    164             return false;
    165         }
    166         if (ebsc.fSize < sizeof(SkOTTableEmbeddedBitmapScaling)) {
    167             return false;
    168         }
    169         if (ebsc->version != SkOTTableEmbeddedBitmapScaling::version_initial) {
    170             return false;
    171         }
    172 
    173         uint32_t numSizes = SkEndianSwap32(ebsc->numSizes);
    174         if (numSizes > 1024 ||
    175             ebsc.fSize < sizeof(SkOTTableEmbeddedBitmapScaling) +
    176                          sizeof(SkOTTableEmbeddedBitmapScaling::BitmapScaleTable) * numSizes)
    177         {
    178             return false;
    179         }
    180 
    181         const SkOTTableEmbeddedBitmapScaling::BitmapScaleTable* scaleTable =
    182                 SkTAfter<const SkOTTableEmbeddedBitmapScaling::BitmapScaleTable>(ebsc.get());
    183         for (uint32_t i = 0; i < numSizes; ++i, ++scaleTable) {
    184             if (scaleTable->ppemX == scaleTable->ppemY &&
    185                 range.min <= scaleTable->ppemX && scaleTable->ppemX <= range.max) {
    186                 // EBSC tables are normally only found in bitmap only fonts.
    187                 return true;
    188             }
    189         }
    190     }
    191 
    192     return false;
    193 }
    194 
    195 static bool both_zero(SkScalar a, SkScalar b) {
    196     return 0 == a && 0 == b;
    197 }
    198 
    199 // returns false if there is any non-90-rotation or skew
    200 static bool is_axis_aligned(const SkScalerContext::Rec& rec) {
    201     return 0 == rec.fPreSkewX &&
    202            (both_zero(rec.fPost2x2[0][1], rec.fPost2x2[1][0]) ||
    203             both_zero(rec.fPost2x2[0][0], rec.fPost2x2[1][1]));
    204 }
    205 
    206 SkScalerContext_DW::SkScalerContext_DW(DWriteFontTypeface* typeface,
    207                                        const SkDescriptor* desc)
    208         : SkScalerContext(typeface, desc)
    209         , fTypeface(SkRef(typeface))
    210         , fGlyphCount(-1) {
    211 
    212     // In general, all glyphs should use CLEARTYPE_NATURAL_SYMMETRIC
    213     // except when bi-level rendering is requested or there are embedded
    214     // bi-level bitmaps (and the embedded bitmap flag is set and no rotation).
    215     //
    216     // DirectWrite's IDWriteFontFace::GetRecommendedRenderingMode does not do
    217     // this. As a result, determine the actual size of the text and then see if
    218     // there are any embedded bi-level bitmaps of that size. If there are, then
    219     // force bitmaps by requesting bi-level rendering.
    220     //
    221     // FreeType allows for separate ppemX and ppemY, but DirectWrite assumes
    222     // square pixels and only uses ppemY. Therefore the transform must track any
    223     // non-uniform x-scale.
    224     //
    225     // Also, rotated glyphs should have the same absolute advance widths as
    226     // horizontal glyphs and the subpixel flag should not affect glyph shapes.
    227 
    228     SkVector scale;
    229     SkMatrix GsA;
    230     fRec.computeMatrices(SkScalerContextRec::kVertical_PreMatrixScale,
    231                          &scale, &fSkXform, &GsA, &fG_inv);
    232 
    233     fXform.m11 = SkScalarToFloat(fSkXform.getScaleX());
    234     fXform.m12 = SkScalarToFloat(fSkXform.getSkewY());
    235     fXform.m21 = SkScalarToFloat(fSkXform.getSkewX());
    236     fXform.m22 = SkScalarToFloat(fSkXform.getScaleY());
    237     fXform.dx = 0;
    238     fXform.dy = 0;
    239 
    240     fGsA.m11 = SkScalarToFloat(GsA.get(SkMatrix::kMScaleX));
    241     fGsA.m12 = SkScalarToFloat(GsA.get(SkMatrix::kMSkewY)); // This should be ~0.
    242     fGsA.m21 = SkScalarToFloat(GsA.get(SkMatrix::kMSkewX));
    243     fGsA.m22 = SkScalarToFloat(GsA.get(SkMatrix::kMScaleY));
    244     fGsA.dx = 0;
    245     fGsA.dy = 0;
    246 
    247     // realTextSize is the actual device size we want (as opposed to the size the user requested).
    248     // gdiTextSize is the size we request when GDI compatible.
    249     // If the scale is negative, this means the matrix will do the flip anyway.
    250     const SkScalar realTextSize = scale.fY;
    251     // Due to floating point math, the lower bits are suspect. Round carefully.
    252     SkScalar gdiTextSize = SkScalarRoundToScalar(realTextSize * 64.0f) / 64.0f;
    253     if (gdiTextSize == 0) {
    254         gdiTextSize = SK_Scalar1;
    255     }
    256 
    257     bool bitmapRequested = SkToBool(fRec.fFlags & SkScalerContext::kEmbeddedBitmapText_Flag);
    258     bool treatLikeBitmap = false;
    259     bool axisAlignedBitmap = false;
    260     if (bitmapRequested) {
    261         // When embedded bitmaps are requested, treat the entire range like
    262         // a bitmap strike if the range is gridfit only and contains a bitmap.
    263         int bitmapPPEM = SkScalarTruncToInt(gdiTextSize);
    264         PPEMRange range = { bitmapPPEM, bitmapPPEM };
    265         expand_range_if_gridfit_only(typeface, bitmapPPEM, &range);
    266         treatLikeBitmap = has_bitmap_strike(typeface, range);
    267 
    268         axisAlignedBitmap = is_axis_aligned(fRec);
    269     }
    270 
    271     // If the user requested aliased, do so with aliased compatible metrics.
    272     if (SkMask::kBW_Format == fRec.fMaskFormat) {
    273         fTextSizeRender = gdiTextSize;
    274         fRenderingMode = DWRITE_RENDERING_MODE_ALIASED;
    275         fTextureType = DWRITE_TEXTURE_ALIASED_1x1;
    276         fTextSizeMeasure = gdiTextSize;
    277         fMeasuringMode = DWRITE_MEASURING_MODE_GDI_CLASSIC;
    278 
    279     // If we can use a bitmap, use gdi classic rendering and measurement.
    280     // This will not always provide a bitmap, but matches expected behavior.
    281     } else if (treatLikeBitmap && axisAlignedBitmap) {
    282         fTextSizeRender = gdiTextSize;
    283         fRenderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC;
    284         fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
    285         fTextSizeMeasure = gdiTextSize;
    286         fMeasuringMode = DWRITE_MEASURING_MODE_GDI_CLASSIC;
    287 
    288     // If rotated but the horizontal text could have used a bitmap,
    289     // render high quality rotated glyphs but measure using bitmap metrics.
    290     } else if (treatLikeBitmap) {
    291         fTextSizeRender = gdiTextSize;
    292         fRenderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
    293         fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
    294         fTextSizeMeasure = gdiTextSize;
    295         fMeasuringMode = DWRITE_MEASURING_MODE_GDI_CLASSIC;
    296 
    297     // Fonts that have hints but no gasp table get non-symmetric rendering.
    298     // Usually such fonts have low quality hints which were never tested
    299     // with anything but GDI ClearType classic. Such fonts often rely on
    300     // drop out control in the y direction in order to be legible.
    301     } else if (is_hinted_without_gasp(typeface)) {
    302         fTextSizeRender = gdiTextSize;
    303         fRenderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL;
    304         fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
    305         fTextSizeMeasure = realTextSize;
    306         fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL;
    307 
    308     // The normal case is to use natural symmetric rendering and linear metrics.
    309     } else {
    310         fTextSizeRender = realTextSize;
    311         fRenderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
    312         fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
    313         fTextSizeMeasure = realTextSize;
    314         fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL;
    315     }
    316 
    317     if (this->isSubpixel()) {
    318         fTextSizeMeasure = realTextSize;
    319         fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL;
    320     }
    321 }
    322 
    323 SkScalerContext_DW::~SkScalerContext_DW() {
    324 }
    325 
    326 unsigned SkScalerContext_DW::generateGlyphCount() {
    327     if (fGlyphCount < 0) {
    328         fGlyphCount = fTypeface->fDWriteFontFace->GetGlyphCount();
    329     }
    330     return fGlyphCount;
    331 }
    332 
    333 uint16_t SkScalerContext_DW::generateCharToGlyph(SkUnichar uni) {
    334     uint16_t index = 0;
    335     fTypeface->fDWriteFontFace->GetGlyphIndices(reinterpret_cast<UINT32*>(&uni), 1, &index);
    336     return index;
    337 }
    338 
    339 void SkScalerContext_DW::generateAdvance(SkGlyph* glyph) {
    340     //Delta is the difference between the right/left side bearing metric
    341     //and where the right/left side bearing ends up after hinting.
    342     //DirectWrite does not provide this information.
    343     glyph->fRsbDelta = 0;
    344     glyph->fLsbDelta = 0;
    345 
    346     glyph->fAdvanceX = 0;
    347     glyph->fAdvanceY = 0;
    348 
    349     uint16_t glyphId = glyph->getGlyphID();
    350     DWRITE_GLYPH_METRICS gm;
    351 
    352     if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode ||
    353         DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode)
    354     {
    355         Exclusive l(DWriteFactoryMutex);
    356         HRVM(fTypeface->fDWriteFontFace->GetGdiCompatibleGlyphMetrics(
    357                  fTextSizeMeasure,
    358                  1.0f, // pixelsPerDip
    359                  &fGsA,
    360                  DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode,
    361                  &glyphId, 1,
    362                  &gm),
    363              "Could not get gdi compatible glyph metrics.");
    364     } else {
    365         Exclusive l(DWriteFactoryMutex);
    366         HRVM(fTypeface->fDWriteFontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm),
    367              "Could not get design metrics.");
    368     }
    369 
    370     DWRITE_FONT_METRICS dwfm;
    371     {
    372         Shared l(DWriteFactoryMutex);
    373         fTypeface->fDWriteFontFace->GetMetrics(&dwfm);
    374     }
    375     SkScalar advanceX = SkScalarMulDiv(fTextSizeMeasure,
    376                                        SkIntToScalar(gm.advanceWidth),
    377                                        SkIntToScalar(dwfm.designUnitsPerEm));
    378 
    379     SkVector vecs[1] = { { advanceX, 0 } };
    380     if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode ||
    381         DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode)
    382     {
    383         // DirectWrite produced 'compatible' metrics, but while close,
    384         // the end result is not always an integer as it would be with GDI.
    385         vecs[0].fX = SkScalarRoundToScalar(advanceX);
    386         fG_inv.mapVectors(vecs, SK_ARRAY_COUNT(vecs));
    387     } else {
    388         fSkXform.mapVectors(vecs, SK_ARRAY_COUNT(vecs));
    389     }
    390 
    391     glyph->fAdvanceX = SkScalarToFixed(vecs[0].fX);
    392     glyph->fAdvanceY = SkScalarToFixed(vecs[0].fY);
    393 }
    394 
    395 HRESULT SkScalerContext_DW::getBoundingBox(SkGlyph* glyph,
    396                                            DWRITE_RENDERING_MODE renderingMode,
    397                                            DWRITE_TEXTURE_TYPE textureType,
    398                                            RECT* bbox)
    399 {
    400     //Measure raster size.
    401     fXform.dx = SkFixedToFloat(glyph->getSubXFixed());
    402     fXform.dy = SkFixedToFloat(glyph->getSubYFixed());
    403 
    404     FLOAT advance = 0;
    405 
    406     UINT16 glyphId = glyph->getGlyphID();
    407 
    408     DWRITE_GLYPH_OFFSET offset;
    409     offset.advanceOffset = 0.0f;
    410     offset.ascenderOffset = 0.0f;
    411 
    412     DWRITE_GLYPH_RUN run;
    413     run.glyphCount = 1;
    414     run.glyphAdvances = &advance;
    415     run.fontFace = fTypeface->fDWriteFontFace.get();
    416     run.fontEmSize = SkScalarToFloat(fTextSizeRender);
    417     run.bidiLevel = 0;
    418     run.glyphIndices = &glyphId;
    419     run.isSideways = FALSE;
    420     run.glyphOffsets = &offset;
    421 
    422     SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
    423     {
    424         Exclusive l(DWriteFactoryMutex);
    425         HRM(fTypeface->fFactory->CreateGlyphRunAnalysis(
    426             &run,
    427             1.0f, // pixelsPerDip,
    428             &fXform,
    429             renderingMode,
    430             fMeasuringMode,
    431             0.0f, // baselineOriginX,
    432             0.0f, // baselineOriginY,
    433             &glyphRunAnalysis),
    434             "Could not create glyph run analysis.");
    435     }
    436     {
    437         Shared l(DWriteFactoryMutex);
    438         HRM(glyphRunAnalysis->GetAlphaTextureBounds(textureType, bbox),
    439             "Could not get texture bounds.");
    440     }
    441     return S_OK;
    442 }
    443 
    444 /** GetAlphaTextureBounds succeeds but sometimes returns empty bounds like
    445  *  { 0x80000000, 0x80000000, 0x80000000, 0x80000000 }
    446  *  for small, but not quite zero, sized glyphs.
    447  *  Only set as non-empty if the returned bounds are non-empty.
    448  */
    449 static bool glyph_check_and_set_bounds(SkGlyph* glyph, const RECT& bbox) {
    450     if (bbox.left >= bbox.right || bbox.top >= bbox.bottom) {
    451         return false;
    452     }
    453     glyph->fWidth = SkToU16(bbox.right - bbox.left);
    454     glyph->fHeight = SkToU16(bbox.bottom - bbox.top);
    455     glyph->fLeft = SkToS16(bbox.left);
    456     glyph->fTop = SkToS16(bbox.top);
    457     return true;
    458 }
    459 
    460 void SkScalerContext_DW::generateMetrics(SkGlyph* glyph) {
    461     glyph->fWidth = 0;
    462     glyph->fHeight = 0;
    463     glyph->fLeft = 0;
    464     glyph->fTop = 0;
    465 
    466     this->generateAdvance(glyph);
    467 
    468     RECT bbox;
    469     HRVM(this->getBoundingBox(glyph, fRenderingMode, fTextureType, &bbox),
    470          "Requested bounding box could not be determined.");
    471 
    472     if (glyph_check_and_set_bounds(glyph, bbox)) {
    473         return;
    474     }
    475 
    476     // GetAlphaTextureBounds succeeds but returns an empty RECT if there are no
    477     // glyphs of the specified texture type. When this happens, try with the
    478     // alternate texture type.
    479     if (DWRITE_TEXTURE_CLEARTYPE_3x1 == fTextureType) {
    480         HRVM(this->getBoundingBox(glyph,
    481                                   DWRITE_RENDERING_MODE_ALIASED,
    482                                   DWRITE_TEXTURE_ALIASED_1x1,
    483                                   &bbox),
    484              "Fallback bounding box could not be determined.");
    485         if (glyph_check_and_set_bounds(glyph, bbox)) {
    486             glyph->fForceBW = 1;
    487         }
    488     }
    489     // TODO: handle the case where a request for DWRITE_TEXTURE_ALIASED_1x1
    490     // fails, and try DWRITE_TEXTURE_CLEARTYPE_3x1.
    491 }
    492 
    493 void SkScalerContext_DW::generateFontMetrics(SkPaint::FontMetrics* metrics) {
    494     if (nullptr == metrics) {
    495         return;
    496     }
    497 
    498     sk_bzero(metrics, sizeof(*metrics));
    499 
    500     DWRITE_FONT_METRICS dwfm;
    501     if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode ||
    502         DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode)
    503     {
    504         fTypeface->fDWriteFontFace->GetGdiCompatibleMetrics(
    505              fTextSizeRender,
    506              1.0f, // pixelsPerDip
    507              &fXform,
    508              &dwfm);
    509     } else {
    510         fTypeface->fDWriteFontFace->GetMetrics(&dwfm);
    511     }
    512 
    513     SkScalar upem = SkIntToScalar(dwfm.designUnitsPerEm);
    514 
    515     metrics->fAscent = -fTextSizeRender * SkIntToScalar(dwfm.ascent) / upem;
    516     metrics->fDescent = fTextSizeRender * SkIntToScalar(dwfm.descent) / upem;
    517     metrics->fLeading = fTextSizeRender * SkIntToScalar(dwfm.lineGap) / upem;
    518     metrics->fXHeight = fTextSizeRender * SkIntToScalar(dwfm.xHeight) / upem;
    519     metrics->fUnderlineThickness = fTextSizeRender * SkIntToScalar(dwfm.underlineThickness) / upem;
    520     metrics->fUnderlinePosition = -(fTextSizeRender * SkIntToScalar(dwfm.underlinePosition) / upem);
    521 
    522     metrics->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
    523     metrics->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
    524 
    525 #if SK_HAS_DWRITE_1_H
    526     if (fTypeface->fDWriteFontFace1.get()) {
    527         DWRITE_FONT_METRICS1 dwfm1;
    528         fTypeface->fDWriteFontFace1->GetMetrics(&dwfm1);
    529         metrics->fTop = -fTextSizeRender * SkIntToScalar(dwfm1.glyphBoxTop) / upem;
    530         metrics->fBottom = -fTextSizeRender * SkIntToScalar(dwfm1.glyphBoxBottom) / upem;
    531         metrics->fXMin = fTextSizeRender * SkIntToScalar(dwfm1.glyphBoxLeft) / upem;
    532         metrics->fXMax = fTextSizeRender * SkIntToScalar(dwfm1.glyphBoxRight) / upem;
    533 
    534         metrics->fMaxCharWidth = metrics->fXMax - metrics->fXMin;
    535         return;
    536     }
    537 #else
    538 #  pragma message("No dwrite_1.h is available, font metrics may be affected.")
    539 #endif
    540 
    541     AutoTDWriteTable<SkOTTableHead> head(fTypeface->fDWriteFontFace.get());
    542     if (head.fExists &&
    543         head.fSize >= sizeof(SkOTTableHead) &&
    544         head->version == SkOTTableHead::version1)
    545     {
    546         metrics->fTop = -fTextSizeRender * (int16_t)SkEndian_SwapBE16(head->yMax) / upem;
    547         metrics->fBottom = -fTextSizeRender * (int16_t)SkEndian_SwapBE16(head->yMin) / upem;
    548         metrics->fXMin = fTextSizeRender * (int16_t)SkEndian_SwapBE16(head->xMin) / upem;
    549         metrics->fXMax = fTextSizeRender * (int16_t)SkEndian_SwapBE16(head->xMax) / upem;
    550 
    551         metrics->fMaxCharWidth = metrics->fXMax - metrics->fXMin;
    552         return;
    553     }
    554 
    555     metrics->fTop = metrics->fAscent;
    556     metrics->fBottom = metrics->fDescent;
    557 }
    558 
    559 ///////////////////////////////////////////////////////////////////////////////
    560 
    561 #include "SkColorPriv.h"
    562 
    563 static void bilevel_to_bw(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph) {
    564     const int width = glyph.fWidth;
    565     const size_t dstRB = (width + 7) >> 3;
    566     uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage);
    567 
    568     int byteCount = width >> 3;
    569     int bitCount = width & 7;
    570 
    571     for (int y = 0; y < glyph.fHeight; ++y) {
    572         if (byteCount > 0) {
    573             for (int i = 0; i < byteCount; ++i) {
    574                 unsigned byte = 0;
    575                 byte |= src[0] & (1 << 7);
    576                 byte |= src[1] & (1 << 6);
    577                 byte |= src[2] & (1 << 5);
    578                 byte |= src[3] & (1 << 4);
    579                 byte |= src[4] & (1 << 3);
    580                 byte |= src[5] & (1 << 2);
    581                 byte |= src[6] & (1 << 1);
    582                 byte |= src[7] & (1 << 0);
    583                 dst[i] = byte;
    584                 src += 8;
    585             }
    586         }
    587         if (bitCount > 0) {
    588             unsigned byte = 0;
    589             unsigned mask = 0x80;
    590             for (int i = 0; i < bitCount; i++) {
    591                 byte |= (src[i]) & mask;
    592                 mask >>= 1;
    593             }
    594             dst[byteCount] = byte;
    595         }
    596         src += bitCount;
    597         dst += dstRB;
    598     }
    599 }
    600 
    601 template<bool APPLY_PREBLEND>
    602 static void rgb_to_a8(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph, const uint8_t* table8) {
    603     const size_t dstRB = glyph.rowBytes();
    604     const U16CPU width = glyph.fWidth;
    605     uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage);
    606 
    607     for (U16CPU y = 0; y < glyph.fHeight; y++) {
    608         for (U16CPU i = 0; i < width; i++) {
    609             U8CPU r = *(src++);
    610             U8CPU g = *(src++);
    611             U8CPU b = *(src++);
    612             dst[i] = sk_apply_lut_if<APPLY_PREBLEND>((r + g + b) / 3, table8);
    613         }
    614         dst = (uint8_t*)((char*)dst + dstRB);
    615     }
    616 }
    617 
    618 template<bool APPLY_PREBLEND, bool RGB>
    619 static void rgb_to_lcd16(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph,
    620                          const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
    621     const size_t dstRB = glyph.rowBytes();
    622     const U16CPU width = glyph.fWidth;
    623     uint16_t* SK_RESTRICT dst = static_cast<uint16_t*>(glyph.fImage);
    624 
    625     for (U16CPU y = 0; y < glyph.fHeight; y++) {
    626         for (U16CPU i = 0; i < width; i++) {
    627             U8CPU r, g, b;
    628             if (RGB) {
    629                 r = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableR);
    630                 g = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableG);
    631                 b = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableB);
    632             } else {
    633                 b = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableB);
    634                 g = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableG);
    635                 r = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableR);
    636             }
    637             dst[i] = SkPack888ToRGB16(r, g, b);
    638         }
    639         dst = (uint16_t*)((char*)dst + dstRB);
    640     }
    641 }
    642 
    643 const void* SkScalerContext_DW::drawDWMask(const SkGlyph& glyph,
    644                                            DWRITE_RENDERING_MODE renderingMode,
    645                                            DWRITE_TEXTURE_TYPE textureType)
    646 {
    647     int sizeNeeded = glyph.fWidth * glyph.fHeight;
    648     if (DWRITE_RENDERING_MODE_ALIASED != renderingMode) {
    649         sizeNeeded *= 3;
    650     }
    651     if (sizeNeeded > fBits.count()) {
    652         fBits.setCount(sizeNeeded);
    653     }
    654 
    655     // erase
    656     memset(fBits.begin(), 0, sizeNeeded);
    657 
    658     fXform.dx = SkFixedToFloat(glyph.getSubXFixed());
    659     fXform.dy = SkFixedToFloat(glyph.getSubYFixed());
    660 
    661     FLOAT advance = 0.0f;
    662 
    663     UINT16 index = glyph.getGlyphID();
    664 
    665     DWRITE_GLYPH_OFFSET offset;
    666     offset.advanceOffset = 0.0f;
    667     offset.ascenderOffset = 0.0f;
    668 
    669     DWRITE_GLYPH_RUN run;
    670     run.glyphCount = 1;
    671     run.glyphAdvances = &advance;
    672     run.fontFace = fTypeface->fDWriteFontFace.get();
    673     run.fontEmSize = SkScalarToFloat(fTextSizeRender);
    674     run.bidiLevel = 0;
    675     run.glyphIndices = &index;
    676     run.isSideways = FALSE;
    677     run.glyphOffsets = &offset;
    678     {
    679 
    680         SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
    681         {
    682             Exclusive l(DWriteFactoryMutex);
    683             HRNM(fTypeface->fFactory->CreateGlyphRunAnalysis(&run,
    684                 1.0f, // pixelsPerDip,
    685                 &fXform,
    686                 renderingMode,
    687                 fMeasuringMode,
    688                 0.0f, // baselineOriginX,
    689                 0.0f, // baselineOriginY,
    690                 &glyphRunAnalysis),
    691                 "Could not create glyph run analysis.");
    692         }
    693         //NOTE: this assumes that the glyph has already been measured
    694         //with an exact same glyph run analysis.
    695         RECT bbox;
    696         bbox.left = glyph.fLeft;
    697         bbox.top = glyph.fTop;
    698         bbox.right = glyph.fLeft + glyph.fWidth;
    699         bbox.bottom = glyph.fTop + glyph.fHeight;
    700         {
    701             Shared l(DWriteFactoryMutex);
    702             HRNM(glyphRunAnalysis->CreateAlphaTexture(textureType,
    703                 &bbox,
    704                 fBits.begin(),
    705                 sizeNeeded),
    706                 "Could not draw mask.");
    707         }
    708     }
    709     return fBits.begin();
    710 }
    711 
    712 void SkScalerContext_DW::generateImage(const SkGlyph& glyph) {
    713     //Create the mask.
    714     DWRITE_RENDERING_MODE renderingMode = fRenderingMode;
    715     DWRITE_TEXTURE_TYPE textureType = fTextureType;
    716     if (glyph.fForceBW) {
    717         renderingMode = DWRITE_RENDERING_MODE_ALIASED;
    718         textureType = DWRITE_TEXTURE_ALIASED_1x1;
    719     }
    720     const void* bits = this->drawDWMask(glyph, renderingMode, textureType);
    721     if (!bits) {
    722         sk_bzero(glyph.fImage, glyph.computeImageSize());
    723         return;
    724     }
    725 
    726     //Copy the mask into the glyph.
    727     const uint8_t* src = (const uint8_t*)bits;
    728     if (DWRITE_RENDERING_MODE_ALIASED == renderingMode) {
    729         bilevel_to_bw(src, glyph);
    730         const_cast<SkGlyph&>(glyph).fMaskFormat = SkMask::kBW_Format;
    731     } else if (!isLCD(fRec)) {
    732         if (fPreBlend.isApplicable()) {
    733             rgb_to_a8<true>(src, glyph, fPreBlend.fG);
    734         } else {
    735             rgb_to_a8<false>(src, glyph, fPreBlend.fG);
    736         }
    737     } else {
    738         SkASSERT(SkMask::kLCD16_Format == glyph.fMaskFormat);
    739         if (fPreBlend.isApplicable()) {
    740             if (fRec.fFlags & SkScalerContext::kLCD_BGROrder_Flag) {
    741                 rgb_to_lcd16<true, false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
    742             } else {
    743                 rgb_to_lcd16<true, true>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
    744             }
    745         } else {
    746             if (fRec.fFlags & SkScalerContext::kLCD_BGROrder_Flag) {
    747                 rgb_to_lcd16<false, false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
    748             } else {
    749                 rgb_to_lcd16<false, true>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
    750             }
    751         }
    752     }
    753 }
    754 
    755 void SkScalerContext_DW::generatePath(const SkGlyph& glyph, SkPath* path) {
    756     SkASSERT(path);
    757 
    758     path->reset();
    759 
    760     SkTScopedComPtr<IDWriteGeometrySink> geometryToPath;
    761     HRVM(SkDWriteGeometrySink::Create(path, &geometryToPath),
    762          "Could not create geometry to path converter.");
    763     uint16_t glyphId = glyph.getGlyphID();
    764     {
    765         Exclusive l(DWriteFactoryMutex);
    766         //TODO: convert to<->from DIUs? This would make a difference if hinting.
    767         //It may not be needed, it appears that DirectWrite only hints at em size.
    768         HRVM(fTypeface->fDWriteFontFace->GetGlyphRunOutline(SkScalarToFloat(fTextSizeRender),
    769             &glyphId,
    770             nullptr, //advances
    771             nullptr, //offsets
    772             1, //num glyphs
    773             FALSE, //sideways
    774             FALSE, //rtl
    775             geometryToPath.get()),
    776             "Could not create glyph outline.");
    777     }
    778 
    779     path->transform(fSkXform);
    780 }
    781 
    782 #endif//defined(SK_BUILD_FOR_WIN32)
    783