xref: /aosp_15_r20/external/skia/gm/fontations_ft_compare.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2023 Google LLC
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "gm/gm.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBitmap.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorPriv.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkData.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFont.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFontTypes.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkStream.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSurface.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypeface.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/ports/SkTypeface_fontations.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skshaper/include/SkShaper.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "src/ports/SkTypeface_FreeType.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "tools/Resources.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "tools/TestFontDataProvider.h"
25*c8dee2aaSAndroid Build Coastguard Worker 
26*c8dee2aaSAndroid Build Coastguard Worker namespace skiagm {
27*c8dee2aaSAndroid Build Coastguard Worker 
28*c8dee2aaSAndroid Build Coastguard Worker namespace {
29*c8dee2aaSAndroid Build Coastguard Worker 
30*c8dee2aaSAndroid Build Coastguard Worker constexpr int kGmWidth = 1000;
31*c8dee2aaSAndroid Build Coastguard Worker constexpr int kMargin = 30;
32*c8dee2aaSAndroid Build Coastguard Worker constexpr float kFontSize = 24;
33*c8dee2aaSAndroid Build Coastguard Worker constexpr float kLangYIncrementScale = 1.9;
34*c8dee2aaSAndroid Build Coastguard Worker 
35*c8dee2aaSAndroid Build Coastguard Worker /** Compare bitmap A and B, in this case originating from text rendering results with FreeType and
36*c8dee2aaSAndroid Build Coastguard Worker  * Fontations + Skia path rendering, compute individual pixel differences for the rectangles that
37*c8dee2aaSAndroid Build Coastguard Worker  * must match in size. Produce a highlighted difference bitmap, in which any pixel becomes white for
38*c8dee2aaSAndroid Build Coastguard Worker  * which a difference was determined. */
comparePixels(const SkPixmap & pixmapA,const SkPixmap & pixmapB,SkBitmap * outPixelDiffBitmap,SkBitmap * outHighlightDiffBitmap)39*c8dee2aaSAndroid Build Coastguard Worker void comparePixels(const SkPixmap& pixmapA,
40*c8dee2aaSAndroid Build Coastguard Worker                    const SkPixmap& pixmapB,
41*c8dee2aaSAndroid Build Coastguard Worker                    SkBitmap* outPixelDiffBitmap,
42*c8dee2aaSAndroid Build Coastguard Worker                    SkBitmap* outHighlightDiffBitmap) {
43*c8dee2aaSAndroid Build Coastguard Worker     if (pixmapA.dimensions() != pixmapB.dimensions()) {
44*c8dee2aaSAndroid Build Coastguard Worker         return;
45*c8dee2aaSAndroid Build Coastguard Worker     }
46*c8dee2aaSAndroid Build Coastguard Worker     if (pixmapA.dimensions() != outPixelDiffBitmap->dimensions()) {
47*c8dee2aaSAndroid Build Coastguard Worker         return;
48*c8dee2aaSAndroid Build Coastguard Worker     }
49*c8dee2aaSAndroid Build Coastguard Worker 
50*c8dee2aaSAndroid Build Coastguard Worker     SkISize dimensions = pixmapA.dimensions();
51*c8dee2aaSAndroid Build Coastguard Worker     for (int32_t x = 0; x < dimensions.fWidth; x++) {
52*c8dee2aaSAndroid Build Coastguard Worker         for (int32_t y = 0; y < dimensions.fHeight; y++) {
53*c8dee2aaSAndroid Build Coastguard Worker             SkColor c0 = pixmapA.getColor(x, y);
54*c8dee2aaSAndroid Build Coastguard Worker             SkColor c1 = pixmapB.getColor(x, y);
55*c8dee2aaSAndroid Build Coastguard Worker             int dr = SkGetPackedR32(c0) - SkGetPackedR32(c1);
56*c8dee2aaSAndroid Build Coastguard Worker             int dg = SkGetPackedG32(c0) - SkGetPackedG32(c1);
57*c8dee2aaSAndroid Build Coastguard Worker             int db = SkGetPackedB32(c0) - SkGetPackedB32(c1);
58*c8dee2aaSAndroid Build Coastguard Worker 
59*c8dee2aaSAndroid Build Coastguard Worker             *(outPixelDiffBitmap->getAddr32(x, y)) =
60*c8dee2aaSAndroid Build Coastguard Worker                     SkPackARGB32(0xFF, SkAbs32(dr), SkAbs32(dg), SkAbs32(db));
61*c8dee2aaSAndroid Build Coastguard Worker 
62*c8dee2aaSAndroid Build Coastguard Worker             if (dr != 0 || dg != 0 || db != 0) {
63*c8dee2aaSAndroid Build Coastguard Worker                 *(outHighlightDiffBitmap->getAddr32(x, y)) = SK_ColorWHITE;
64*c8dee2aaSAndroid Build Coastguard Worker             } else {
65*c8dee2aaSAndroid Build Coastguard Worker                 *(outHighlightDiffBitmap->getAddr32(x, y)) = SK_ColorBLACK;
66*c8dee2aaSAndroid Build Coastguard Worker             }
67*c8dee2aaSAndroid Build Coastguard Worker         }
68*c8dee2aaSAndroid Build Coastguard Worker     }
69*c8dee2aaSAndroid Build Coastguard Worker }
70*c8dee2aaSAndroid Build Coastguard Worker 
71*c8dee2aaSAndroid Build Coastguard Worker }  // namespace
72*c8dee2aaSAndroid Build Coastguard Worker 
73*c8dee2aaSAndroid Build Coastguard Worker class FontationsFtCompareGM : public GM {
74*c8dee2aaSAndroid Build Coastguard Worker public:
FontationsFtCompareGM(std::string testName,std::string fontNameFilterRegexp,std::string langFilterRegexp,SkFontHinting hintingMode=SkFontHinting::kNone)75*c8dee2aaSAndroid Build Coastguard Worker     FontationsFtCompareGM(std::string testName,
76*c8dee2aaSAndroid Build Coastguard Worker                           std::string fontNameFilterRegexp,
77*c8dee2aaSAndroid Build Coastguard Worker                           std::string langFilterRegexp,
78*c8dee2aaSAndroid Build Coastguard Worker                           SkFontHinting hintingMode = SkFontHinting::kNone)
79*c8dee2aaSAndroid Build Coastguard Worker             : fTestDataIterator(fontNameFilterRegexp, langFilterRegexp)
80*c8dee2aaSAndroid Build Coastguard Worker             , fTestName(testName.c_str())
81*c8dee2aaSAndroid Build Coastguard Worker             , fHintingMode(hintingMode) {
82*c8dee2aaSAndroid Build Coastguard Worker         this->setBGColor(SK_ColorWHITE);
83*c8dee2aaSAndroid Build Coastguard Worker     }
84*c8dee2aaSAndroid Build Coastguard Worker 
85*c8dee2aaSAndroid Build Coastguard Worker protected:
getName() const86*c8dee2aaSAndroid Build Coastguard Worker     SkString getName() const override {
87*c8dee2aaSAndroid Build Coastguard Worker         SkString testName = SkStringPrintf("fontations_compare_ft_%s", fTestName.c_str());
88*c8dee2aaSAndroid Build Coastguard Worker         switch (fHintingMode) {
89*c8dee2aaSAndroid Build Coastguard Worker             case SkFontHinting::kNormal: {
90*c8dee2aaSAndroid Build Coastguard Worker                 testName.append("_hint_normal");
91*c8dee2aaSAndroid Build Coastguard Worker                 break;
92*c8dee2aaSAndroid Build Coastguard Worker             }
93*c8dee2aaSAndroid Build Coastguard Worker             case SkFontHinting::kSlight: {
94*c8dee2aaSAndroid Build Coastguard Worker                 testName.append("_hint_slight");
95*c8dee2aaSAndroid Build Coastguard Worker                 break;
96*c8dee2aaSAndroid Build Coastguard Worker             }
97*c8dee2aaSAndroid Build Coastguard Worker             case SkFontHinting::kFull: {
98*c8dee2aaSAndroid Build Coastguard Worker                 testName.append("_hint_full");
99*c8dee2aaSAndroid Build Coastguard Worker                 break;
100*c8dee2aaSAndroid Build Coastguard Worker             }
101*c8dee2aaSAndroid Build Coastguard Worker             case SkFontHinting::kNone: {
102*c8dee2aaSAndroid Build Coastguard Worker                 testName.append("_hint_none");
103*c8dee2aaSAndroid Build Coastguard Worker                 break;
104*c8dee2aaSAndroid Build Coastguard Worker             }
105*c8dee2aaSAndroid Build Coastguard Worker         }
106*c8dee2aaSAndroid Build Coastguard Worker         return testName;
107*c8dee2aaSAndroid Build Coastguard Worker     }
108*c8dee2aaSAndroid Build Coastguard Worker 
getISize()109*c8dee2aaSAndroid Build Coastguard Worker     SkISize getISize() override {
110*c8dee2aaSAndroid Build Coastguard Worker         TestFontDataProvider::TestSet testSet;
111*c8dee2aaSAndroid Build Coastguard Worker         fTestDataIterator.rewind();
112*c8dee2aaSAndroid Build Coastguard Worker         fTestDataIterator.next(&testSet);
113*c8dee2aaSAndroid Build Coastguard Worker 
114*c8dee2aaSAndroid Build Coastguard Worker         return SkISize::Make(kGmWidth,
115*c8dee2aaSAndroid Build Coastguard Worker                              testSet.langSamples.size() * kFontSize * kLangYIncrementScale + 100);
116*c8dee2aaSAndroid Build Coastguard Worker     }
117*c8dee2aaSAndroid Build Coastguard Worker 
onDraw(SkCanvas * canvas,SkString * errorMsg)118*c8dee2aaSAndroid Build Coastguard Worker     DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
119*c8dee2aaSAndroid Build Coastguard Worker         SkPaint paint;
120*c8dee2aaSAndroid Build Coastguard Worker         paint.setColor(SK_ColorBLACK);
121*c8dee2aaSAndroid Build Coastguard Worker 
122*c8dee2aaSAndroid Build Coastguard Worker         fTestDataIterator.rewind();
123*c8dee2aaSAndroid Build Coastguard Worker         TestFontDataProvider::TestSet testSet;
124*c8dee2aaSAndroid Build Coastguard Worker 
125*c8dee2aaSAndroid Build Coastguard Worker         while (fTestDataIterator.next(&testSet)) {
126*c8dee2aaSAndroid Build Coastguard Worker             sk_sp<SkTypeface> testTypeface = SkTypeface_Make_Fontations(
127*c8dee2aaSAndroid Build Coastguard Worker                     SkStream::MakeFromFile(testSet.fontFilename.c_str()), SkFontArguments());
128*c8dee2aaSAndroid Build Coastguard Worker             sk_sp<SkTypeface> ftTypeface = SkTypeface_FreeType::MakeFromStream(
129*c8dee2aaSAndroid Build Coastguard Worker                     SkStream::MakeFromFile(testSet.fontFilename.c_str()), SkFontArguments());
130*c8dee2aaSAndroid Build Coastguard Worker 
131*c8dee2aaSAndroid Build Coastguard Worker             if (!testTypeface || !ftTypeface) {
132*c8dee2aaSAndroid Build Coastguard Worker                 *errorMsg = "Unable to initialize typeface.";
133*c8dee2aaSAndroid Build Coastguard Worker                 return DrawResult::kSkip;
134*c8dee2aaSAndroid Build Coastguard Worker             }
135*c8dee2aaSAndroid Build Coastguard Worker 
136*c8dee2aaSAndroid Build Coastguard Worker             auto configureFont = [this](SkFont& font) {
137*c8dee2aaSAndroid Build Coastguard Worker                 font.setSize(kFontSize);
138*c8dee2aaSAndroid Build Coastguard Worker                 font.setEdging(SkFont::Edging::kSubpixelAntiAlias);
139*c8dee2aaSAndroid Build Coastguard Worker                 font.setSubpixel(true);
140*c8dee2aaSAndroid Build Coastguard Worker                 font.setHinting(fHintingMode);
141*c8dee2aaSAndroid Build Coastguard Worker             };
142*c8dee2aaSAndroid Build Coastguard Worker 
143*c8dee2aaSAndroid Build Coastguard Worker             SkFont font(testTypeface);
144*c8dee2aaSAndroid Build Coastguard Worker             configureFont(font);
145*c8dee2aaSAndroid Build Coastguard Worker 
146*c8dee2aaSAndroid Build Coastguard Worker             SkFont ftFont(ftTypeface);
147*c8dee2aaSAndroid Build Coastguard Worker             configureFont(ftFont);
148*c8dee2aaSAndroid Build Coastguard Worker             enum class DrawPhase { Fontations, FreeType, Comparison };
149*c8dee2aaSAndroid Build Coastguard Worker 
150*c8dee2aaSAndroid Build Coastguard Worker             SkRect maxBounds = SkRect::MakeEmpty();
151*c8dee2aaSAndroid Build Coastguard Worker             for (auto phase : {DrawPhase::Fontations, DrawPhase::FreeType, DrawPhase::Comparison}) {
152*c8dee2aaSAndroid Build Coastguard Worker                 SkScalar yCoord = kFontSize * 1.5f;
153*c8dee2aaSAndroid Build Coastguard Worker 
154*c8dee2aaSAndroid Build Coastguard Worker                 for (auto& langEntry : testSet.langSamples) {
155*c8dee2aaSAndroid Build Coastguard Worker                     auto shapeAndDrawToCanvas = [canvas, paint, langEntry](const SkFont& font,
156*c8dee2aaSAndroid Build Coastguard Worker                                                                            SkPoint coord) {
157*c8dee2aaSAndroid Build Coastguard Worker                         std::string testString(langEntry.sampleShort.c_str(),
158*c8dee2aaSAndroid Build Coastguard Worker                                                langEntry.sampleShort.size());
159*c8dee2aaSAndroid Build Coastguard Worker                         SkTextBlobBuilderRunHandler textBlobBuilder(testString.c_str(), {0, 0});
160*c8dee2aaSAndroid Build Coastguard Worker                         std::unique_ptr<SkShaper> shaper = SkShaper::Make();
161*c8dee2aaSAndroid Build Coastguard Worker                         shaper->shape(testString.c_str(),
162*c8dee2aaSAndroid Build Coastguard Worker                                       testString.size(),
163*c8dee2aaSAndroid Build Coastguard Worker                                       font,
164*c8dee2aaSAndroid Build Coastguard Worker                                       true,
165*c8dee2aaSAndroid Build Coastguard Worker                                       999999, /* Don't linebreak. */
166*c8dee2aaSAndroid Build Coastguard Worker                                       &textBlobBuilder);
167*c8dee2aaSAndroid Build Coastguard Worker                         sk_sp<const SkTextBlob> blob = textBlobBuilder.makeBlob();
168*c8dee2aaSAndroid Build Coastguard Worker                         canvas->drawTextBlob(blob.get(), coord.x(), coord.y(), paint);
169*c8dee2aaSAndroid Build Coastguard Worker                         return blob->bounds();
170*c8dee2aaSAndroid Build Coastguard Worker                     };
171*c8dee2aaSAndroid Build Coastguard Worker 
172*c8dee2aaSAndroid Build Coastguard Worker                     auto roundToDevicePixels = [canvas](SkPoint& point) {
173*c8dee2aaSAndroid Build Coastguard Worker                         SkMatrix ctm = canvas->getLocalToDeviceAs3x3();
174*c8dee2aaSAndroid Build Coastguard Worker                         SkPoint mapped = ctm.mapPoint(point);
175*c8dee2aaSAndroid Build Coastguard Worker                         SkPoint mappedRounded =
176*c8dee2aaSAndroid Build Coastguard Worker                                 SkPoint::Make(roundf(mapped.x()), roundf(mapped.y()));
177*c8dee2aaSAndroid Build Coastguard Worker                         SkMatrix inverse;
178*c8dee2aaSAndroid Build Coastguard Worker                         bool inverseExists = ctm.invert(&inverse);
179*c8dee2aaSAndroid Build Coastguard Worker                         SkASSERT(inverseExists);
180*c8dee2aaSAndroid Build Coastguard Worker                         if (inverseExists) {
181*c8dee2aaSAndroid Build Coastguard Worker                             point = inverse.mapPoint(mappedRounded);
182*c8dee2aaSAndroid Build Coastguard Worker                         }
183*c8dee2aaSAndroid Build Coastguard Worker                     };
184*c8dee2aaSAndroid Build Coastguard Worker 
185*c8dee2aaSAndroid Build Coastguard Worker                     auto fontationsCoord = [yCoord, roundToDevicePixels]() {
186*c8dee2aaSAndroid Build Coastguard Worker                         SkPoint fontationsCoord = SkPoint::Make(kMargin, yCoord);
187*c8dee2aaSAndroid Build Coastguard Worker                         roundToDevicePixels(fontationsCoord);
188*c8dee2aaSAndroid Build Coastguard Worker                         return fontationsCoord;
189*c8dee2aaSAndroid Build Coastguard Worker                     };
190*c8dee2aaSAndroid Build Coastguard Worker 
191*c8dee2aaSAndroid Build Coastguard Worker                     auto freetypeCoord = [yCoord, maxBounds, roundToDevicePixels]() {
192*c8dee2aaSAndroid Build Coastguard Worker                         SkPoint freetypeCoord = SkPoint::Make(
193*c8dee2aaSAndroid Build Coastguard Worker                                 2 * kMargin + maxBounds.left() + maxBounds.width(), yCoord);
194*c8dee2aaSAndroid Build Coastguard Worker                         roundToDevicePixels(freetypeCoord);
195*c8dee2aaSAndroid Build Coastguard Worker                         return freetypeCoord;
196*c8dee2aaSAndroid Build Coastguard Worker                     };
197*c8dee2aaSAndroid Build Coastguard Worker 
198*c8dee2aaSAndroid Build Coastguard Worker                     switch (phase) {
199*c8dee2aaSAndroid Build Coastguard Worker                         case DrawPhase::Fontations: {
200*c8dee2aaSAndroid Build Coastguard Worker                             SkRect boundsFontations = shapeAndDrawToCanvas(font, fontationsCoord());
201*c8dee2aaSAndroid Build Coastguard Worker                             /* Determine maximum of column width across all language samples. */
202*c8dee2aaSAndroid Build Coastguard Worker                             boundsFontations.roundOut();
203*c8dee2aaSAndroid Build Coastguard Worker                             maxBounds.join(boundsFontations);
204*c8dee2aaSAndroid Build Coastguard Worker                             break;
205*c8dee2aaSAndroid Build Coastguard Worker                         }
206*c8dee2aaSAndroid Build Coastguard Worker                         case DrawPhase::FreeType: {
207*c8dee2aaSAndroid Build Coastguard Worker                             shapeAndDrawToCanvas(ftFont, freetypeCoord());
208*c8dee2aaSAndroid Build Coastguard Worker                             break;
209*c8dee2aaSAndroid Build Coastguard Worker                         }
210*c8dee2aaSAndroid Build Coastguard Worker                         case DrawPhase::Comparison: {
211*c8dee2aaSAndroid Build Coastguard Worker                             /* Read back pixels from equally sized rectangles from the space in
212*c8dee2aaSAndroid Build Coastguard Worker                              * SkCanvas where Fontations and FreeType sample texts were drawn,
213*c8dee2aaSAndroid Build Coastguard Worker                              * compare them using pixel comparisons similar to SkDiff, draw a
214*c8dee2aaSAndroid Build Coastguard Worker                              * comparison as faint pixel differences, and as an amplified
215*c8dee2aaSAndroid Build Coastguard Worker                              * visualization in which each differing pixel is drawn as white. */
216*c8dee2aaSAndroid Build Coastguard Worker                             SkPoint fontationsOrigin = fontationsCoord();
217*c8dee2aaSAndroid Build Coastguard Worker                             SkPoint freetypeOrigin = freetypeCoord();
218*c8dee2aaSAndroid Build Coastguard Worker                             SkRect fontationsBBox(maxBounds.makeOffset(fontationsOrigin));
219*c8dee2aaSAndroid Build Coastguard Worker                             SkRect freetypeBBox(maxBounds.makeOffset(freetypeOrigin));
220*c8dee2aaSAndroid Build Coastguard Worker 
221*c8dee2aaSAndroid Build Coastguard Worker                             SkMatrix ctm = canvas->getLocalToDeviceAs3x3();
222*c8dee2aaSAndroid Build Coastguard Worker                             ctm.mapRect(&fontationsBBox, fontationsBBox);
223*c8dee2aaSAndroid Build Coastguard Worker                             ctm.mapRect(&freetypeBBox, freetypeBBox);
224*c8dee2aaSAndroid Build Coastguard Worker 
225*c8dee2aaSAndroid Build Coastguard Worker                             SkIRect fontationsIBox(fontationsBBox.roundOut());
226*c8dee2aaSAndroid Build Coastguard Worker                             SkIRect freetypeIBox(freetypeBBox.roundOut());
227*c8dee2aaSAndroid Build Coastguard Worker 
228*c8dee2aaSAndroid Build Coastguard Worker                             SkISize pixelDimensions(fontationsIBox.size());
229*c8dee2aaSAndroid Build Coastguard Worker                             SkImageInfo canvasImageInfo = canvas->imageInfo();
230*c8dee2aaSAndroid Build Coastguard Worker                             SkImageInfo diffImageInfo =
231*c8dee2aaSAndroid Build Coastguard Worker                                     SkImageInfo::Make(pixelDimensions,
232*c8dee2aaSAndroid Build Coastguard Worker                                                       SkColorType::kN32_SkColorType,
233*c8dee2aaSAndroid Build Coastguard Worker                                                       SkAlphaType::kUnpremul_SkAlphaType);
234*c8dee2aaSAndroid Build Coastguard Worker 
235*c8dee2aaSAndroid Build Coastguard Worker                             SkBitmap diffBitmap, highlightDiffBitmap;
236*c8dee2aaSAndroid Build Coastguard Worker                             diffBitmap.allocPixels(diffImageInfo, 0);
237*c8dee2aaSAndroid Build Coastguard Worker                             highlightDiffBitmap.allocPixels(diffImageInfo, 0);
238*c8dee2aaSAndroid Build Coastguard Worker 
239*c8dee2aaSAndroid Build Coastguard Worker                             // Workaround OveridePaintFilterCanvas limitations
240*c8dee2aaSAndroid Build Coastguard Worker                             // by getting pixel access through peekPixels()
241*c8dee2aaSAndroid Build Coastguard Worker                             // instead of readPixels(). Then use same pixmap to
242*c8dee2aaSAndroid Build Coastguard Worker                             // later write back the comparison results.
243*c8dee2aaSAndroid Build Coastguard Worker                             SkPixmap canvasPixmap;
244*c8dee2aaSAndroid Build Coastguard Worker                             if (!canvas->peekPixels(&canvasPixmap)) {
245*c8dee2aaSAndroid Build Coastguard Worker                                 break;
246*c8dee2aaSAndroid Build Coastguard Worker                             }
247*c8dee2aaSAndroid Build Coastguard Worker 
248*c8dee2aaSAndroid Build Coastguard Worker                             SkPixmap fontationsPixmap, freetypePixmap;
249*c8dee2aaSAndroid Build Coastguard Worker                             if (!canvasPixmap.extractSubset(&fontationsPixmap, fontationsIBox) ||
250*c8dee2aaSAndroid Build Coastguard Worker                                 !canvasPixmap.extractSubset(&freetypePixmap, freetypeIBox)) {
251*c8dee2aaSAndroid Build Coastguard Worker                                 break;
252*c8dee2aaSAndroid Build Coastguard Worker                             }
253*c8dee2aaSAndroid Build Coastguard Worker 
254*c8dee2aaSAndroid Build Coastguard Worker                             comparePixels(fontationsPixmap,
255*c8dee2aaSAndroid Build Coastguard Worker                                           freetypePixmap,
256*c8dee2aaSAndroid Build Coastguard Worker                                           &diffBitmap,
257*c8dee2aaSAndroid Build Coastguard Worker                                           &highlightDiffBitmap);
258*c8dee2aaSAndroid Build Coastguard Worker 
259*c8dee2aaSAndroid Build Coastguard Worker                             /* Place comparison results as two extra columns, shift up to account
260*c8dee2aaSAndroid Build Coastguard Worker                                for placement of rectangles vs. SkTextBlobs (baseline shift). */
261*c8dee2aaSAndroid Build Coastguard Worker                             SkPoint comparisonCoord = ctm.mapPoint(SkPoint::Make(
262*c8dee2aaSAndroid Build Coastguard Worker                                     3 * kMargin + maxBounds.width() * 2, yCoord + maxBounds.top()));
263*c8dee2aaSAndroid Build Coastguard Worker                             SkPoint whiteCoord = ctm.mapPoint(SkPoint::Make(
264*c8dee2aaSAndroid Build Coastguard Worker                                     4 * kMargin + maxBounds.width() * 3, yCoord + maxBounds.top()));
265*c8dee2aaSAndroid Build Coastguard Worker 
266*c8dee2aaSAndroid Build Coastguard Worker                             SkSurfaceProps canvasSurfaceProps = canvas->getBaseProps();
267*c8dee2aaSAndroid Build Coastguard Worker                             sk_sp<SkSurface> writeBackSurface =
268*c8dee2aaSAndroid Build Coastguard Worker                                     SkSurfaces::WrapPixels(canvasPixmap, &canvasSurfaceProps);
269*c8dee2aaSAndroid Build Coastguard Worker 
270*c8dee2aaSAndroid Build Coastguard Worker                             writeBackSurface->writePixels(
271*c8dee2aaSAndroid Build Coastguard Worker                                     diffBitmap, comparisonCoord.x(), comparisonCoord.y());
272*c8dee2aaSAndroid Build Coastguard Worker                             writeBackSurface->writePixels(
273*c8dee2aaSAndroid Build Coastguard Worker                                     highlightDiffBitmap, whiteCoord.x(), whiteCoord.y());
274*c8dee2aaSAndroid Build Coastguard Worker                             break;
275*c8dee2aaSAndroid Build Coastguard Worker                         }
276*c8dee2aaSAndroid Build Coastguard Worker                     }
277*c8dee2aaSAndroid Build Coastguard Worker 
278*c8dee2aaSAndroid Build Coastguard Worker                     yCoord += font.getSize() * kLangYIncrementScale;
279*c8dee2aaSAndroid Build Coastguard Worker                 }
280*c8dee2aaSAndroid Build Coastguard Worker             }
281*c8dee2aaSAndroid Build Coastguard Worker         }
282*c8dee2aaSAndroid Build Coastguard Worker 
283*c8dee2aaSAndroid Build Coastguard Worker         return DrawResult::kOk;
284*c8dee2aaSAndroid Build Coastguard Worker     }
285*c8dee2aaSAndroid Build Coastguard Worker 
286*c8dee2aaSAndroid Build Coastguard Worker private:
287*c8dee2aaSAndroid Build Coastguard Worker     using INHERITED = GM;
288*c8dee2aaSAndroid Build Coastguard Worker 
289*c8dee2aaSAndroid Build Coastguard Worker     TestFontDataProvider fTestDataIterator;
290*c8dee2aaSAndroid Build Coastguard Worker     SkString fTestName;
291*c8dee2aaSAndroid Build Coastguard Worker     SkFontHinting fHintingMode;
292*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<SkTypeface> fReportTypeface;
293*c8dee2aaSAndroid Build Coastguard Worker     std::unique_ptr<SkFontArguments::VariationPosition::Coordinate[]> fCoordinates;
294*c8dee2aaSAndroid Build Coastguard Worker };
295*c8dee2aaSAndroid Build Coastguard Worker 
296*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new FontationsFtCompareGM(
297*c8dee2aaSAndroid Build Coastguard Worker         "NotoSans",
298*c8dee2aaSAndroid Build Coastguard Worker         "Noto Sans",
299*c8dee2aaSAndroid Build Coastguard Worker         "en_Latn|es_Latn|pt_Latn|id_Latn|ru_Cyrl|fr_Latn|tr_Latn|vi_Latn|de_"
300*c8dee2aaSAndroid Build Coastguard Worker         "Latn|it_Latn|pl_Latn|nl_Latn|uk_Cyrl|gl_Latn|ro_Latn|cs_Latn|hu_Latn|"
301*c8dee2aaSAndroid Build Coastguard Worker         "el_Grek|se_Latn|da_Latn|bg_Latn|sk_Latn|fi_Latn|bs_Latn|ca_Latn|no_"
302*c8dee2aaSAndroid Build Coastguard Worker         "Latn|sr_Latn|sr_Cyrl|lt_Latn|hr_Latn|sl_Latn|uz_Latn|uz_Cyrl|lv_Latn|"
303*c8dee2aaSAndroid Build Coastguard Worker         "et_Latn|az_Latn|az_Cyrl|la_Latn|tg_Latn|tg_Cyrl|sw_Latn|mn_Cyrl|kk_"
304*c8dee2aaSAndroid Build Coastguard Worker         "Latn|kk_Cyrl|sq_Latn|af_Latn|ha_Latn|ky_Cyrl"));
305*c8dee2aaSAndroid Build Coastguard Worker 
306*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new FontationsFtCompareGM(
307*c8dee2aaSAndroid Build Coastguard Worker         "NotoSans",
308*c8dee2aaSAndroid Build Coastguard Worker         "Noto Sans",
309*c8dee2aaSAndroid Build Coastguard Worker         "en_Latn|es_Latn|pt_Latn|id_Latn|ru_Cyrl|fr_Latn|tr_Latn|vi_Latn|de_"
310*c8dee2aaSAndroid Build Coastguard Worker         "Latn|it_Latn|pl_Latn|nl_Latn|uk_Cyrl|gl_Latn|ro_Latn|cs_Latn|hu_Latn|"
311*c8dee2aaSAndroid Build Coastguard Worker         "el_Grek|se_Latn|da_Latn|bg_Latn|sk_Latn|fi_Latn|bs_Latn|ca_Latn|no_"
312*c8dee2aaSAndroid Build Coastguard Worker         "Latn|sr_Latn|sr_Cyrl|lt_Latn|hr_Latn|sl_Latn|uz_Latn|uz_Cyrl|lv_Latn|"
313*c8dee2aaSAndroid Build Coastguard Worker         "et_Latn|az_Latn|az_Cyrl|la_Latn|tg_Latn|tg_Cyrl|sw_Latn|mn_Cyrl|kk_"
314*c8dee2aaSAndroid Build Coastguard Worker         "Latn|kk_Cyrl|sq_Latn|af_Latn|ha_Latn|ky_Cyrl",
315*c8dee2aaSAndroid Build Coastguard Worker         SkFontHinting::kSlight));
316*c8dee2aaSAndroid Build Coastguard Worker 
317*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new FontationsFtCompareGM(
318*c8dee2aaSAndroid Build Coastguard Worker         "NotoSans",
319*c8dee2aaSAndroid Build Coastguard Worker         "Noto Sans",
320*c8dee2aaSAndroid Build Coastguard Worker         "en_Latn|es_Latn|pt_Latn|id_Latn|ru_Cyrl|fr_Latn|tr_Latn|vi_Latn|de_"
321*c8dee2aaSAndroid Build Coastguard Worker         "Latn|it_Latn|pl_Latn|nl_Latn|uk_Cyrl|gl_Latn|ro_Latn|cs_Latn|hu_Latn|"
322*c8dee2aaSAndroid Build Coastguard Worker         "el_Grek|se_Latn|da_Latn|bg_Latn|sk_Latn|fi_Latn|bs_Latn|ca_Latn|no_"
323*c8dee2aaSAndroid Build Coastguard Worker         "Latn|sr_Latn|sr_Cyrl|lt_Latn|hr_Latn|sl_Latn|uz_Latn|uz_Cyrl|lv_Latn|"
324*c8dee2aaSAndroid Build Coastguard Worker         "et_Latn|az_Latn|az_Cyrl|la_Latn|tg_Latn|tg_Cyrl|sw_Latn|mn_Cyrl|kk_"
325*c8dee2aaSAndroid Build Coastguard Worker         "Latn|kk_Cyrl|sq_Latn|af_Latn|ha_Latn|ky_Cyrl",
326*c8dee2aaSAndroid Build Coastguard Worker         SkFontHinting::kNormal));
327*c8dee2aaSAndroid Build Coastguard Worker 
328*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new FontationsFtCompareGM("NotoSans_Deva",
329*c8dee2aaSAndroid Build Coastguard Worker                                         "Noto Sans Devanagari",
330*c8dee2aaSAndroid Build Coastguard Worker                                         "hi_Deva|mr_Deva"));
331*c8dee2aaSAndroid Build Coastguard Worker 
332*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new FontationsFtCompareGM(
333*c8dee2aaSAndroid Build Coastguard Worker         "NotoSans_Deva", "Noto Sans Devanagari", "hi_Deva|mr_Deva", SkFontHinting::kSlight));
334*c8dee2aaSAndroid Build Coastguard Worker 
335*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new FontationsFtCompareGM(
336*c8dee2aaSAndroid Build Coastguard Worker         "NotoSans_Deva", "Noto Sans Devanagari", "hi_Deva|mr_Deva", SkFontHinting::kNormal));
337*c8dee2aaSAndroid Build Coastguard Worker 
338*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new FontationsFtCompareGM("NotoSans_ar_Arab",
339*c8dee2aaSAndroid Build Coastguard Worker                                         "Noto Sans Arabic",
340*c8dee2aaSAndroid Build Coastguard Worker                                         "ar_Arab|uz_Arab|kk_Arab|ky_Arab"));
341*c8dee2aaSAndroid Build Coastguard Worker 
342*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new FontationsFtCompareGM("NotoSans_ar_Arab",
343*c8dee2aaSAndroid Build Coastguard Worker                                         "Noto Sans Arabic",
344*c8dee2aaSAndroid Build Coastguard Worker                                         "ar_Arab|uz_Arab|kk_Arab|ky_Arab",
345*c8dee2aaSAndroid Build Coastguard Worker                                         SkFontHinting::kSlight));
346*c8dee2aaSAndroid Build Coastguard Worker 
347*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new FontationsFtCompareGM("NotoSans_ar_Arab",
348*c8dee2aaSAndroid Build Coastguard Worker                                         "Noto Sans Arabic",
349*c8dee2aaSAndroid Build Coastguard Worker                                         "ar_Arab|uz_Arab|kk_Arab|ky_Arab",
350*c8dee2aaSAndroid Build Coastguard Worker                                         SkFontHinting::kNormal));
351*c8dee2aaSAndroid Build Coastguard Worker 
352*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new FontationsFtCompareGM("NotoSans_Beng", "Noto Sans Bengali", "bn_Beng"));
353*c8dee2aaSAndroid Build Coastguard Worker 
354*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new FontationsFtCompareGM("NotoSans_Jpan", "Noto Sans JP", "ja_Jpan"));
355*c8dee2aaSAndroid Build Coastguard Worker 
356*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new FontationsFtCompareGM("NotoSans_Thai", "Noto Sans Thai", "th_Thai"));
357*c8dee2aaSAndroid Build Coastguard Worker 
358*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new FontationsFtCompareGM("NotoSans_Hans", "Noto Sans SC", "zh_Hans"));
359*c8dee2aaSAndroid Build Coastguard Worker 
360*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new FontationsFtCompareGM("NotoSans_Hant", "Noto Sans TC", "zh_Hant"));
361*c8dee2aaSAndroid Build Coastguard Worker 
362*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new FontationsFtCompareGM("NotoSans_Kore", "Noto Sans KR", "ko_Kore"));
363*c8dee2aaSAndroid Build Coastguard Worker 
364*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new FontationsFtCompareGM("NotoSans_Taml", "Noto Sans Tamil", "ta_Taml"));
365*c8dee2aaSAndroid Build Coastguard Worker 
366*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new FontationsFtCompareGM("NotoSans_Newa", "Noto Sans Newa", "new_Newa"));
367*c8dee2aaSAndroid Build Coastguard Worker 
368*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new FontationsFtCompareGM("NotoSans_Knda", "Noto Sans Kannada", "kn_Knda"));
369*c8dee2aaSAndroid Build Coastguard Worker 
370*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new FontationsFtCompareGM("NotoSans_Tglg", "Noto Sans Tagalog", "fil_Tglg"));
371*c8dee2aaSAndroid Build Coastguard Worker 
372*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new FontationsFtCompareGM("NotoSans_Telu", "Noto Sans Telugu", "te_Telu"));
373*c8dee2aaSAndroid Build Coastguard Worker 
374*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new FontationsFtCompareGM("NotoSans_Gujr", "Noto Sans Gujarati", "gu_Gujr"));
375*c8dee2aaSAndroid Build Coastguard Worker 
376*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new FontationsFtCompareGM("NotoSans_Geor", "Noto Sans Georgian", "ka_Geor"));
377*c8dee2aaSAndroid Build Coastguard Worker 
378*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new FontationsFtCompareGM("NotoSans_Mlym", "Noto Sans Malayalam", "ml_Mlym"));
379*c8dee2aaSAndroid Build Coastguard Worker 
380*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new FontationsFtCompareGM("NotoSans_Khmr", "Noto Sans Khmer", "km_Khmr"));
381*c8dee2aaSAndroid Build Coastguard Worker 
382*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new FontationsFtCompareGM("NotoSans_Sinh", "Noto Sans Sinhala", "si_Sinh"));
383*c8dee2aaSAndroid Build Coastguard Worker 
384*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new FontationsFtCompareGM("NotoSans_Mymr", "Noto Sans Myanmar", "my_Mymr"));
385*c8dee2aaSAndroid Build Coastguard Worker 
386*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new FontationsFtCompareGM("NotoSans_Java", "Noto Sans Javanese", "jv_Java"));
387*c8dee2aaSAndroid Build Coastguard Worker 
388*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new FontationsFtCompareGM("NotoSans_Mong", "Noto Sans Mongolian", "mn_Mong"));
389*c8dee2aaSAndroid Build Coastguard Worker 
390*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new FontationsFtCompareGM("NotoSans_Armn", "Noto Sans Armenian", "hy_Armn"));
391*c8dee2aaSAndroid Build Coastguard Worker 
392*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new FontationsFtCompareGM("NotoSans_Elba", "Noto Sans Elbasan", "sq_Elba"));
393*c8dee2aaSAndroid Build Coastguard Worker 
394*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new FontationsFtCompareGM("NotoSans_Vith", "Noto Sans Vithkuqi", "sq_Vith"));
395*c8dee2aaSAndroid Build Coastguard Worker 
396*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new FontationsFtCompareGM("NotoSans_Guru", "Noto Sans Gurmukhi", "pa_Guru"));
397*c8dee2aaSAndroid Build Coastguard Worker 
398*c8dee2aaSAndroid Build Coastguard Worker }  // namespace skiagm
399