1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/*
2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2014 Google Inc.
3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *
4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be
5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file.
6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPaint.h"
9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPoint.h"
10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkTextBlobRunIterator.h"
11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkTypeface.h"
12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "Test.h"
14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "sk_tool_utils.h"
15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass TextBlobTester {
17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // This unit test feeds an SkTextBlobBuilder various runs then checks to see if
19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // the result contains the provided data and merges runs when appropriate.
20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static void TestBuilder(skiatest::Reporter* reporter) {
21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkTextBlobBuilder builder;
22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // empty run set
24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        RunBuilderTest(reporter, builder, nullptr, 0, nullptr, 0);
25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        RunDef set1[] = {
27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { 128, SkTextBlob::kDefault_Positioning, 100, 100 },
28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        };
29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        RunBuilderTest(reporter, builder, set1, SK_ARRAY_COUNT(set1), set1, SK_ARRAY_COUNT(set1));
30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        RunDef set2[] = {
32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { 128, SkTextBlob::kHorizontal_Positioning, 100, 100 },
33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        };
34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        RunBuilderTest(reporter, builder, set2, SK_ARRAY_COUNT(set2), set2, SK_ARRAY_COUNT(set2));
35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        RunDef set3[] = {
37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { 128, SkTextBlob::kFull_Positioning, 100, 100 },
38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        };
39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        RunBuilderTest(reporter, builder, set3, SK_ARRAY_COUNT(set3), set3, SK_ARRAY_COUNT(set3));
40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        RunDef set4[] = {
42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { 128, SkTextBlob::kDefault_Positioning, 100, 150 },
43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { 128, SkTextBlob::kDefault_Positioning, 100, 150 },
44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { 128, SkTextBlob::kDefault_Positioning, 100, 150 },
45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        };
46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        RunBuilderTest(reporter, builder, set4, SK_ARRAY_COUNT(set4), set4, SK_ARRAY_COUNT(set4));
47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        RunDef set5[] = {
49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { 128, SkTextBlob::kHorizontal_Positioning, 100, 150 },
50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { 128, SkTextBlob::kHorizontal_Positioning, 200, 150 },
51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { 128, SkTextBlob::kHorizontal_Positioning, 300, 250 },
52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        };
53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        RunDef mergedSet5[] = {
54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { 256, SkTextBlob::kHorizontal_Positioning, 0, 150 },
55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { 128, SkTextBlob::kHorizontal_Positioning, 0, 250 },
56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        };
57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        RunBuilderTest(reporter, builder, set5, SK_ARRAY_COUNT(set5), mergedSet5,
58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                       SK_ARRAY_COUNT(mergedSet5));
59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        RunDef set6[] = {
61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { 128, SkTextBlob::kFull_Positioning, 100, 100 },
62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { 128, SkTextBlob::kFull_Positioning, 200, 200 },
63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { 128, SkTextBlob::kFull_Positioning, 300, 300 },
64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        };
65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        RunDef mergedSet6[] = {
66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { 384, SkTextBlob::kFull_Positioning, 0, 0 },
67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        };
68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        RunBuilderTest(reporter, builder, set6, SK_ARRAY_COUNT(set6), mergedSet6,
69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                       SK_ARRAY_COUNT(mergedSet6));
70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        RunDef set7[] = {
72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { 128, SkTextBlob::kDefault_Positioning, 100, 150 },
73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { 128, SkTextBlob::kDefault_Positioning, 100, 150 },
74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { 128, SkTextBlob::kHorizontal_Positioning, 100, 150 },
75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { 128, SkTextBlob::kHorizontal_Positioning, 200, 150 },
76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { 128, SkTextBlob::kFull_Positioning, 400, 350 },
77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { 128, SkTextBlob::kFull_Positioning, 400, 350 },
78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { 128, SkTextBlob::kDefault_Positioning, 100, 450 },
79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { 128, SkTextBlob::kDefault_Positioning, 100, 450 },
80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { 128, SkTextBlob::kHorizontal_Positioning, 100, 550 },
81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { 128, SkTextBlob::kHorizontal_Positioning, 200, 650 },
82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { 128, SkTextBlob::kFull_Positioning, 400, 750 },
83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { 128, SkTextBlob::kFull_Positioning, 400, 850 },
84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        };
85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        RunDef mergedSet7[] = {
86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { 128, SkTextBlob::kDefault_Positioning, 100, 150 },
87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { 128, SkTextBlob::kDefault_Positioning, 100, 150 },
88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { 256, SkTextBlob::kHorizontal_Positioning, 0, 150 },
89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { 256, SkTextBlob::kFull_Positioning, 0, 0 },
90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { 128, SkTextBlob::kDefault_Positioning, 100, 450 },
91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { 128, SkTextBlob::kDefault_Positioning, 100, 450 },
92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { 128, SkTextBlob::kHorizontal_Positioning, 0, 550 },
93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { 128, SkTextBlob::kHorizontal_Positioning, 0, 650 },
94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { 256, SkTextBlob::kFull_Positioning, 0, 0 },
95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        };
96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        RunBuilderTest(reporter, builder, set7, SK_ARRAY_COUNT(set7), mergedSet7,
97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                       SK_ARRAY_COUNT(mergedSet7));
98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // This unit test verifies blob bounds computation.
101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static void TestBounds(skiatest::Reporter* reporter) {
102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkTextBlobBuilder builder;
103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPaint font;
104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        font.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // Explicit bounds.
107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        {
108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            sk_sp<SkTextBlob> blob(builder.make());
109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, !blob);
110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        {
113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkRect r1 = SkRect::MakeXYWH(10, 10, 20, 20);
114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            builder.allocRun(font, 16, 0, 0, &r1);
115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            sk_sp<SkTextBlob> blob(builder.make());
116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, blob->bounds() == r1);
117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        {
120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkRect r1 = SkRect::MakeXYWH(10, 10, 20, 20);
121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            builder.allocRunPosH(font, 16, 0, &r1);
122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            sk_sp<SkTextBlob> blob(builder.make());
123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, blob->bounds() == r1);
124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        {
127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkRect r1 = SkRect::MakeXYWH(10, 10, 20, 20);
128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            builder.allocRunPos(font, 16, &r1);
129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            sk_sp<SkTextBlob> blob(builder.make());
130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, blob->bounds() == r1);
131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        {
134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkRect r1 = SkRect::MakeXYWH(10, 10, 20, 20);
135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkRect r2 = SkRect::MakeXYWH(15, 20, 50, 50);
136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkRect r3 = SkRect::MakeXYWH(0, 5, 10, 5);
137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            builder.allocRun(font, 16, 0, 0, &r1);
139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            builder.allocRunPosH(font, 16, 0, &r2);
140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            builder.allocRunPos(font, 16, &r3);
141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            sk_sp<SkTextBlob> blob(builder.make());
143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, blob->bounds() == SkRect::MakeXYWH(0, 5, 65, 65));
144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        {
147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            sk_sp<SkTextBlob> blob(builder.make());
148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, !blob);
149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // Implicit bounds
152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        {
154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // Exercise the empty bounds path, and ensure that RunRecord-aligned pos buffers
155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // don't trigger asserts (http://crbug.com/542643).
156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkPaint p;
157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            p.setTextSize(0);
158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            p.setTextEncoding(SkPaint::kUTF8_TextEncoding);
159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            const char* txt = "BOOO";
161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            const size_t txtLen = strlen(txt);
162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            const int glyphCount = p.textToGlyphs(txt, txtLen, nullptr);
163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            p.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            const SkTextBlobBuilder::RunBuffer& buffer = builder.allocRunPos(p, glyphCount);
166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            p.setTextEncoding(SkPaint::kUTF8_TextEncoding);
168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            p.textToGlyphs(txt, txtLen, buffer.glyphs);
169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            memset(buffer.pos, 0, sizeof(SkScalar) * glyphCount * 2);
171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            sk_sp<SkTextBlob> blob(builder.make());
172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, blob->bounds().isEmpty());
173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Verify that text-related properties are captured in run paints.
177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static void TestPaintProps(skiatest::Reporter* reporter) {
178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPaint font;
179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        font.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // Kitchen sink font.
182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        font.setTextSize(42);
183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        font.setTextScaleX(4.2f);
184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        font.setTypeface(SkTypeface::MakeDefault());
185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        font.setTextSkewX(0.42f);
186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        font.setTextAlign(SkPaint::kCenter_Align);
187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        font.setHinting(SkPaint::kFull_Hinting);
188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        font.setAntiAlias(true);
189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        font.setFakeBoldText(true);
190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        font.setLinearText(true);
191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        font.setSubpixelText(true);
192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        font.setDevKernText(true);
193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        font.setLCDRenderText(true);
194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        font.setEmbeddedBitmapText(true);
195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        font.setAutohinted(true);
196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        font.setVerticalText(true);
197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        font.setFlags(font.getFlags() | SkPaint::kGenA8FromLCD_Flag);
198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // Ensure we didn't pick default values by mistake.
200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPaint defaultPaint;
201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        REPORTER_ASSERT(reporter, defaultPaint.getTextSize() != font.getTextSize());
202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        REPORTER_ASSERT(reporter, defaultPaint.getTextScaleX() != font.getTextScaleX());
203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        REPORTER_ASSERT(reporter, defaultPaint.getTypeface() != font.getTypeface());
204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        REPORTER_ASSERT(reporter, defaultPaint.getTextSkewX() != font.getTextSkewX());
205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        REPORTER_ASSERT(reporter, defaultPaint.getTextAlign() != font.getTextAlign());
206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        REPORTER_ASSERT(reporter, defaultPaint.getHinting() != font.getHinting());
207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        REPORTER_ASSERT(reporter, defaultPaint.isAntiAlias() != font.isAntiAlias());
208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        REPORTER_ASSERT(reporter, defaultPaint.isFakeBoldText() != font.isFakeBoldText());
209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        REPORTER_ASSERT(reporter, defaultPaint.isLinearText() != font.isLinearText());
210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        REPORTER_ASSERT(reporter, defaultPaint.isSubpixelText() != font.isSubpixelText());
211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        REPORTER_ASSERT(reporter, defaultPaint.isDevKernText() != font.isDevKernText());
212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        REPORTER_ASSERT(reporter, defaultPaint.isLCDRenderText() != font.isLCDRenderText());
213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        REPORTER_ASSERT(reporter, defaultPaint.isEmbeddedBitmapText() != font.isEmbeddedBitmapText());
214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        REPORTER_ASSERT(reporter, defaultPaint.isAutohinted() != font.isAutohinted());
215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        REPORTER_ASSERT(reporter, defaultPaint.isVerticalText() != font.isVerticalText());
216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        REPORTER_ASSERT(reporter, (defaultPaint.getFlags() & SkPaint::kGenA8FromLCD_Flag) !=
217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                  (font.getFlags() & SkPaint::kGenA8FromLCD_Flag));
218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkTextBlobBuilder builder;
220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        AddRun(font, 1, SkTextBlob::kDefault_Positioning, SkPoint::Make(0, 0), builder);
221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        AddRun(font, 1, SkTextBlob::kHorizontal_Positioning, SkPoint::Make(0, 0), builder);
222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        AddRun(font, 1, SkTextBlob::kFull_Positioning, SkPoint::Make(0, 0), builder);
223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        sk_sp<SkTextBlob> blob(builder.make());
224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkTextBlobRunIterator it(blob.get());
226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        while (!it.done()) {
227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkPaint paint;
228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            it.applyFontToPaint(&paint);
229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, paint.getTextSize() == font.getTextSize());
231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, paint.getTextScaleX() == font.getTextScaleX());
232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, paint.getTypeface() == font.getTypeface());
233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, paint.getTextSkewX() == font.getTextSkewX());
234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, paint.getTextAlign() == font.getTextAlign());
235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, paint.getHinting() == font.getHinting());
236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, paint.isAntiAlias() == font.isAntiAlias());
237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, paint.isFakeBoldText() == font.isFakeBoldText());
238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, paint.isLinearText() == font.isLinearText());
239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, paint.isSubpixelText() == font.isSubpixelText());
240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, paint.isDevKernText() == font.isDevKernText());
241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, paint.isLCDRenderText() == font.isLCDRenderText());
242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, paint.isEmbeddedBitmapText() == font.isEmbeddedBitmapText());
243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, paint.isAutohinted() == font.isAutohinted());
244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, paint.isVerticalText() == font.isVerticalText());
245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, (paint.getFlags() & SkPaint::kGenA8FromLCD_Flag) ==
246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                      (font.getFlags() & SkPaint::kGenA8FromLCD_Flag));
247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            it.next();
249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate:
254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    struct RunDef {
255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        unsigned                     count;
256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkTextBlob::GlyphPositioning pos;
257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkScalar                     x, y;
258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    };
259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static void RunBuilderTest(skiatest::Reporter* reporter, SkTextBlobBuilder& builder,
261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                               const RunDef in[], unsigned inCount,
262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                               const RunDef out[], unsigned outCount) {
263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPaint font;
264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        font.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        unsigned glyphCount = 0;
267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        unsigned posCount = 0;
268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (unsigned i = 0; i < inCount; ++i) {
270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            AddRun(font, in[i].count, in[i].pos, SkPoint::Make(in[i].x, in[i].y), builder);
271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            glyphCount += in[i].count;
272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            posCount += in[i].count * in[i].pos;
273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        sk_sp<SkTextBlob> blob(builder.make());
276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        REPORTER_ASSERT(reporter, (inCount > 0) == SkToBool(blob));
277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (!blob) {
278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return;
279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkTextBlobRunIterator it(blob.get());
282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (unsigned i = 0; i < outCount; ++i) {
283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, !it.done());
284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, out[i].pos == it.positioning());
285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, out[i].count == it.glyphCount());
286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (SkTextBlob::kDefault_Positioning == out[i].pos) {
287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                REPORTER_ASSERT(reporter, out[i].x == it.offset().x());
288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                REPORTER_ASSERT(reporter, out[i].y == it.offset().y());
289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            } else if (SkTextBlob::kHorizontal_Positioning == out[i].pos) {
290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                REPORTER_ASSERT(reporter, out[i].y == it.offset().y());
291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
293fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            for (unsigned k = 0; k < it.glyphCount(); ++k) {
294fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                REPORTER_ASSERT(reporter, k % 128 == it.glyphs()[k]);
295fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if (SkTextBlob::kHorizontal_Positioning == it.positioning()) {
296fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    REPORTER_ASSERT(reporter, SkIntToScalar(k % 128) == it.pos()[k]);
297fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                } else if (SkTextBlob::kFull_Positioning == it.positioning()) {
298fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    REPORTER_ASSERT(reporter, SkIntToScalar(k % 128) == it.pos()[k * 2]);
299fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    REPORTER_ASSERT(reporter, -SkIntToScalar(k % 128) == it.pos()[k * 2 + 1]);
300fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
301fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
302fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
303fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            it.next();
304fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
305fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
306fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        REPORTER_ASSERT(reporter, it.done());
307fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
308fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
309fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static void AddRun(const SkPaint& font, int count, SkTextBlob::GlyphPositioning pos,
310fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                       const SkPoint& offset, SkTextBlobBuilder& builder,
311fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                       const SkRect* bounds = nullptr) {
312fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        switch (pos) {
313fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case SkTextBlob::kDefault_Positioning: {
314fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            const SkTextBlobBuilder::RunBuffer& rb = builder.allocRun(font, count, offset.x(),
315fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                      offset.y(), bounds);
316fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            for (int i = 0; i < count; ++i) {
317fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                rb.glyphs[i] = i;
318fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
319fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } break;
320fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case SkTextBlob::kHorizontal_Positioning: {
321fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            const SkTextBlobBuilder::RunBuffer& rb = builder.allocRunPosH(font, count, offset.y(),
322fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                          bounds);
323fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            for (int i = 0; i < count; ++i) {
324fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                rb.glyphs[i] = i;
325fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                rb.pos[i] = SkIntToScalar(i);
326fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
327fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } break;
328fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case SkTextBlob::kFull_Positioning: {
329fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            const SkTextBlobBuilder::RunBuffer& rb = builder.allocRunPos(font, count, bounds);
330fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            for (int i = 0; i < count; ++i) {
331fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                rb.glyphs[i] = i;
332fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                rb.pos[i * 2] = SkIntToScalar(i);
333fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                rb.pos[i * 2 + 1] = -SkIntToScalar(i);
334fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
335fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } break;
336fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        default:
337fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SK_ABORT("unhandled positioning value");
338fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
339fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
340fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
341fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
342fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_TEST(TextBlob_builder, reporter) {
343fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    TextBlobTester::TestBuilder(reporter);
344fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    TextBlobTester::TestBounds(reporter);
345fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
346fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
347fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_TEST(TextBlob_paint, reporter) {
348fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    TextBlobTester::TestPaintProps(reporter);
349fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
350fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
351fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_TEST(TextBlob_extended, reporter) {
352fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkTextBlobBuilder textBlobBuilder;
353fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPaint paint;
354fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char text1[] = "Foo";
355fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char text2[] = "Bar";
356fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
357fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int glyphCount = paint.textToGlyphs(text1, strlen(text1), nullptr);
358fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkAutoTMalloc<uint16_t> glyphs(glyphCount);
359fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    (void)paint.textToGlyphs(text1, strlen(text1), glyphs.get());
360fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
361fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
362fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    auto run = textBlobBuilder.allocRunText(
363fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            paint, glyphCount, 0, 0, SkToInt(strlen(text2)), SkString(), nullptr);
364fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    memcpy(run.glyphs, glyphs.get(), sizeof(uint16_t) * glyphCount);
365fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    memcpy(run.utf8text, text2, strlen(text2));
366fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (int i = 0; i < glyphCount; ++i) {
367fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        run.clusters[i] = SkTMin(SkToU32(i), SkToU32(strlen(text2)));
368fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
369fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp<SkTextBlob> blob(textBlobBuilder.make());
370fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    REPORTER_ASSERT(reporter, blob);
371fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
372fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (SkTextBlobRunIterator it(blob.get()); !it.done(); it.next()) {
373fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        REPORTER_ASSERT(reporter, it.glyphCount() == (uint32_t)glyphCount);
374fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (uint32_t i = 0; i < it.glyphCount(); ++i) {
375fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, it.glyphs()[i] == glyphs[i]);
376fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
377fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        REPORTER_ASSERT(reporter, SkTextBlob::kDefault_Positioning == it.positioning());
378fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        REPORTER_ASSERT(reporter, (SkPoint{0.0f, 0.0f}) == it.offset());
379fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        REPORTER_ASSERT(reporter, it.textSize() > 0);
380fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        REPORTER_ASSERT(reporter, it.clusters());
381fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (uint32_t i = 0; i < it.glyphCount(); ++i) {
382fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            REPORTER_ASSERT(reporter, i == it.clusters()[i]);
383fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
384fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        REPORTER_ASSERT(reporter, 0 == strncmp(text2, it.text(), it.textSize()));
385fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
386fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
387fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
388fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot///////////////////////////////////////////////////////////////////////////////////////////////////
389fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkCanvas.h"
390fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkSurface.h"
391fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkTDArray.h"
392fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
393fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void add_run(SkTextBlobBuilder* builder, const char text[], SkScalar x, SkScalar y,
394fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    sk_sp<SkTypeface> tf) {
395fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPaint paint;
396fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    paint.setAntiAlias(true);
397fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    paint.setSubpixelText(true);
398fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    paint.setTextSize(16);
399fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    paint.setTypeface(tf);
400fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
401fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int glyphCount = paint.textToGlyphs(text, strlen(text), nullptr);
402fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
403fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
404fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkTextBlobBuilder::RunBuffer buffer = builder->allocRun(paint, glyphCount, x, y);
405fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
406fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    paint.setTextEncoding(SkPaint::kUTF8_TextEncoding);
407fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    (void)paint.textToGlyphs(text, strlen(text), buffer.glyphs);
408fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
409fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
410fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic sk_sp<SkImage> render(const SkTextBlob* blob) {
411fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    auto surf = SkSurface::MakeRasterN32Premul(SkScalarRoundToInt(blob->bounds().width()),
412fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                               SkScalarRoundToInt(blob->bounds().height()));
413fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!surf) {
414fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return nullptr; // bounds are empty?
415fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
416fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    surf->getCanvas()->clear(SK_ColorWHITE);
417fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    surf->getCanvas()->drawTextBlob(blob, -blob->bounds().left(), -blob->bounds().top(), SkPaint());
418fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return surf->makeImageSnapshot();
419fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
420fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
421fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/*
422fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *  Build a blob with more than one typeface.
423fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *  Draw it into an offscreen,
424fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *  then serialize and deserialize,
425fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *  Then draw the new instance and assert it draws the same as the original.
426fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
427fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_TEST(TextBlob_serialize, reporter) {
428fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp<SkTextBlob> blob0 = []() {
429fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        sk_sp<SkTypeface> tf = SkTypeface::MakeDefault();
430fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
431fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkTextBlobBuilder builder;
432fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        add_run(&builder, "Hello", 10, 20, nullptr);    // we don't flatten this in the paint
433fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        add_run(&builder, "World", 10, 40, tf);         // we will flatten this in the paint
434fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return builder.make();
435fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }();
436fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
437fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkTDArray<SkTypeface*> array;
438fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp<SkData> data = blob0->serialize([](SkTypeface* tf, void* ctx) {
439fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        auto array = (SkTDArray<SkTypeface*>*)ctx;
440fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (array->find(tf) < 0) {
441fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            *array->append() = tf;
442fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
443fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }, &array);
444fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // we only expect 1, since null would not have been serialized, but the default would
445fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    REPORTER_ASSERT(reporter, array.count() == 1);
446fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
447fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp<SkTextBlob> blob1 = SkTextBlob::Deserialize(data->data(), data->size(),
448fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                      [](uint32_t uniqueID, void* ctx) {
449fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        auto array = (SkTDArray<SkTypeface*>*)ctx;
450fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int i = 0; i < array->count(); ++i) {
451fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if ((*array)[i]->uniqueID() == uniqueID) {
452fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                return sk_ref_sp((*array)[i]);
453fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
454fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
455fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(false);
456fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return sk_sp<SkTypeface>(nullptr);
457fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }, &array);
458fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
459fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp<SkImage> img0 = render(blob0.get());
460fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp<SkImage> img1 = render(blob1.get());
461fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (img0 && img1) {
462fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        REPORTER_ASSERT(reporter, sk_tool_utils::equal_pixels(img0.get(), img1.get()));
463fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
464fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
465