1e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com/*
2e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com * Copyright 2011 Google Inc.
3e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com *
4e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com * Use of this source code is governed by a BSD-style license that can be
5e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com * found in the LICENSE file.
6e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com */
7e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com
8e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com#include "SkTypes.h"
98f11d4dcafef4447fa68ea0ab28a72589241e9fdMike Klein#if defined(SK_BUILD_FOR_WIN)
101ee76510f5dbf632d30975fc3509ef4f609156d2mtklein
11e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com#undef GetGlyphIndices
12e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com
13c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin#include "SkDraw.h"
1472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkDWrite.h"
15e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com#include "SkDWriteGeometrySink.h"
16e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com#include "SkEndian.h"
17e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com#include "SkGlyph.h"
18e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com#include "SkHRESULT.h"
19e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com#include "SkMaskGamma.h"
20058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com#include "SkMatrix22.h"
21c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb#include "SkMutex.h"
22058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com#include "SkOTTable_EBLC.h"
23058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com#include "SkOTTable_EBSC.h"
24740c3f17f7f37fca5268b60a83448953f075d8d1bungeman#include "SkOTTable_gasp.h"
25761b2509d59787a8920b2e98911cff9f88e0eb4ebungeman#include "SkOTTable_maxp.h"
26e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com#include "SkPath.h"
27c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin#include "SkRasterClip.h"
2851daa25a2b16bca578e78b7ea1e5815b9abb8b0bbungeman#include "SkScalerContext.h"
2951daa25a2b16bca578e78b7ea1e5815b9abb8b0bbungeman#include "SkScalerContext_win_dw.h"
306440f0b09ede274f93131eebb3ef49e73dfb2b9cherb#include "SkSharedMutex.h"
31e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com#include "SkTScopedComPtr.h"
3251daa25a2b16bca578e78b7ea1e5815b9abb8b0bbungeman#include "SkTypeface_win_dw.h"
33e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com
34e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com#include <dwrite.h>
35e0c9e00cd5ed17a45a988b8b57fa9c09f3574921Ben Wagner#include <dwrite_1.h>
36e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com
37c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb/* Note:
38c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb * In versions 8 and 8.1 of Windows, some calls in DWrite are not thread safe.
39c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb * The DWriteFactoryMutex protects the calls that are problematic.
40c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb */
416440f0b09ede274f93131eebb3ef49e73dfb2b9cherbstatic SkSharedMutex DWriteFactoryMutex;
42c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb
436440f0b09ede274f93131eebb3ef49e73dfb2b9cherbtypedef SkAutoSharedMutexShared Shared;
44c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb
453e45a2f48ed8dbf3a55e980c43d97d29afeb93a0Ben Wagnerstatic bool isLCD(const SkScalerContextRec& rec) {
46d54d3fc82456f8789b3e4dff40faeb7b670bcf4breed    return SkMask::kLCD16_Format == rec.fMaskFormat;
47e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com}
48e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com
499f591347e902aa0c59a5da2915d829ae162831f4Ben Wagnerstatic bool is_hinted(DWriteFontTypeface* typeface) {
50f10637f2795b147751ef413237389d230b869360mtklein    SkAutoExclusive l(DWriteFactoryMutex);
51761b2509d59787a8920b2e98911cff9f88e0eb4ebungeman    AutoTDWriteTable<SkOTTableMaximumProfile> maxp(typeface->fDWriteFontFace.get());
52761b2509d59787a8920b2e98911cff9f88e0eb4ebungeman    if (!maxp.fExists) {
53761b2509d59787a8920b2e98911cff9f88e0eb4ebungeman        return false;
54761b2509d59787a8920b2e98911cff9f88e0eb4ebungeman    }
55761b2509d59787a8920b2e98911cff9f88e0eb4ebungeman    if (maxp.fSize < sizeof(SkOTTableMaximumProfile::Version::TT)) {
56761b2509d59787a8920b2e98911cff9f88e0eb4ebungeman        return false;
57761b2509d59787a8920b2e98911cff9f88e0eb4ebungeman    }
58761b2509d59787a8920b2e98911cff9f88e0eb4ebungeman    if (maxp->version.version != SkOTTableMaximumProfile::Version::TT::VERSION) {
59761b2509d59787a8920b2e98911cff9f88e0eb4ebungeman        return false;
60761b2509d59787a8920b2e98911cff9f88e0eb4ebungeman    }
619f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner    return (0 != maxp->version.tt.maxSizeOfInstructions);
62761b2509d59787a8920b2e98911cff9f88e0eb4ebungeman}
63761b2509d59787a8920b2e98911cff9f88e0eb4ebungeman
6422253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner/** A GaspRange is inclusive, [min, max]. */
6522253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagnerstruct GaspRange {
6622253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner    using Behavior = SkOTTableGridAndScanProcedure::GaspRange::behavior;
6742a2a20b9114c904ce73d66d0105b81f19d93914Ben Wagner    GaspRange(int min, int max, int version, Behavior flags)
6842a2a20b9114c904ce73d66d0105b81f19d93914Ben Wagner        : fMin(min), fMax(max), fVersion(version), fFlags(flags) { }
6922253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner    int fMin;
7022253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner    int fMax;
7142a2a20b9114c904ce73d66d0105b81f19d93914Ben Wagner    int fVersion;
7222253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner    Behavior fFlags;
73740c3f17f7f37fca5268b60a83448953f075d8d1bungeman};
74740c3f17f7f37fca5268b60a83448953f075d8d1bungeman
7522253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagnerbool get_gasp_range(DWriteFontTypeface* typeface, int size, GaspRange* range) {
76740c3f17f7f37fca5268b60a83448953f075d8d1bungeman    AutoTDWriteTable<SkOTTableGridAndScanProcedure> gasp(typeface->fDWriteFontFace.get());
77740c3f17f7f37fca5268b60a83448953f075d8d1bungeman    if (!gasp.fExists) {
7822253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner        return false;
79740c3f17f7f37fca5268b60a83448953f075d8d1bungeman    }
80740c3f17f7f37fca5268b60a83448953f075d8d1bungeman    if (gasp.fSize < sizeof(SkOTTableGridAndScanProcedure)) {
8122253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner        return false;
82740c3f17f7f37fca5268b60a83448953f075d8d1bungeman    }
83740c3f17f7f37fca5268b60a83448953f075d8d1bungeman    if (gasp->version != SkOTTableGridAndScanProcedure::version0 &&
84740c3f17f7f37fca5268b60a83448953f075d8d1bungeman        gasp->version != SkOTTableGridAndScanProcedure::version1)
85740c3f17f7f37fca5268b60a83448953f075d8d1bungeman    {
8622253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner        return false;
87740c3f17f7f37fca5268b60a83448953f075d8d1bungeman    }
88740c3f17f7f37fca5268b60a83448953f075d8d1bungeman
89740c3f17f7f37fca5268b60a83448953f075d8d1bungeman    uint16_t numRanges = SkEndianSwap16(gasp->numRanges);
90740c3f17f7f37fca5268b60a83448953f075d8d1bungeman    if (numRanges > 1024 ||
91740c3f17f7f37fca5268b60a83448953f075d8d1bungeman        gasp.fSize < sizeof(SkOTTableGridAndScanProcedure) +
9222253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner        sizeof(SkOTTableGridAndScanProcedure::GaspRange) * numRanges)
93740c3f17f7f37fca5268b60a83448953f075d8d1bungeman    {
9422253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner        return false;
95740c3f17f7f37fca5268b60a83448953f075d8d1bungeman    }
96740c3f17f7f37fca5268b60a83448953f075d8d1bungeman
97740c3f17f7f37fca5268b60a83448953f075d8d1bungeman    const SkOTTableGridAndScanProcedure::GaspRange* rangeTable =
98740c3f17f7f37fca5268b60a83448953f075d8d1bungeman            SkTAfter<const SkOTTableGridAndScanProcedure::GaspRange>(gasp.get());
99740c3f17f7f37fca5268b60a83448953f075d8d1bungeman    int minPPEM = -1;
100740c3f17f7f37fca5268b60a83448953f075d8d1bungeman    for (uint16_t i = 0; i < numRanges; ++i, ++rangeTable) {
101740c3f17f7f37fca5268b60a83448953f075d8d1bungeman        int maxPPEM = SkEndianSwap16(rangeTable->maxPPEM);
10222253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner        if (minPPEM < size && size <= maxPPEM) {
10322253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner            range->fMin = minPPEM + 1;
10422253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner            range->fMax = maxPPEM;
10542a2a20b9114c904ce73d66d0105b81f19d93914Ben Wagner            range->fVersion = SkEndian_SwapBE16(gasp->version);
10622253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner            range->fFlags = rangeTable->flags;
10722253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner            return true;
108740c3f17f7f37fca5268b60a83448953f075d8d1bungeman        }
109740c3f17f7f37fca5268b60a83448953f075d8d1bungeman        minPPEM = maxPPEM;
110740c3f17f7f37fca5268b60a83448953f075d8d1bungeman    }
11122253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner    return false;
11222253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner}
11322253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner/** If the rendering mode for the specified 'size' is gridfit, then place
11422253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner *  the gridfit range into 'range'. Otherwise, leave 'range' alone.
11522253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner */
11622253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagnerstatic bool is_gridfit_only(GaspRange::Behavior flags) {
11722253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner    return flags.raw.value == GaspRange::Behavior::Raw::GridfitMask;
118740c3f17f7f37fca5268b60a83448953f075d8d1bungeman}
119740c3f17f7f37fca5268b60a83448953f075d8d1bungeman
12022253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagnerstatic bool has_bitmap_strike(DWriteFontTypeface* typeface, GaspRange range) {
121f10637f2795b147751ef413237389d230b869360mtklein    SkAutoExclusive l(DWriteFactoryMutex);
122058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com    {
123058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com        AutoTDWriteTable<SkOTTableEmbeddedBitmapLocation> eblc(typeface->fDWriteFontFace.get());
124058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com        if (!eblc.fExists) {
125058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com            return false;
126058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com        }
127058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com        if (eblc.fSize < sizeof(SkOTTableEmbeddedBitmapLocation)) {
128058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com            return false;
129058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com        }
130058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com        if (eblc->version != SkOTTableEmbeddedBitmapLocation::version_initial) {
131058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com            return false;
132058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com        }
133058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com
134058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com        uint32_t numSizes = SkEndianSwap32(eblc->numSizes);
135740c3f17f7f37fca5268b60a83448953f075d8d1bungeman        if (numSizes > 1024 ||
136740c3f17f7f37fca5268b60a83448953f075d8d1bungeman            eblc.fSize < sizeof(SkOTTableEmbeddedBitmapLocation) +
137058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com                         sizeof(SkOTTableEmbeddedBitmapLocation::BitmapSizeTable) * numSizes)
138058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com        {
139058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com            return false;
140058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com        }
141058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com
142058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com        const SkOTTableEmbeddedBitmapLocation::BitmapSizeTable* sizeTable =
143058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com                SkTAfter<const SkOTTableEmbeddedBitmapLocation::BitmapSizeTable>(eblc.get());
144058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com        for (uint32_t i = 0; i < numSizes; ++i, ++sizeTable) {
145740c3f17f7f37fca5268b60a83448953f075d8d1bungeman            if (sizeTable->ppemX == sizeTable->ppemY &&
14622253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                range.fMin <= sizeTable->ppemX && sizeTable->ppemX <= range.fMax)
147740c3f17f7f37fca5268b60a83448953f075d8d1bungeman            {
148058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com                // TODO: determine if we should dig through IndexSubTableArray/IndexSubTable
149058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com                // to determine the actual number of glyphs with bitmaps.
150058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com
151058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com                // TODO: Ensure that the bitmaps actually cover a significant portion of the strike.
152058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com
153740c3f17f7f37fca5268b60a83448953f075d8d1bungeman                // TODO: Ensure that the bitmaps are bi-level?
154058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com                if (sizeTable->endGlyphIndex >= sizeTable->startGlyphIndex + 3) {
155058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com                    return true;
156058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com                }
157058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com            }
158058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com        }
159058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com    }
160058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com
161058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com    {
162058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com        AutoTDWriteTable<SkOTTableEmbeddedBitmapScaling> ebsc(typeface->fDWriteFontFace.get());
163058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com        if (!ebsc.fExists) {
164058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com            return false;
165058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com        }
166058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com        if (ebsc.fSize < sizeof(SkOTTableEmbeddedBitmapScaling)) {
167058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com            return false;
168058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com        }
169058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com        if (ebsc->version != SkOTTableEmbeddedBitmapScaling::version_initial) {
170058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com            return false;
171058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com        }
172058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com
173058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com        uint32_t numSizes = SkEndianSwap32(ebsc->numSizes);
174740c3f17f7f37fca5268b60a83448953f075d8d1bungeman        if (numSizes > 1024 ||
175740c3f17f7f37fca5268b60a83448953f075d8d1bungeman            ebsc.fSize < sizeof(SkOTTableEmbeddedBitmapScaling) +
176058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com                         sizeof(SkOTTableEmbeddedBitmapScaling::BitmapScaleTable) * numSizes)
177058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com        {
178058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com            return false;
179058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com        }
180058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com
181058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com        const SkOTTableEmbeddedBitmapScaling::BitmapScaleTable* scaleTable =
182058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com                SkTAfter<const SkOTTableEmbeddedBitmapScaling::BitmapScaleTable>(ebsc.get());
183058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com        for (uint32_t i = 0; i < numSizes; ++i, ++scaleTable) {
184740c3f17f7f37fca5268b60a83448953f075d8d1bungeman            if (scaleTable->ppemX == scaleTable->ppemY &&
18522253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                range.fMin <= scaleTable->ppemX && scaleTable->ppemX <= range.fMax) {
186058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com                // EBSC tables are normally only found in bitmap only fonts.
187058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com                return true;
188058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com            }
189058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com        }
190058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com    }
191058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com
192058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com    return false;
193058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com}
194058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com
195740c3f17f7f37fca5268b60a83448953f075d8d1bungemanstatic bool both_zero(SkScalar a, SkScalar b) {
196058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com    return 0 == a && 0 == b;
197058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com}
198058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com
199058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com// returns false if there is any non-90-rotation or skew
2003e45a2f48ed8dbf3a55e980c43d97d29afeb93a0Ben Wagnerstatic bool is_axis_aligned(const SkScalerContextRec& rec) {
201058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com    return 0 == rec.fPreSkewX &&
202740c3f17f7f37fca5268b60a83448953f075d8d1bungeman           (both_zero(rec.fPost2x2[0][1], rec.fPost2x2[1][0]) ||
203740c3f17f7f37fca5268b60a83448953f075d8d1bungeman            both_zero(rec.fPost2x2[0][0], rec.fPost2x2[1][1]));
204058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com}
205058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com
2067cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungemanSkScalerContext_DW::SkScalerContext_DW(sk_sp<DWriteFontTypeface> typefaceRef,
207a9322c2d86aaef1085c267dfc43cf0747f170a86reed                                       const SkScalerContextEffects& effects,
2086eddc77f6a0078570471277954c07d73b3a921d8bungeman@google.com                                       const SkDescriptor* desc)
2097cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman        : SkScalerContext(std::move(typefaceRef), effects, desc)
210e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com        , fGlyphCount(-1) {
211e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com
2127cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman    DWriteFontTypeface* typeface = this->getDWriteTypeface();
21322253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner    fIsColorFont = typeface->fFactory2 &&
21422253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                   typeface->fDWriteFontFace2 &&
21522253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                   typeface->fDWriteFontFace2->IsColorFont();
216c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin
21722253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner    // In general, all glyphs should use NATURAL_SYMMETRIC
218058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com    // except when bi-level rendering is requested or there are embedded
219058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com    // bi-level bitmaps (and the embedded bitmap flag is set and no rotation).
220058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com    //
221058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com    // DirectWrite's IDWriteFontFace::GetRecommendedRenderingMode does not do
222058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com    // this. As a result, determine the actual size of the text and then see if
223058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com    // there are any embedded bi-level bitmaps of that size. If there are, then
224058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com    // force bitmaps by requesting bi-level rendering.
225058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com    //
226058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com    // FreeType allows for separate ppemX and ppemY, but DirectWrite assumes
227058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com    // square pixels and only uses ppemY. Therefore the transform must track any
228058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com    // non-uniform x-scale.
229058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com    //
230058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com    // Also, rotated glyphs should have the same absolute advance widths as
231058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com    // horizontal glyphs and the subpixel flag should not affect glyph shapes.
232058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com
2335f14c5e038a16c80d50c2f87ae7c8775f977456cbungeman    SkVector scale;
2341f5f6b823d32b1f85589e0cf81f8e7b91e89c1f2Ben Wagner    fRec.computeMatrices(SkScalerContextRec::kVertical_PreMatrixScale, &scale, &fSkXform);
235058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com
2365f14c5e038a16c80d50c2f87ae7c8775f977456cbungeman    fXform.m11 = SkScalarToFloat(fSkXform.getScaleX());
2375f14c5e038a16c80d50c2f87ae7c8775f977456cbungeman    fXform.m12 = SkScalarToFloat(fSkXform.getSkewY());
2385f14c5e038a16c80d50c2f87ae7c8775f977456cbungeman    fXform.m21 = SkScalarToFloat(fSkXform.getSkewX());
2395f14c5e038a16c80d50c2f87ae7c8775f977456cbungeman    fXform.m22 = SkScalarToFloat(fSkXform.getScaleY());
2405f14c5e038a16c80d50c2f87ae7c8775f977456cbungeman    fXform.dx = 0;
2415f14c5e038a16c80d50c2f87ae7c8775f977456cbungeman    fXform.dy = 0;
242058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com
243058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com    // realTextSize is the actual device size we want (as opposed to the size the user requested).
244058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com    // gdiTextSize is the size we request when GDI compatible.
245058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com    // If the scale is negative, this means the matrix will do the flip anyway.
2465f14c5e038a16c80d50c2f87ae7c8775f977456cbungeman    const SkScalar realTextSize = scale.fY;
247058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com    // Due to floating point math, the lower bits are suspect. Round carefully.
2487c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com    SkScalar gdiTextSize = SkScalarRoundToScalar(realTextSize * 64.0f) / 64.0f;
249058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com    if (gdiTextSize == 0) {
250058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com        gdiTextSize = SK_Scalar1;
251058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com    }
252058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com
2537c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com    bool bitmapRequested = SkToBool(fRec.fFlags & SkScalerContext::kEmbeddedBitmapText_Flag);
254740c3f17f7f37fca5268b60a83448953f075d8d1bungeman    bool treatLikeBitmap = false;
2557c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com    bool axisAlignedBitmap = false;
2567c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com    if (bitmapRequested) {
257740c3f17f7f37fca5268b60a83448953f075d8d1bungeman        // When embedded bitmaps are requested, treat the entire range like
258740c3f17f7f37fca5268b60a83448953f075d8d1bungeman        // a bitmap strike if the range is gridfit only and contains a bitmap.
259740c3f17f7f37fca5268b60a83448953f075d8d1bungeman        int bitmapPPEM = SkScalarTruncToInt(gdiTextSize);
26042a2a20b9114c904ce73d66d0105b81f19d93914Ben Wagner        GaspRange range(bitmapPPEM, bitmapPPEM, 0, GaspRange::Behavior());
26122253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner        if (get_gasp_range(typeface, bitmapPPEM, &range)) {
26222253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner            if (!is_gridfit_only(range.fFlags)) {
26342a2a20b9114c904ce73d66d0105b81f19d93914Ben Wagner                range = GaspRange(bitmapPPEM, bitmapPPEM, 0, GaspRange::Behavior());
26422253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner            }
26522253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner        }
266740c3f17f7f37fca5268b60a83448953f075d8d1bungeman        treatLikeBitmap = has_bitmap_strike(typeface, range);
267740c3f17f7f37fca5268b60a83448953f075d8d1bungeman
268740c3f17f7f37fca5268b60a83448953f075d8d1bungeman        axisAlignedBitmap = is_axis_aligned(fRec);
2697c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com    }
270058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com
27142a2a20b9114c904ce73d66d0105b81f19d93914Ben Wagner    GaspRange range(0, 0xFFFF, 0, GaspRange::Behavior());
2729f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner
2737c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com    // If the user requested aliased, do so with aliased compatible metrics.
2747c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com    if (SkMask::kBW_Format == fRec.fMaskFormat) {
275058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com        fTextSizeRender = gdiTextSize;
276d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com        fRenderingMode = DWRITE_RENDERING_MODE_ALIASED;
277d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com        fTextureType = DWRITE_TEXTURE_ALIASED_1x1;
278058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com        fTextSizeMeasure = gdiTextSize;
279058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com        fMeasuringMode = DWRITE_MEASURING_MODE_GDI_CLASSIC;
280df1640d413c16abf4527960642aca41581808699bungeman
2817c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com    // If we can use a bitmap, use gdi classic rendering and measurement.
2827c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com    // This will not always provide a bitmap, but matches expected behavior.
283740c3f17f7f37fca5268b60a83448953f075d8d1bungeman    } else if (treatLikeBitmap && axisAlignedBitmap) {
2847c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com        fTextSizeRender = gdiTextSize;
28522253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner        fRenderingMode = DWRITE_RENDERING_MODE_GDI_CLASSIC;
2867c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com        fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
2877c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com        fTextSizeMeasure = gdiTextSize;
2887c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com        fMeasuringMode = DWRITE_MEASURING_MODE_GDI_CLASSIC;
289df1640d413c16abf4527960642aca41581808699bungeman
2907c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com    // If rotated but the horizontal text could have used a bitmap,
2917c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com    // render high quality rotated glyphs but measure using bitmap metrics.
292740c3f17f7f37fca5268b60a83448953f075d8d1bungeman    } else if (treatLikeBitmap) {
293058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com        fTextSizeRender = gdiTextSize;
29422253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner        fRenderingMode = DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC;
295058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com        fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
296058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com        fTextSizeMeasure = gdiTextSize;
297d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com        fMeasuringMode = DWRITE_MEASURING_MODE_GDI_CLASSIC;
2987c18351d1f9f8fe4c5cbebf1852cd4f7bb5e026fbungeman@google.com
29942a2a20b9114c904ce73d66d0105b81f19d93914Ben Wagner    // If the font has a gasp table version 1, use it to determine symmetric rendering.
30042a2a20b9114c904ce73d66d0105b81f19d93914Ben Wagner    } else if (get_gasp_range(typeface, SkScalarRoundToInt(gdiTextSize), &range) &&
30142a2a20b9114c904ce73d66d0105b81f19d93914Ben Wagner               range.fVersion >= 1)
30242a2a20b9114c904ce73d66d0105b81f19d93914Ben Wagner    {
3039f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner        fTextSizeRender = realTextSize;
3049f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner        fRenderingMode = range.fFlags.field.SymmetricSmoothing
3059f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner                       ? DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC
3069f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner                       : DWRITE_RENDERING_MODE_NATURAL;
307761b2509d59787a8920b2e98911cff9f88e0eb4ebungeman        fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
308761b2509d59787a8920b2e98911cff9f88e0eb4ebungeman        fTextSizeMeasure = realTextSize;
309761b2509d59787a8920b2e98911cff9f88e0eb4ebungeman        fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL;
310761b2509d59787a8920b2e98911cff9f88e0eb4ebungeman
3119f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner    // If the requested size is above 20px or there are no bytecode hints, use symmetric rendering.
3129f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner    } else if (realTextSize > SkIntToScalar(20) || !is_hinted(typeface)) {
313058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com        fTextSizeRender = realTextSize;
3149f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner        fRenderingMode = DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC;
3159f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner        fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
3169f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner        fTextSizeMeasure = realTextSize;
3179f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner        fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL;
3189f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner
31942a2a20b9114c904ce73d66d0105b81f19d93914Ben Wagner    // Fonts with hints, no gasp or gasp version 0, and below 20px get non-symmetric rendering.
32042a2a20b9114c904ce73d66d0105b81f19d93914Ben Wagner    // Often such fonts have hints which were only tested with GDI ClearType classic.
32142a2a20b9114c904ce73d66d0105b81f19d93914Ben Wagner    // Some of these fonts rely on drop out control in the y direction in order to be legible.
3229f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner    // Tenor Sans
3239f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner    //    https://fonts.google.com/specimen/Tenor+Sans
3249f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner    // Gill Sans W04
3259f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner    //    https://cdn.leagueoflegends.com/lolkit/1.1.9/resources/fonts/gill-sans-w04-book.woff
3269f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner    //    https://na.leagueoflegends.com/en/news/game-updates/patch/patch-410-notes
3279f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner    // See https://crbug.com/385897
3289f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner    } else {
3299f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner        fTextSizeRender = gdiTextSize;
3309f591347e902aa0c59a5da2915d829ae162831f4Ben Wagner        fRenderingMode = DWRITE_RENDERING_MODE_NATURAL;
331d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com        fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
332058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com        fTextSizeMeasure = realTextSize;
333d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com        fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL;
334d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com    }
335d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com
33622253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner    // DirectWrite2 allows for grayscale hinting.
33722253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner    fAntiAliasMode = DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE;
33822253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner    if (typeface->fFactory2 && typeface->fDWriteFontFace2 &&
339e0a34e7dcddf68f0972805894f26c54869c3fabaBen Wagner        SkMask::kA8_Format == fRec.fMaskFormat &&
340e0a34e7dcddf68f0972805894f26c54869c3fabaBen Wagner        !(fRec.fFlags & SkScalerContext::kGenA8FromLCD_Flag))
34122253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner    {
34222253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner        // DWRITE_TEXTURE_ALIASED_1x1 is now misnamed, it must also be used with grayscale.
34322253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner        fTextureType = DWRITE_TEXTURE_ALIASED_1x1;
34422253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner        fAntiAliasMode = DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE;
34522253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner    }
34622253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner
34722253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner    // DirectWrite2 allows hinting to be disabled.
34822253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner    fGridFitMode = DWRITE_GRID_FIT_MODE_ENABLED;
34922253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner    if (fRec.getHinting() == SkPaint::kNo_Hinting) {
35022253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner        fGridFitMode = DWRITE_GRID_FIT_MODE_DISABLED;
35122253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner        if (fRenderingMode != DWRITE_RENDERING_MODE_ALIASED) {
35222253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner            fRenderingMode = DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC;
35322253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner        }
35422253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner    }
35522253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner
356d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com    if (this->isSubpixel()) {
357058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com        fTextSizeMeasure = realTextSize;
358d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com        fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL;
359d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com    }
360e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com}
361e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com
36230ddd615c447fed73286151b463af20d309c85f1reed@google.comSkScalerContext_DW::~SkScalerContext_DW() {
363e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com}
364e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com
36530ddd615c447fed73286151b463af20d309c85f1reed@google.comunsigned SkScalerContext_DW::generateGlyphCount() {
366e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    if (fGlyphCount < 0) {
3677cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman        fGlyphCount = this->getDWriteTypeface()->fDWriteFontFace->GetGlyphCount();
368e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    }
369e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    return fGlyphCount;
370e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com}
371e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com
37230ddd615c447fed73286151b463af20d309c85f1reed@google.comuint16_t SkScalerContext_DW::generateCharToGlyph(SkUnichar uni) {
373e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    uint16_t index = 0;
3747cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman    UINT32* uniPtr = reinterpret_cast<UINT32*>(&uni);
3757cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman    this->getDWriteTypeface()->fDWriteFontFace->GetGlyphIndices(uniPtr, 1, &index);
376e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    return index;
377e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com}
378e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com
37930ddd615c447fed73286151b463af20d309c85f1reed@google.comvoid SkScalerContext_DW::generateAdvance(SkGlyph* glyph) {
380e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    //Delta is the difference between the right/left side bearing metric
381e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    //and where the right/left side bearing ends up after hinting.
382e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    //DirectWrite does not provide this information.
383e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    glyph->fRsbDelta = 0;
384e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    glyph->fLsbDelta = 0;
385d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
386e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    glyph->fAdvanceX = 0;
387e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    glyph->fAdvanceY = 0;
388e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com
389e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    uint16_t glyphId = glyph->getGlyphID();
390e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    DWRITE_GLYPH_METRICS gm;
391d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com
392d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com    if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode ||
393d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com        DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode)
394d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com    {
395f10637f2795b147751ef413237389d230b869360mtklein        SkAutoExclusive l(DWriteFactoryMutex);
3967cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman        HRVM(this->getDWriteTypeface()->fDWriteFontFace->GetGdiCompatibleGlyphMetrics(
397058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com                 fTextSizeMeasure,
398d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com                 1.0f, // pixelsPerDip
3991f5f6b823d32b1f85589e0cf81f8e7b91e89c1f2Ben Wagner                 // This parameter does not act like the lpmat2 parameter to GetGlyphOutlineW.
4001f5f6b823d32b1f85589e0cf81f8e7b91e89c1f2Ben Wagner                 // If it did then GsA here and G_inv below to mapVectors.
4011f5f6b823d32b1f85589e0cf81f8e7b91e89c1f2Ben Wagner                 nullptr,
402d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com                 DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode,
403d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com                 &glyphId, 1,
404d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com                 &gm),
405d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com             "Could not get gdi compatible glyph metrics.");
406d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com    } else {
407f10637f2795b147751ef413237389d230b869360mtklein        SkAutoExclusive l(DWriteFactoryMutex);
4087cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman        HRVM(this->getDWriteTypeface()->fDWriteFontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm),
409d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com             "Could not get design metrics.");
410d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com    }
411e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com
412e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    DWRITE_FONT_METRICS dwfm;
413c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb    {
4146440f0b09ede274f93131eebb3ef49e73dfb2b9cherb        Shared l(DWriteFactoryMutex);
4157cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman        this->getDWriteTypeface()->fDWriteFontFace->GetMetrics(&dwfm);
416c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb    }
4178be952ad8c9deefe19cff36f9ad217563400f817Mike Reed    SkScalar advanceX = fTextSizeMeasure * gm.advanceWidth / dwfm.designUnitsPerEm;
418d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
4191f5f6b823d32b1f85589e0cf81f8e7b91e89c1f2Ben Wagner    SkVector advance = { advanceX, 0 };
420058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com    if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode ||
421058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com        DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode)
422058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com    {
423761b2509d59787a8920b2e98911cff9f88e0eb4ebungeman        // DirectWrite produced 'compatible' metrics, but while close,
424761b2509d59787a8920b2e98911cff9f88e0eb4ebungeman        // the end result is not always an integer as it would be with GDI.
4251f5f6b823d32b1f85589e0cf81f8e7b91e89c1f2Ben Wagner        advance.fX = SkScalarRoundToScalar(advance.fX);
426058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com    }
4271f5f6b823d32b1f85589e0cf81f8e7b91e89c1f2Ben Wagner    fSkXform.mapVectors(&advance, 1);
428e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com
4291f5f6b823d32b1f85589e0cf81f8e7b91e89c1f2Ben Wagner    glyph->fAdvanceX = SkScalarToFloat(advance.fX);
4301f5f6b823d32b1f85589e0cf81f8e7b91e89c1f2Ben Wagner    glyph->fAdvanceY = SkScalarToFloat(advance.fY);
431e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com}
432e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com
433683a37692bc67ef1144922b73a1e871e7e1e842ebungemanHRESULT SkScalerContext_DW::getBoundingBox(SkGlyph* glyph,
434683a37692bc67ef1144922b73a1e871e7e1e842ebungeman                                           DWRITE_RENDERING_MODE renderingMode,
435683a37692bc67ef1144922b73a1e871e7e1e842ebungeman                                           DWRITE_TEXTURE_TYPE textureType,
436683a37692bc67ef1144922b73a1e871e7e1e842ebungeman                                           RECT* bbox)
437b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner{
438e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    //Measure raster size.
439e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    fXform.dx = SkFixedToFloat(glyph->getSubXFixed());
440e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    fXform.dy = SkFixedToFloat(glyph->getSubYFixed());
441e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com
442e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    FLOAT advance = 0;
443e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com
444e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    UINT16 glyphId = glyph->getGlyphID();
445e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com
446e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    DWRITE_GLYPH_OFFSET offset;
447e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    offset.advanceOffset = 0.0f;
448e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    offset.ascenderOffset = 0.0f;
449e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com
450e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    DWRITE_GLYPH_RUN run;
451e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    run.glyphCount = 1;
452e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    run.glyphAdvances = &advance;
4537cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman    run.fontFace = this->getDWriteTypeface()->fDWriteFontFace.get();
454058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com    run.fontEmSize = SkScalarToFloat(fTextSizeRender);
455e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    run.bidiLevel = 0;
456e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    run.glyphIndices = &glyphId;
457e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    run.isSideways = FALSE;
458e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    run.glyphOffsets = &offset;
4596440f0b09ede274f93131eebb3ef49e73dfb2b9cherb
4606440f0b09ede274f93131eebb3ef49e73dfb2b9cherb    SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
461c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb    {
462f10637f2795b147751ef413237389d230b869360mtklein        SkAutoExclusive l(DWriteFactoryMutex);
46322253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner        // IDWriteFactory2::CreateGlyphRunAnalysis is very bad at aliased glyphs.
46422253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner        if (this->getDWriteTypeface()->fFactory2 &&
46522253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                (fGridFitMode == DWRITE_GRID_FIT_MODE_DISABLED ||
46622253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                 fAntiAliasMode == DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE))
46722253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner        {
46822253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner            HRM(this->getDWriteTypeface()->fFactory2->CreateGlyphRunAnalysis(
46922253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                    &run,
47022253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                    &fXform,
47122253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                    renderingMode,
47222253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                    fMeasuringMode,
47322253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                    fGridFitMode,
47422253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                    fAntiAliasMode,
47522253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                    0.0f, // baselineOriginX,
47622253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                    0.0f, // baselineOriginY,
47722253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                    &glyphRunAnalysis),
47822253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                "Could not create DW2 glyph run analysis.");
47922253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner        } else {
48022253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner            HRM(this->getDWriteTypeface()->fFactory->CreateGlyphRunAnalysis(&run,
48122253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                    1.0f, // pixelsPerDip,
48222253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                    &fXform,
48322253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                    renderingMode,
48422253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                    fMeasuringMode,
48522253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                    0.0f, // baselineOriginX,
48622253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                    0.0f, // baselineOriginY,
48722253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                    &glyphRunAnalysis),
48822253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                "Could not create glyph run analysis.");
48922253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner        }
4906440f0b09ede274f93131eebb3ef49e73dfb2b9cherb    }
4916440f0b09ede274f93131eebb3ef49e73dfb2b9cherb    {
4926440f0b09ede274f93131eebb3ef49e73dfb2b9cherb        Shared l(DWriteFactoryMutex);
493c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb        HRM(glyphRunAnalysis->GetAlphaTextureBounds(textureType, bbox),
494c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb            "Could not get texture bounds.");
495c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb    }
496683a37692bc67ef1144922b73a1e871e7e1e842ebungeman    return S_OK;
497683a37692bc67ef1144922b73a1e871e7e1e842ebungeman}
498683a37692bc67ef1144922b73a1e871e7e1e842ebungeman
499683a37692bc67ef1144922b73a1e871e7e1e842ebungeman/** GetAlphaTextureBounds succeeds but sometimes returns empty bounds like
500683a37692bc67ef1144922b73a1e871e7e1e842ebungeman *  { 0x80000000, 0x80000000, 0x80000000, 0x80000000 }
501683a37692bc67ef1144922b73a1e871e7e1e842ebungeman *  for small, but not quite zero, sized glyphs.
502683a37692bc67ef1144922b73a1e871e7e1e842ebungeman *  Only set as non-empty if the returned bounds are non-empty.
503683a37692bc67ef1144922b73a1e871e7e1e842ebungeman */
504683a37692bc67ef1144922b73a1e871e7e1e842ebungemanstatic bool glyph_check_and_set_bounds(SkGlyph* glyph, const RECT& bbox) {
505683a37692bc67ef1144922b73a1e871e7e1e842ebungeman    if (bbox.left >= bbox.right || bbox.top >= bbox.bottom) {
506683a37692bc67ef1144922b73a1e871e7e1e842ebungeman        return false;
507683a37692bc67ef1144922b73a1e871e7e1e842ebungeman    }
508d94e00c985dedccb4b8870de1a822fe75dc1edb1Mike Klein
509d94e00c985dedccb4b8870de1a822fe75dc1edb1Mike Klein    // We're trying to pack left and top into int16_t,
510d94e00c985dedccb4b8870de1a822fe75dc1edb1Mike Klein    // and width and height into uint16_t, after outsetting by 1.
511d94e00c985dedccb4b8870de1a822fe75dc1edb1Mike Klein    if (!SkIRect::MakeXYWH(-32767, -32767, 65535, 65535).contains(
512d94e00c985dedccb4b8870de1a822fe75dc1edb1Mike Klein                SkIRect::MakeLTRB(bbox.left, bbox.top, bbox.right, bbox.bottom))) {
513d94e00c985dedccb4b8870de1a822fe75dc1edb1Mike Klein        return false;
514d94e00c985dedccb4b8870de1a822fe75dc1edb1Mike Klein    }
515d94e00c985dedccb4b8870de1a822fe75dc1edb1Mike Klein
516683a37692bc67ef1144922b73a1e871e7e1e842ebungeman    glyph->fWidth = SkToU16(bbox.right - bbox.left);
517683a37692bc67ef1144922b73a1e871e7e1e842ebungeman    glyph->fHeight = SkToU16(bbox.bottom - bbox.top);
518683a37692bc67ef1144922b73a1e871e7e1e842ebungeman    glyph->fLeft = SkToS16(bbox.left);
519683a37692bc67ef1144922b73a1e871e7e1e842ebungeman    glyph->fTop = SkToS16(bbox.top);
520683a37692bc67ef1144922b73a1e871e7e1e842ebungeman    return true;
521b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner}
522b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner
523c4b091543b4082fd1a2f356ef3b478073c5f9418kulshinbool SkScalerContext_DW::isColorGlyph(const SkGlyph& glyph) {
524c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    SkTScopedComPtr<IDWriteColorGlyphRunEnumerator> colorLayer;
525e0c9e00cd5ed17a45a988b8b57fa9c09f3574921Ben Wagner    return getColorGlyphRun(glyph, &colorLayer);
526c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin}
527c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin
528c4b091543b4082fd1a2f356ef3b478073c5f9418kulshinbool SkScalerContext_DW::getColorGlyphRun(const SkGlyph& glyph,
529c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin                                          IDWriteColorGlyphRunEnumerator** colorGlyph)
530c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin{
531c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    FLOAT advance = 0;
532c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    UINT16 glyphId = glyph.getGlyphID();
533c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin
534c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    DWRITE_GLYPH_OFFSET offset;
535c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    offset.advanceOffset = 0.0f;
536c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    offset.ascenderOffset = 0.0f;
537c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin
538c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    DWRITE_GLYPH_RUN run;
539c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    run.glyphCount = 1;
540c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    run.glyphAdvances = &advance;
5417cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman    run.fontFace = this->getDWriteTypeface()->fDWriteFontFace.get();
542c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    run.fontEmSize = SkScalarToFloat(fTextSizeRender);
543c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    run.bidiLevel = 0;
544c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    run.glyphIndices = &glyphId;
545c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    run.isSideways = FALSE;
546c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    run.glyphOffsets = &offset;
547c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin
54822253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner    HRESULT hr = this->getDWriteTypeface()->fFactory2->TranslateColorGlyphRun(
549c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin        0, 0, &run, nullptr, fMeasuringMode, &fXform, 0, colorGlyph);
550c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    if (hr == DWRITE_E_NOCOLOR) {
551c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin        return false;
552c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    }
553c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    HRBM(hr, "Failed to translate color glyph run");
554c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    return true;
555c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin}
556c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin
557b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagnervoid SkScalerContext_DW::generateMetrics(SkGlyph* glyph) {
558b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner    glyph->fWidth = 0;
559683a37692bc67ef1144922b73a1e871e7e1e842ebungeman    glyph->fHeight = 0;
560683a37692bc67ef1144922b73a1e871e7e1e842ebungeman    glyph->fLeft = 0;
561683a37692bc67ef1144922b73a1e871e7e1e842ebungeman    glyph->fTop = 0;
562b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner
563b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner    this->generateAdvance(glyph);
564b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner
565c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    if (fIsColorFont && isColorGlyph(*glyph)) {
566c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin        glyph->fMaskFormat = SkMask::kARGB32_Format;
567c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    }
568c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin
569b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner    RECT bbox;
570683a37692bc67ef1144922b73a1e871e7e1e842ebungeman    HRVM(this->getBoundingBox(glyph, fRenderingMode, fTextureType, &bbox),
571683a37692bc67ef1144922b73a1e871e7e1e842ebungeman         "Requested bounding box could not be determined.");
572683a37692bc67ef1144922b73a1e871e7e1e842ebungeman
573683a37692bc67ef1144922b73a1e871e7e1e842ebungeman    if (glyph_check_and_set_bounds(glyph, bbox)) {
574683a37692bc67ef1144922b73a1e871e7e1e842ebungeman        return;
575683a37692bc67ef1144922b73a1e871e7e1e842ebungeman    }
576b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner
577b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner    // GetAlphaTextureBounds succeeds but returns an empty RECT if there are no
578b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner    // glyphs of the specified texture type. When this happens, try with the
579b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner    // alternate texture type.
580683a37692bc67ef1144922b73a1e871e7e1e842ebungeman    if (DWRITE_TEXTURE_CLEARTYPE_3x1 == fTextureType) {
581683a37692bc67ef1144922b73a1e871e7e1e842ebungeman        HRVM(this->getBoundingBox(glyph,
582683a37692bc67ef1144922b73a1e871e7e1e842ebungeman                                  DWRITE_RENDERING_MODE_ALIASED,
583683a37692bc67ef1144922b73a1e871e7e1e842ebungeman                                  DWRITE_TEXTURE_ALIASED_1x1,
584683a37692bc67ef1144922b73a1e871e7e1e842ebungeman                                  &bbox),
585683a37692bc67ef1144922b73a1e871e7e1e842ebungeman             "Fallback bounding box could not be determined.");
586683a37692bc67ef1144922b73a1e871e7e1e842ebungeman        if (glyph_check_and_set_bounds(glyph, bbox)) {
587683a37692bc67ef1144922b73a1e871e7e1e842ebungeman            glyph->fForceBW = 1;
588b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner        }
589b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner    }
590683a37692bc67ef1144922b73a1e871e7e1e842ebungeman    // TODO: handle the case where a request for DWRITE_TEXTURE_ALIASED_1x1
591683a37692bc67ef1144922b73a1e871e7e1e842ebungeman    // fails, and try DWRITE_TEXTURE_CLEARTYPE_3x1.
592e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com}
593e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com
594410780677af260e32948b02c0725ef6ad761260cbungemanvoid SkScalerContext_DW::generateFontMetrics(SkPaint::FontMetrics* metrics) {
59596fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == metrics) {
596f73c237291bb1fc698f688d8a9b1cdd23838ed18bungeman        return;
597e1b9bad0711e557e45fee109fb492d19e35e1d38bungeman@google.com    }
598e1b9bad0711e557e45fee109fb492d19e35e1d38bungeman@google.com
599410780677af260e32948b02c0725ef6ad761260cbungeman    sk_bzero(metrics, sizeof(*metrics));
600410780677af260e32948b02c0725ef6ad761260cbungeman
601e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    DWRITE_FONT_METRICS dwfm;
602d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com    if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode ||
603d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com        DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode)
604d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com    {
6057cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman        this->getDWriteTypeface()->fDWriteFontFace->GetGdiCompatibleMetrics(
606058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com             fTextSizeRender,
607d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com             1.0f, // pixelsPerDip
608d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com             &fXform,
609d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com             &dwfm);
610d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com    } else {
6117cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman        this->getDWriteTypeface()->fDWriteFontFace->GetMetrics(&dwfm);
612d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com    }
613e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com
614e1b9bad0711e557e45fee109fb492d19e35e1d38bungeman@google.com    SkScalar upem = SkIntToScalar(dwfm.designUnitsPerEm);
615e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com
616f73c237291bb1fc698f688d8a9b1cdd23838ed18bungeman    metrics->fAscent = -fTextSizeRender * SkIntToScalar(dwfm.ascent) / upem;
617410780677af260e32948b02c0725ef6ad761260cbungeman    metrics->fDescent = fTextSizeRender * SkIntToScalar(dwfm.descent) / upem;
618410780677af260e32948b02c0725ef6ad761260cbungeman    metrics->fLeading = fTextSizeRender * SkIntToScalar(dwfm.lineGap) / upem;
619410780677af260e32948b02c0725ef6ad761260cbungeman    metrics->fXHeight = fTextSizeRender * SkIntToScalar(dwfm.xHeight) / upem;
620a6725fcb14f63734d7668bb0550cd9c128e841b0Koji Ishii    metrics->fCapHeight = fTextSizeRender * SkIntToScalar(dwfm.capHeight) / upem;
621410780677af260e32948b02c0725ef6ad761260cbungeman    metrics->fUnderlineThickness = fTextSizeRender * SkIntToScalar(dwfm.underlineThickness) / upem;
622410780677af260e32948b02c0725ef6ad761260cbungeman    metrics->fUnderlinePosition = -(fTextSizeRender * SkIntToScalar(dwfm.underlinePosition) / upem);
623219f3622ba32a1cb6380212a2ec1947513fbfeb9Ben Wagner    metrics->fStrikeoutThickness = fTextSizeRender * SkIntToScalar(dwfm.strikethroughThickness) / upem;
624219f3622ba32a1cb6380212a2ec1947513fbfeb9Ben Wagner    metrics->fStrikeoutPosition = -(fTextSizeRender * SkIntToScalar(dwfm.strikethroughPosition) / upem);
625410780677af260e32948b02c0725ef6ad761260cbungeman
6263318da5d1aa19533dd034f90d4bc29a2d2e86b66Ben Wagner    metrics->fFlags |= SkPaint::FontMetrics::kUnderlineThicknessIsValid_Flag;
627410780677af260e32948b02c0725ef6ad761260cbungeman    metrics->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
628219f3622ba32a1cb6380212a2ec1947513fbfeb9Ben Wagner    metrics->fFlags |= SkPaint::FontMetrics::kStrikeoutThicknessIsValid_Flag;
629219f3622ba32a1cb6380212a2ec1947513fbfeb9Ben Wagner    metrics->fFlags |= SkPaint::FontMetrics::kStrikeoutPositionIsValid_Flag;
630f73c237291bb1fc698f688d8a9b1cdd23838ed18bungeman
6317cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman    if (this->getDWriteTypeface()->fDWriteFontFace1.get()) {
632f73c237291bb1fc698f688d8a9b1cdd23838ed18bungeman        DWRITE_FONT_METRICS1 dwfm1;
6337cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman        this->getDWriteTypeface()->fDWriteFontFace1->GetMetrics(&dwfm1);
634f73c237291bb1fc698f688d8a9b1cdd23838ed18bungeman        metrics->fTop = -fTextSizeRender * SkIntToScalar(dwfm1.glyphBoxTop) / upem;
635f73c237291bb1fc698f688d8a9b1cdd23838ed18bungeman        metrics->fBottom = -fTextSizeRender * SkIntToScalar(dwfm1.glyphBoxBottom) / upem;
636f73c237291bb1fc698f688d8a9b1cdd23838ed18bungeman        metrics->fXMin = fTextSizeRender * SkIntToScalar(dwfm1.glyphBoxLeft) / upem;
637f73c237291bb1fc698f688d8a9b1cdd23838ed18bungeman        metrics->fXMax = fTextSizeRender * SkIntToScalar(dwfm1.glyphBoxRight) / upem;
638f73c237291bb1fc698f688d8a9b1cdd23838ed18bungeman
639f73c237291bb1fc698f688d8a9b1cdd23838ed18bungeman        metrics->fMaxCharWidth = metrics->fXMax - metrics->fXMin;
640f548444684b9c96f7717aebe645944af4f95d650bungeman        return;
641f548444684b9c96f7717aebe645944af4f95d650bungeman    }
642f548444684b9c96f7717aebe645944af4f95d650bungeman
6437cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman    AutoTDWriteTable<SkOTTableHead> head(this->getDWriteTypeface()->fDWriteFontFace.get());
644f548444684b9c96f7717aebe645944af4f95d650bungeman    if (head.fExists &&
645f548444684b9c96f7717aebe645944af4f95d650bungeman        head.fSize >= sizeof(SkOTTableHead) &&
646f548444684b9c96f7717aebe645944af4f95d650bungeman        head->version == SkOTTableHead::version1)
647f548444684b9c96f7717aebe645944af4f95d650bungeman    {
648f548444684b9c96f7717aebe645944af4f95d650bungeman        metrics->fTop = -fTextSizeRender * (int16_t)SkEndian_SwapBE16(head->yMax) / upem;
649f548444684b9c96f7717aebe645944af4f95d650bungeman        metrics->fBottom = -fTextSizeRender * (int16_t)SkEndian_SwapBE16(head->yMin) / upem;
650f548444684b9c96f7717aebe645944af4f95d650bungeman        metrics->fXMin = fTextSizeRender * (int16_t)SkEndian_SwapBE16(head->xMin) / upem;
651f548444684b9c96f7717aebe645944af4f95d650bungeman        metrics->fXMax = fTextSizeRender * (int16_t)SkEndian_SwapBE16(head->xMax) / upem;
652f548444684b9c96f7717aebe645944af4f95d650bungeman
653f548444684b9c96f7717aebe645944af4f95d650bungeman        metrics->fMaxCharWidth = metrics->fXMax - metrics->fXMin;
654f548444684b9c96f7717aebe645944af4f95d650bungeman        return;
655f73c237291bb1fc698f688d8a9b1cdd23838ed18bungeman    }
656f548444684b9c96f7717aebe645944af4f95d650bungeman
657f548444684b9c96f7717aebe645944af4f95d650bungeman    metrics->fTop = metrics->fAscent;
658f548444684b9c96f7717aebe645944af4f95d650bungeman    metrics->fBottom = metrics->fDescent;
659e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com}
660e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com
661e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com///////////////////////////////////////////////////////////////////////////////
662e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com
663a4083c97d48e8a4f88e2797d7363f141e3d42553Cary Clark#include "SkColorData.h"
664e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com
665e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.comstatic void bilevel_to_bw(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph) {
666e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    const int width = glyph.fWidth;
667e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    const size_t dstRB = (width + 7) >> 3;
668e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage);
669e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com
670e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    int byteCount = width >> 3;
671e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    int bitCount = width & 7;
672e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com
673e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    for (int y = 0; y < glyph.fHeight; ++y) {
674e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com        if (byteCount > 0) {
675e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com            for (int i = 0; i < byteCount; ++i) {
676e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com                unsigned byte = 0;
677e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com                byte |= src[0] & (1 << 7);
678e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com                byte |= src[1] & (1 << 6);
679e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com                byte |= src[2] & (1 << 5);
680e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com                byte |= src[3] & (1 << 4);
681e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com                byte |= src[4] & (1 << 3);
682e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com                byte |= src[5] & (1 << 2);
683e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com                byte |= src[6] & (1 << 1);
684e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com                byte |= src[7] & (1 << 0);
685e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com                dst[i] = byte;
686e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com                src += 8;
687e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com            }
688e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com        }
689e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com        if (bitCount > 0) {
690e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com            unsigned byte = 0;
691e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com            unsigned mask = 0x80;
692e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com            for (int i = 0; i < bitCount; i++) {
693e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com                byte |= (src[i]) & mask;
694e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com                mask >>= 1;
695e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com            }
696e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com            dst[byteCount] = byte;
697e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com        }
698e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com        src += bitCount;
699e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com        dst += dstRB;
700e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    }
701e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com}
702e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com
703e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.comtemplate<bool APPLY_PREBLEND>
70422253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagnerstatic void grayscale_to_a8(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph,
70522253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                            const uint8_t* table8) {
70622253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner    const size_t dstRB = glyph.rowBytes();
70722253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner    const U16CPU width = glyph.fWidth;
70822253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner    uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage);
70922253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner
71022253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner    for (U16CPU y = 0; y < glyph.fHeight; y++) {
71122253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner        for (U16CPU i = 0; i < width; i++) {
71222253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner            U8CPU a = *(src++);
71322253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner            dst[i] = sk_apply_lut_if<APPLY_PREBLEND>(a, table8);
71422253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner        }
71522253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner        dst = SkTAddOffset<uint8_t>(dst, dstRB);
71622253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner    }
71722253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner}
71822253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner
71922253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagnertemplate<bool APPLY_PREBLEND>
720e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.comstatic void rgb_to_a8(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph, const uint8_t* table8) {
721e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    const size_t dstRB = glyph.rowBytes();
722e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    const U16CPU width = glyph.fWidth;
723e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage);
724e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com
725e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    for (U16CPU y = 0; y < glyph.fHeight; y++) {
726e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com        for (U16CPU i = 0; i < width; i++) {
727e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com            U8CPU r = *(src++);
728e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com            U8CPU g = *(src++);
729e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com            U8CPU b = *(src++);
730e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com            dst[i] = sk_apply_lut_if<APPLY_PREBLEND>((r + g + b) / 3, table8);
731e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com        }
73222253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner        dst = SkTAddOffset<uint8_t>(dst, dstRB);
733e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    }
734e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com}
735e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com
73612f03121bb76214b71677ac0208d74c3c56c3b1fbungemantemplate<bool APPLY_PREBLEND, bool RGB>
737e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.comstatic void rgb_to_lcd16(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph,
738e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com                         const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
739e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    const size_t dstRB = glyph.rowBytes();
740e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    const U16CPU width = glyph.fWidth;
741e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    uint16_t* SK_RESTRICT dst = static_cast<uint16_t*>(glyph.fImage);
742e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com
743e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    for (U16CPU y = 0; y < glyph.fHeight; y++) {
744e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com        for (U16CPU i = 0; i < width; i++) {
74512f03121bb76214b71677ac0208d74c3c56c3b1fbungeman            U8CPU r, g, b;
74612f03121bb76214b71677ac0208d74c3c56c3b1fbungeman            if (RGB) {
74712f03121bb76214b71677ac0208d74c3c56c3b1fbungeman                r = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableR);
74812f03121bb76214b71677ac0208d74c3c56c3b1fbungeman                g = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableG);
74912f03121bb76214b71677ac0208d74c3c56c3b1fbungeman                b = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableB);
75012f03121bb76214b71677ac0208d74c3c56c3b1fbungeman            } else {
75112f03121bb76214b71677ac0208d74c3c56c3b1fbungeman                b = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableB);
75212f03121bb76214b71677ac0208d74c3c56c3b1fbungeman                g = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableG);
75312f03121bb76214b71677ac0208d74c3c56c3b1fbungeman                r = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableR);
75412f03121bb76214b71677ac0208d74c3c56c3b1fbungeman            }
755e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com            dst[i] = SkPack888ToRGB16(r, g, b);
756e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com        }
75722253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner        dst = SkTAddOffset<uint16_t>(dst, dstRB);
758e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    }
759e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com}
760e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com
761b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagnerconst void* SkScalerContext_DW::drawDWMask(const SkGlyph& glyph,
762b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner                                           DWRITE_RENDERING_MODE renderingMode,
763b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner                                           DWRITE_TEXTURE_TYPE textureType)
764b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner{
765d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com    int sizeNeeded = glyph.fWidth * glyph.fHeight;
76622253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner    if (DWRITE_TEXTURE_CLEARTYPE_3x1 == textureType) {
767d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com        sizeNeeded *= 3;
768d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com    }
769d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com    if (sizeNeeded > fBits.count()) {
770d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com        fBits.setCount(sizeNeeded);
771d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com    }
772d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com
773d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com    // erase
774d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com    memset(fBits.begin(), 0, sizeNeeded);
775d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com
776d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com    fXform.dx = SkFixedToFloat(glyph.getSubXFixed());
777d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com    fXform.dy = SkFixedToFloat(glyph.getSubYFixed());
778d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com
779d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com    FLOAT advance = 0.0f;
780d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com
781d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com    UINT16 index = glyph.getGlyphID();
782d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com
783d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com    DWRITE_GLYPH_OFFSET offset;
784d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com    offset.advanceOffset = 0.0f;
785d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com    offset.ascenderOffset = 0.0f;
786e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com
787d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com    DWRITE_GLYPH_RUN run;
788d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com    run.glyphCount = 1;
789d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com    run.glyphAdvances = &advance;
7907cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman    run.fontFace = this->getDWriteTypeface()->fDWriteFontFace.get();
791058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com    run.fontEmSize = SkScalarToFloat(fTextSizeRender);
792d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com    run.bidiLevel = 0;
793d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com    run.glyphIndices = &index;
794d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com    run.isSideways = FALSE;
795d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com    run.glyphOffsets = &offset;
796c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb    {
7976440f0b09ede274f93131eebb3ef49e73dfb2b9cherb        SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
7986440f0b09ede274f93131eebb3ef49e73dfb2b9cherb        {
799f10637f2795b147751ef413237389d230b869360mtklein            SkAutoExclusive l(DWriteFactoryMutex);
80022253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner            // IDWriteFactory2::CreateGlyphRunAnalysis is very bad at aliased glyphs.
80122253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner            if (this->getDWriteTypeface()->fFactory2 &&
80222253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                    (fGridFitMode == DWRITE_GRID_FIT_MODE_DISABLED ||
80322253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                     fAntiAliasMode == DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE))
80422253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner            {
80522253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                HRNM(this->getDWriteTypeface()->fFactory2->CreateGlyphRunAnalysis(&run,
80622253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                         &fXform,
80722253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                         renderingMode,
80822253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                         fMeasuringMode,
80922253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                         fGridFitMode,
81022253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                         fAntiAliasMode,
81122253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                         0.0f, // baselineOriginX,
81222253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                         0.0f, // baselineOriginY,
81322253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                         &glyphRunAnalysis),
81422253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                     "Could not create DW2 glyph run analysis.");
81522253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner            } else {
81622253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                HRNM(this->getDWriteTypeface()->fFactory->CreateGlyphRunAnalysis(&run,
81722253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                         1.0f, // pixelsPerDip,
81822253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                         &fXform,
81922253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                         renderingMode,
82022253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                         fMeasuringMode,
82122253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                         0.0f, // baselineOriginX,
82222253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                         0.0f, // baselineOriginY,
82322253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                         &glyphRunAnalysis),
82422253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                     "Could not create glyph run analysis.");
82522253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner            }
8266440f0b09ede274f93131eebb3ef49e73dfb2b9cherb        }
827c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb        //NOTE: this assumes that the glyph has already been measured
828c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb        //with an exact same glyph run analysis.
829c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb        RECT bbox;
830c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb        bbox.left = glyph.fLeft;
831c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb        bbox.top = glyph.fTop;
832c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb        bbox.right = glyph.fLeft + glyph.fWidth;
833c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb        bbox.bottom = glyph.fTop + glyph.fHeight;
8346440f0b09ede274f93131eebb3ef49e73dfb2b9cherb        {
8356440f0b09ede274f93131eebb3ef49e73dfb2b9cherb            Shared l(DWriteFactoryMutex);
8366440f0b09ede274f93131eebb3ef49e73dfb2b9cherb            HRNM(glyphRunAnalysis->CreateAlphaTexture(textureType,
83722253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                    &bbox,
83822253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                    fBits.begin(),
83922253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                    sizeNeeded),
8406440f0b09ede274f93131eebb3ef49e73dfb2b9cherb                "Could not draw mask.");
8416440f0b09ede274f93131eebb3ef49e73dfb2b9cherb        }
842c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb    }
843d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com    return fBits.begin();
844d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com}
845d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com
846c4b091543b4082fd1a2f356ef3b478073c5f9418kulshinvoid SkScalerContext_DW::generateColorGlyphImage(const SkGlyph& glyph) {
847c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    SkASSERT(isColorGlyph(glyph));
848c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    SkASSERT(glyph.fMaskFormat == SkMask::Format::kARGB32_Format);
849c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin
850c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    memset(glyph.fImage, 0, glyph.computeImageSize());
851c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin
852c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    SkTScopedComPtr<IDWriteColorGlyphRunEnumerator> colorLayers;
853c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    getColorGlyphRun(glyph, &colorLayers);
854c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    SkASSERT(colorLayers.get());
855c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin
856c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    SkMatrix matrix = fSkXform;
857c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    matrix.postTranslate(-SkIntToScalar(glyph.fLeft), -SkIntToScalar(glyph.fTop));
858c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    SkRasterClip rc(SkIRect::MakeWH(glyph.fWidth, glyph.fHeight));
859c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    SkDraw draw;
860c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    draw.fDst = SkPixmap(SkImageInfo::MakeN32(glyph.fWidth, glyph.fHeight, kPremul_SkAlphaType),
861c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin                         glyph.fImage,
862c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin                         glyph.ComputeRowBytes(glyph.fWidth, SkMask::Format::kARGB32_Format));
863c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    draw.fMatrix = &matrix;
864c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    draw.fRC = &rc;
865c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin
866c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    SkPaint paint;
867c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    if (fRenderingMode != DWRITE_RENDERING_MODE_ALIASED) {
868c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin        paint.setFlags(SkPaint::Flags::kAntiAlias_Flag);
869c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    }
870c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin
871c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    BOOL hasNextRun = FALSE;
872c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    while (SUCCEEDED(colorLayers->MoveNext(&hasNextRun)) && hasNextRun) {
873c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin        const DWRITE_COLOR_GLYPH_RUN* colorGlyph;
874c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin        HRVM(colorLayers->GetCurrentRun(&colorGlyph), "Could not get current color glyph run");
875c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin
876c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin        SkColor color;
877c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin        if (colorGlyph->paletteIndex != 0xffff) {
87835ee0e09b4966bd087147e2c9b4c3177e9737d3bMike Reed            color = SkColorSetARGB(sk_float_round2int(colorGlyph->runColor.a * 255),
87935ee0e09b4966bd087147e2c9b4c3177e9737d3bMike Reed                                   sk_float_round2int(colorGlyph->runColor.r * 255),
88035ee0e09b4966bd087147e2c9b4c3177e9737d3bMike Reed                                   sk_float_round2int(colorGlyph->runColor.g * 255),
88135ee0e09b4966bd087147e2c9b4c3177e9737d3bMike Reed                                   sk_float_round2int(colorGlyph->runColor.b * 255));
882c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin        } else {
883c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin            // If all components of runColor are 0 or (equivalently) paletteIndex is 0xFFFF then
884c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin            // the 'current brush' is used. fRec.getLuminanceColor() is kinda sorta what is wanted
885c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin            // here, but not really, it will often be the wrong value because it wan't designed for
886c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin            // this.
8875f544345d653900ef30212ea1c243947be8bb074bungeman            // TODO: implement this fully, bug.skia.org/5788
888c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin            color = fRec.getLuminanceColor();
889c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin        }
890c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin        paint.setColor(color);
891c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin
892c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin        SkPath path;
893c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin        SkTScopedComPtr<IDWriteGeometrySink> geometryToPath;
894c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin        HRVM(SkDWriteGeometrySink::Create(&path, &geometryToPath),
895c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin             "Could not create geometry to path converter.");
896c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin        {
897f10637f2795b147751ef413237389d230b869360mtklein            SkAutoExclusive l(DWriteFactoryMutex);
898c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin            HRVM(colorGlyph->glyphRun.fontFace->GetGlyphRunOutline(
899c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin                colorGlyph->glyphRun.fontEmSize,
900c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin                colorGlyph->glyphRun.glyphIndices,
901c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin                colorGlyph->glyphRun.glyphAdvances,
902c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin                colorGlyph->glyphRun.glyphOffsets,
903c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin                colorGlyph->glyphRun.glyphCount,
904c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin                colorGlyph->glyphRun.isSideways,
905c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin                colorGlyph->glyphRun.bidiLevel % 2, //rtl
906c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin                geometryToPath.get()),
907c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin                "Could not create glyph outline.");
908c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin        }
909c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin        draw.drawPath(path, paint, nullptr, true /* pathIsMutable */);
910c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    }
911c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin}
912c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin
913d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.comvoid SkScalerContext_DW::generateImage(const SkGlyph& glyph) {
914e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    //Create the mask.
915b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner    DWRITE_RENDERING_MODE renderingMode = fRenderingMode;
916b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner    DWRITE_TEXTURE_TYPE textureType = fTextureType;
917b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner    if (glyph.fForceBW) {
918b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner        renderingMode = DWRITE_RENDERING_MODE_ALIASED;
919b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner        textureType = DWRITE_TEXTURE_ALIASED_1x1;
920b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner    }
921c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin
922c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    if (SkMask::kARGB32_Format == glyph.fMaskFormat) {
923c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin        generateColorGlyphImage(glyph);
924c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin        return;
925c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin    }
926c4b091543b4082fd1a2f356ef3b478073c5f9418kulshin
927b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner    const void* bits = this->drawDWMask(glyph, renderingMode, textureType);
928e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    if (!bits) {
929e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com        sk_bzero(glyph.fImage, glyph.computeImageSize());
930e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com        return;
931e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    }
932e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com
933e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    //Copy the mask into the glyph.
934e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    const uint8_t* src = (const uint8_t*)bits;
935b2f7fce9e034c3b6749e75a129e7836df3529706Ben Wagner    if (DWRITE_RENDERING_MODE_ALIASED == renderingMode) {
936e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com        bilevel_to_bw(src, glyph);
937d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com        const_cast<SkGlyph&>(glyph).fMaskFormat = SkMask::kBW_Format;
938d715aaa33fc52d36f566caf941787a2cca24d85bbungeman@google.com    } else if (!isLCD(fRec)) {
93922253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner        if (textureType == DWRITE_TEXTURE_ALIASED_1x1) {
94022253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner            if (fPreBlend.isApplicable()) {
94122253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                grayscale_to_a8<true>(src, glyph, fPreBlend.fG);
94222253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner            } else {
94322253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                grayscale_to_a8<false>(src, glyph, fPreBlend.fG);
94422253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner            }
945e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com        } else {
94622253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner            if (fPreBlend.isApplicable()) {
94722253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                rgb_to_a8<true>(src, glyph, fPreBlend.fG);
94822253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner            } else {
94922253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner                rgb_to_a8<false>(src, glyph, fPreBlend.fG);
95022253064ceee1dd9fcd26b7d6d69505cba76bb33Ben Wagner            }
951e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com        }
952d54d3fc82456f8789b3e4dff40faeb7b670bcf4breed    } else {
953d54d3fc82456f8789b3e4dff40faeb7b670bcf4breed        SkASSERT(SkMask::kLCD16_Format == glyph.fMaskFormat);
954a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com        if (fPreBlend.isApplicable()) {
95512f03121bb76214b71677ac0208d74c3c56c3b1fbungeman            if (fRec.fFlags & SkScalerContext::kLCD_BGROrder_Flag) {
95612f03121bb76214b71677ac0208d74c3c56c3b1fbungeman                rgb_to_lcd16<true, false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
95712f03121bb76214b71677ac0208d74c3c56c3b1fbungeman            } else {
95812f03121bb76214b71677ac0208d74c3c56c3b1fbungeman                rgb_to_lcd16<true, true>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
95912f03121bb76214b71677ac0208d74c3c56c3b1fbungeman            }
960e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com        } else {
96112f03121bb76214b71677ac0208d74c3c56c3b1fbungeman            if (fRec.fFlags & SkScalerContext::kLCD_BGROrder_Flag) {
96212f03121bb76214b71677ac0208d74c3c56c3b1fbungeman                rgb_to_lcd16<false, false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
96312f03121bb76214b71677ac0208d74c3c56c3b1fbungeman            } else {
96412f03121bb76214b71677ac0208d74c3c56c3b1fbungeman                rgb_to_lcd16<false, true>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
96512f03121bb76214b71677ac0208d74c3c56c3b1fbungeman            }
966e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com        }
967e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    }
968e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com}
969e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com
9706e9ac12495f3b64b6ea8860bb9f99c43cd33aa08Ben Wagnervoid SkScalerContext_DW::generatePath(SkGlyphID glyph, SkPath* path) {
9712f19b551ac10b96a1a35a147063cd4300d6fe07adcheng    SkASSERT(path);
972e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com
973e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    path->reset();
974e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com
975e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    SkTScopedComPtr<IDWriteGeometrySink> geometryToPath;
976e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com    HRVM(SkDWriteGeometrySink::Create(path, &geometryToPath),
977e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com         "Could not create geometry to path converter.");
9786e9ac12495f3b64b6ea8860bb9f99c43cd33aa08Ben Wagner    UINT16 glyphId = SkTo<UINT16>(glyph);
979c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb    {
980f10637f2795b147751ef413237389d230b869360mtklein        SkAutoExclusive l(DWriteFactoryMutex);
981c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb        //TODO: convert to<->from DIUs? This would make a difference if hinting.
982c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb        //It may not be needed, it appears that DirectWrite only hints at em size.
9837cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman        HRVM(this->getDWriteTypeface()->fDWriteFontFace->GetGlyphRunOutline(
9847cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman             SkScalarToFloat(fTextSizeRender),
9857cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman             &glyphId,
9867cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman             nullptr, //advances
9877cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman             nullptr, //offsets
9887cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman             1, //num glyphs
9897cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman             FALSE, //sideways
9907cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman             FALSE, //rtl
9917cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman             geometryToPath.get()),
9927cfd46aebda7b7d2b88e73621ed0d1be7244c2cabungeman             "Could not create glyph outline.");
993c7378af961cabef5b77c4dae40d8d3b9c1471a9eherb    }
994091f51b794e62942db47ccef6fef143ad1590d12bungeman@google.com
995058670b1e52910e61d9de294a46b5023ed6dd964bungeman@google.com    path->transform(fSkXform);
996e8f0592ae8b37e94d99f49816eb22e9fafde6d86bungeman@google.com}
9971ee76510f5dbf632d30975fc3509ef4f609156d2mtklein
9988f11d4dcafef4447fa68ea0ab28a72589241e9fdMike Klein#endif//defined(SK_BUILD_FOR_WIN)
999