1c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita/*
2c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita * Copyright 2014 Google Inc.
3c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita *
4c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita * Use of this source code is governed by a BSD-style license that can be
5c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita * found in the LICENSE file.
6c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita */
7c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita
8c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita#include "SkPaint.h"
9c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita#include "SkPoint.h"
10337797580de42cdb722caab4bed121311ed7d0d2halcanary#include "SkTextBlobRunIterator.h"
1132d6b876163580711a07e96d9f29c9c1490a7271fmalita#include "SkTypeface.h"
12c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita
13c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita#include "Test.h"
144bcef3c40ad8d3a16bbca4ab74fa15256fb4b125Mike Reed#include "sk_tool_utils.h"
15c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita
16c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalitaclass TextBlobTester {
17c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalitapublic:
1851bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita    // This unit test feeds an SkTextBlobBuilder various runs then checks to see if
1951bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita    // the result contains the provided data and merges runs when appropriate.
2051bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita    static void TestBuilder(skiatest::Reporter* reporter) {
21c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita        SkTextBlobBuilder builder;
22c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita
23c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita        // empty run set
2496fcdcc219d2a0d3579719b84b28bede76efba64halcanary        RunBuilderTest(reporter, builder, nullptr, 0, nullptr, 0);
25c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita
2651bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita        RunDef set1[] = {
27c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            { 128, SkTextBlob::kDefault_Positioning, 100, 100 },
28c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita        };
2951bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita        RunBuilderTest(reporter, builder, set1, SK_ARRAY_COUNT(set1), set1, SK_ARRAY_COUNT(set1));
30c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita
3151bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita        RunDef set2[] = {
32c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            { 128, SkTextBlob::kHorizontal_Positioning, 100, 100 },
33c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita        };
3451bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita        RunBuilderTest(reporter, builder, set2, SK_ARRAY_COUNT(set2), set2, SK_ARRAY_COUNT(set2));
35c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita
3651bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita        RunDef set3[] = {
37c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            { 128, SkTextBlob::kFull_Positioning, 100, 100 },
38c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita        };
3951bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita        RunBuilderTest(reporter, builder, set3, SK_ARRAY_COUNT(set3), set3, SK_ARRAY_COUNT(set3));
40c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita
4151bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita        RunDef set4[] = {
42c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            { 128, SkTextBlob::kDefault_Positioning, 100, 150 },
43c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            { 128, SkTextBlob::kDefault_Positioning, 100, 150 },
44c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            { 128, SkTextBlob::kDefault_Positioning, 100, 150 },
45c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita        };
4651bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita        RunBuilderTest(reporter, builder, set4, SK_ARRAY_COUNT(set4), set4, SK_ARRAY_COUNT(set4));
47c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita
4851bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita        RunDef set5[] = {
49c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            { 128, SkTextBlob::kHorizontal_Positioning, 100, 150 },
50c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            { 128, SkTextBlob::kHorizontal_Positioning, 200, 150 },
51c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            { 128, SkTextBlob::kHorizontal_Positioning, 300, 250 },
52c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita        };
5351bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita        RunDef mergedSet5[] = {
54c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            { 256, SkTextBlob::kHorizontal_Positioning, 0, 150 },
55c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            { 128, SkTextBlob::kHorizontal_Positioning, 0, 250 },
56c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita        };
5751bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita        RunBuilderTest(reporter, builder, set5, SK_ARRAY_COUNT(set5), mergedSet5,
5851bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita                       SK_ARRAY_COUNT(mergedSet5));
59c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita
6051bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita        RunDef set6[] = {
61c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            { 128, SkTextBlob::kFull_Positioning, 100, 100 },
62c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            { 128, SkTextBlob::kFull_Positioning, 200, 200 },
63c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            { 128, SkTextBlob::kFull_Positioning, 300, 300 },
64c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita        };
6551bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita        RunDef mergedSet6[] = {
66c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            { 384, SkTextBlob::kFull_Positioning, 0, 0 },
67c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita        };
6851bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita        RunBuilderTest(reporter, builder, set6, SK_ARRAY_COUNT(set6), mergedSet6,
6951bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita                       SK_ARRAY_COUNT(mergedSet6));
70c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita
7151bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita        RunDef set7[] = {
72c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            { 128, SkTextBlob::kDefault_Positioning, 100, 150 },
73c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            { 128, SkTextBlob::kDefault_Positioning, 100, 150 },
74c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            { 128, SkTextBlob::kHorizontal_Positioning, 100, 150 },
75c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            { 128, SkTextBlob::kHorizontal_Positioning, 200, 150 },
76c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            { 128, SkTextBlob::kFull_Positioning, 400, 350 },
77c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            { 128, SkTextBlob::kFull_Positioning, 400, 350 },
78c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            { 128, SkTextBlob::kDefault_Positioning, 100, 450 },
79c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            { 128, SkTextBlob::kDefault_Positioning, 100, 450 },
80c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            { 128, SkTextBlob::kHorizontal_Positioning, 100, 550 },
81c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            { 128, SkTextBlob::kHorizontal_Positioning, 200, 650 },
82c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            { 128, SkTextBlob::kFull_Positioning, 400, 750 },
83c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            { 128, SkTextBlob::kFull_Positioning, 400, 850 },
84c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita        };
8551bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita        RunDef mergedSet7[] = {
86c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            { 128, SkTextBlob::kDefault_Positioning, 100, 150 },
87c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            { 128, SkTextBlob::kDefault_Positioning, 100, 150 },
88c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            { 256, SkTextBlob::kHorizontal_Positioning, 0, 150 },
89c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            { 256, SkTextBlob::kFull_Positioning, 0, 0 },
90c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            { 128, SkTextBlob::kDefault_Positioning, 100, 450 },
91c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            { 128, SkTextBlob::kDefault_Positioning, 100, 450 },
92c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            { 128, SkTextBlob::kHorizontal_Positioning, 0, 550 },
93c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            { 128, SkTextBlob::kHorizontal_Positioning, 0, 650 },
94c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            { 256, SkTextBlob::kFull_Positioning, 0, 0 },
95c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita        };
9651bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita        RunBuilderTest(reporter, builder, set7, SK_ARRAY_COUNT(set7), mergedSet7,
9751bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita                       SK_ARRAY_COUNT(mergedSet7));
9851bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita    }
9951bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita
10051bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita    // This unit test verifies blob bounds computation.
10151bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita    static void TestBounds(skiatest::Reporter* reporter) {
10251bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita        SkTextBlobBuilder builder;
10351bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita        SkPaint font;
10451bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita        font.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
10551bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita
10651bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita        // Explicit bounds.
10751bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita        {
10837283c28aa5bea2204c18956e74f83b238d7a891fmalita            sk_sp<SkTextBlob> blob(builder.make());
1093a9a7a310c5cff72bc1c2388a496af1b82326355Florin Malita            REPORTER_ASSERT(reporter, !blob);
11051bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita        }
11151bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita
11251bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita        {
11351bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita            SkRect r1 = SkRect::MakeXYWH(10, 10, 20, 20);
11451bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita            builder.allocRun(font, 16, 0, 0, &r1);
11537283c28aa5bea2204c18956e74f83b238d7a891fmalita            sk_sp<SkTextBlob> blob(builder.make());
11651bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita            REPORTER_ASSERT(reporter, blob->bounds() == r1);
11751bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita        }
11851bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita
11951bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita        {
12051bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita            SkRect r1 = SkRect::MakeXYWH(10, 10, 20, 20);
12151bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita            builder.allocRunPosH(font, 16, 0, &r1);
12237283c28aa5bea2204c18956e74f83b238d7a891fmalita            sk_sp<SkTextBlob> blob(builder.make());
12351bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita            REPORTER_ASSERT(reporter, blob->bounds() == r1);
12451bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita        }
12551bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita
12651bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita        {
12751bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita            SkRect r1 = SkRect::MakeXYWH(10, 10, 20, 20);
12851bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita            builder.allocRunPos(font, 16, &r1);
12937283c28aa5bea2204c18956e74f83b238d7a891fmalita            sk_sp<SkTextBlob> blob(builder.make());
13051bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita            REPORTER_ASSERT(reporter, blob->bounds() == r1);
13151bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita        }
13251bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita
13351bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita        {
13451bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita            SkRect r1 = SkRect::MakeXYWH(10, 10, 20, 20);
13551bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita            SkRect r2 = SkRect::MakeXYWH(15, 20, 50, 50);
13651bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita            SkRect r3 = SkRect::MakeXYWH(0, 5, 10, 5);
13751bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita
13851bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita            builder.allocRun(font, 16, 0, 0, &r1);
13951bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita            builder.allocRunPosH(font, 16, 0, &r2);
14051bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita            builder.allocRunPos(font, 16, &r3);
14151bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita
14237283c28aa5bea2204c18956e74f83b238d7a891fmalita            sk_sp<SkTextBlob> blob(builder.make());
14351bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita            REPORTER_ASSERT(reporter, blob->bounds() == SkRect::MakeXYWH(0, 5, 65, 65));
14451bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita        }
14551bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita
14651bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita        {
14737283c28aa5bea2204c18956e74f83b238d7a891fmalita            sk_sp<SkTextBlob> blob(builder.make());
1483a9a7a310c5cff72bc1c2388a496af1b82326355Florin Malita            REPORTER_ASSERT(reporter, !blob);
14951bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita        }
15051bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita
15151bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita        // Implicit bounds
1529ae8fe1c601ecb7fef9962f9eb1adf11032378e4fmalita
1539ae8fe1c601ecb7fef9962f9eb1adf11032378e4fmalita        {
1549ae8fe1c601ecb7fef9962f9eb1adf11032378e4fmalita            // Exercise the empty bounds path, and ensure that RunRecord-aligned pos buffers
1559ae8fe1c601ecb7fef9962f9eb1adf11032378e4fmalita            // don't trigger asserts (http://crbug.com/542643).
1569ae8fe1c601ecb7fef9962f9eb1adf11032378e4fmalita            SkPaint p;
1579ae8fe1c601ecb7fef9962f9eb1adf11032378e4fmalita            p.setTextSize(0);
1580b01da7bca9dacdd58affe5d5433860cb3d59194fmalita            p.setTextEncoding(SkPaint::kUTF8_TextEncoding);
1599ae8fe1c601ecb7fef9962f9eb1adf11032378e4fmalita
1609ae8fe1c601ecb7fef9962f9eb1adf11032378e4fmalita            const char* txt = "BOOO";
1610b01da7bca9dacdd58affe5d5433860cb3d59194fmalita            const size_t txtLen = strlen(txt);
1620b01da7bca9dacdd58affe5d5433860cb3d59194fmalita            const int glyphCount = p.textToGlyphs(txt, txtLen, nullptr);
1630b01da7bca9dacdd58affe5d5433860cb3d59194fmalita
1640b01da7bca9dacdd58affe5d5433860cb3d59194fmalita            p.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
1650b01da7bca9dacdd58affe5d5433860cb3d59194fmalita            const SkTextBlobBuilder::RunBuffer& buffer = builder.allocRunPos(p, glyphCount);
1660b01da7bca9dacdd58affe5d5433860cb3d59194fmalita
1670b01da7bca9dacdd58affe5d5433860cb3d59194fmalita            p.setTextEncoding(SkPaint::kUTF8_TextEncoding);
1680b01da7bca9dacdd58affe5d5433860cb3d59194fmalita            p.textToGlyphs(txt, txtLen, buffer.glyphs);
1690b01da7bca9dacdd58affe5d5433860cb3d59194fmalita
1700b01da7bca9dacdd58affe5d5433860cb3d59194fmalita            memset(buffer.pos, 0, sizeof(SkScalar) * glyphCount * 2);
17137283c28aa5bea2204c18956e74f83b238d7a891fmalita            sk_sp<SkTextBlob> blob(builder.make());
1729ae8fe1c601ecb7fef9962f9eb1adf11032378e4fmalita            REPORTER_ASSERT(reporter, blob->bounds().isEmpty());
1739ae8fe1c601ecb7fef9962f9eb1adf11032378e4fmalita        }
174c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita    }
175c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita
17632d6b876163580711a07e96d9f29c9c1490a7271fmalita    // Verify that text-related properties are captured in run paints.
17732d6b876163580711a07e96d9f29c9c1490a7271fmalita    static void TestPaintProps(skiatest::Reporter* reporter) {
17832d6b876163580711a07e96d9f29c9c1490a7271fmalita        SkPaint font;
17932d6b876163580711a07e96d9f29c9c1490a7271fmalita        font.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
18032d6b876163580711a07e96d9f29c9c1490a7271fmalita
18132d6b876163580711a07e96d9f29c9c1490a7271fmalita        // Kitchen sink font.
18232d6b876163580711a07e96d9f29c9c1490a7271fmalita        font.setTextSize(42);
18332d6b876163580711a07e96d9f29c9c1490a7271fmalita        font.setTextScaleX(4.2f);
18413b9c95295f4c5732e34574789e721a6bc08f7b4bungeman        font.setTypeface(SkTypeface::MakeDefault());
18532d6b876163580711a07e96d9f29c9c1490a7271fmalita        font.setTextSkewX(0.42f);
18632d6b876163580711a07e96d9f29c9c1490a7271fmalita        font.setTextAlign(SkPaint::kCenter_Align);
18732d6b876163580711a07e96d9f29c9c1490a7271fmalita        font.setHinting(SkPaint::kFull_Hinting);
18832d6b876163580711a07e96d9f29c9c1490a7271fmalita        font.setAntiAlias(true);
18932d6b876163580711a07e96d9f29c9c1490a7271fmalita        font.setFakeBoldText(true);
19032d6b876163580711a07e96d9f29c9c1490a7271fmalita        font.setLinearText(true);
19132d6b876163580711a07e96d9f29c9c1490a7271fmalita        font.setSubpixelText(true);
19232d6b876163580711a07e96d9f29c9c1490a7271fmalita        font.setDevKernText(true);
19332d6b876163580711a07e96d9f29c9c1490a7271fmalita        font.setLCDRenderText(true);
19432d6b876163580711a07e96d9f29c9c1490a7271fmalita        font.setEmbeddedBitmapText(true);
19532d6b876163580711a07e96d9f29c9c1490a7271fmalita        font.setAutohinted(true);
19632d6b876163580711a07e96d9f29c9c1490a7271fmalita        font.setVerticalText(true);
19732d6b876163580711a07e96d9f29c9c1490a7271fmalita        font.setFlags(font.getFlags() | SkPaint::kGenA8FromLCD_Flag);
19832d6b876163580711a07e96d9f29c9c1490a7271fmalita
19932d6b876163580711a07e96d9f29c9c1490a7271fmalita        // Ensure we didn't pick default values by mistake.
20032d6b876163580711a07e96d9f29c9c1490a7271fmalita        SkPaint defaultPaint;
20132d6b876163580711a07e96d9f29c9c1490a7271fmalita        REPORTER_ASSERT(reporter, defaultPaint.getTextSize() != font.getTextSize());
20232d6b876163580711a07e96d9f29c9c1490a7271fmalita        REPORTER_ASSERT(reporter, defaultPaint.getTextScaleX() != font.getTextScaleX());
20332d6b876163580711a07e96d9f29c9c1490a7271fmalita        REPORTER_ASSERT(reporter, defaultPaint.getTypeface() != font.getTypeface());
20432d6b876163580711a07e96d9f29c9c1490a7271fmalita        REPORTER_ASSERT(reporter, defaultPaint.getTextSkewX() != font.getTextSkewX());
20532d6b876163580711a07e96d9f29c9c1490a7271fmalita        REPORTER_ASSERT(reporter, defaultPaint.getTextAlign() != font.getTextAlign());
20632d6b876163580711a07e96d9f29c9c1490a7271fmalita        REPORTER_ASSERT(reporter, defaultPaint.getHinting() != font.getHinting());
20732d6b876163580711a07e96d9f29c9c1490a7271fmalita        REPORTER_ASSERT(reporter, defaultPaint.isAntiAlias() != font.isAntiAlias());
20832d6b876163580711a07e96d9f29c9c1490a7271fmalita        REPORTER_ASSERT(reporter, defaultPaint.isFakeBoldText() != font.isFakeBoldText());
20932d6b876163580711a07e96d9f29c9c1490a7271fmalita        REPORTER_ASSERT(reporter, defaultPaint.isLinearText() != font.isLinearText());
21032d6b876163580711a07e96d9f29c9c1490a7271fmalita        REPORTER_ASSERT(reporter, defaultPaint.isSubpixelText() != font.isSubpixelText());
21132d6b876163580711a07e96d9f29c9c1490a7271fmalita        REPORTER_ASSERT(reporter, defaultPaint.isDevKernText() != font.isDevKernText());
21232d6b876163580711a07e96d9f29c9c1490a7271fmalita        REPORTER_ASSERT(reporter, defaultPaint.isLCDRenderText() != font.isLCDRenderText());
21332d6b876163580711a07e96d9f29c9c1490a7271fmalita        REPORTER_ASSERT(reporter, defaultPaint.isEmbeddedBitmapText() != font.isEmbeddedBitmapText());
21432d6b876163580711a07e96d9f29c9c1490a7271fmalita        REPORTER_ASSERT(reporter, defaultPaint.isAutohinted() != font.isAutohinted());
21532d6b876163580711a07e96d9f29c9c1490a7271fmalita        REPORTER_ASSERT(reporter, defaultPaint.isVerticalText() != font.isVerticalText());
21632d6b876163580711a07e96d9f29c9c1490a7271fmalita        REPORTER_ASSERT(reporter, (defaultPaint.getFlags() & SkPaint::kGenA8FromLCD_Flag) !=
21732d6b876163580711a07e96d9f29c9c1490a7271fmalita                                  (font.getFlags() & SkPaint::kGenA8FromLCD_Flag));
21832d6b876163580711a07e96d9f29c9c1490a7271fmalita
21932d6b876163580711a07e96d9f29c9c1490a7271fmalita        SkTextBlobBuilder builder;
22032d6b876163580711a07e96d9f29c9c1490a7271fmalita        AddRun(font, 1, SkTextBlob::kDefault_Positioning, SkPoint::Make(0, 0), builder);
22132d6b876163580711a07e96d9f29c9c1490a7271fmalita        AddRun(font, 1, SkTextBlob::kHorizontal_Positioning, SkPoint::Make(0, 0), builder);
22232d6b876163580711a07e96d9f29c9c1490a7271fmalita        AddRun(font, 1, SkTextBlob::kFull_Positioning, SkPoint::Make(0, 0), builder);
22337283c28aa5bea2204c18956e74f83b238d7a891fmalita        sk_sp<SkTextBlob> blob(builder.make());
22432d6b876163580711a07e96d9f29c9c1490a7271fmalita
22537283c28aa5bea2204c18956e74f83b238d7a891fmalita        SkTextBlobRunIterator it(blob.get());
22632d6b876163580711a07e96d9f29c9c1490a7271fmalita        while (!it.done()) {
22732d6b876163580711a07e96d9f29c9c1490a7271fmalita            SkPaint paint;
22832d6b876163580711a07e96d9f29c9c1490a7271fmalita            it.applyFontToPaint(&paint);
22932d6b876163580711a07e96d9f29c9c1490a7271fmalita
23032d6b876163580711a07e96d9f29c9c1490a7271fmalita            REPORTER_ASSERT(reporter, paint.getTextSize() == font.getTextSize());
23132d6b876163580711a07e96d9f29c9c1490a7271fmalita            REPORTER_ASSERT(reporter, paint.getTextScaleX() == font.getTextScaleX());
23232d6b876163580711a07e96d9f29c9c1490a7271fmalita            REPORTER_ASSERT(reporter, paint.getTypeface() == font.getTypeface());
23332d6b876163580711a07e96d9f29c9c1490a7271fmalita            REPORTER_ASSERT(reporter, paint.getTextSkewX() == font.getTextSkewX());
23432d6b876163580711a07e96d9f29c9c1490a7271fmalita            REPORTER_ASSERT(reporter, paint.getTextAlign() == font.getTextAlign());
23532d6b876163580711a07e96d9f29c9c1490a7271fmalita            REPORTER_ASSERT(reporter, paint.getHinting() == font.getHinting());
23632d6b876163580711a07e96d9f29c9c1490a7271fmalita            REPORTER_ASSERT(reporter, paint.isAntiAlias() == font.isAntiAlias());
23732d6b876163580711a07e96d9f29c9c1490a7271fmalita            REPORTER_ASSERT(reporter, paint.isFakeBoldText() == font.isFakeBoldText());
23832d6b876163580711a07e96d9f29c9c1490a7271fmalita            REPORTER_ASSERT(reporter, paint.isLinearText() == font.isLinearText());
23932d6b876163580711a07e96d9f29c9c1490a7271fmalita            REPORTER_ASSERT(reporter, paint.isSubpixelText() == font.isSubpixelText());
24032d6b876163580711a07e96d9f29c9c1490a7271fmalita            REPORTER_ASSERT(reporter, paint.isDevKernText() == font.isDevKernText());
24132d6b876163580711a07e96d9f29c9c1490a7271fmalita            REPORTER_ASSERT(reporter, paint.isLCDRenderText() == font.isLCDRenderText());
24232d6b876163580711a07e96d9f29c9c1490a7271fmalita            REPORTER_ASSERT(reporter, paint.isEmbeddedBitmapText() == font.isEmbeddedBitmapText());
24332d6b876163580711a07e96d9f29c9c1490a7271fmalita            REPORTER_ASSERT(reporter, paint.isAutohinted() == font.isAutohinted());
24432d6b876163580711a07e96d9f29c9c1490a7271fmalita            REPORTER_ASSERT(reporter, paint.isVerticalText() == font.isVerticalText());
24532d6b876163580711a07e96d9f29c9c1490a7271fmalita            REPORTER_ASSERT(reporter, (paint.getFlags() & SkPaint::kGenA8FromLCD_Flag) ==
24632d6b876163580711a07e96d9f29c9c1490a7271fmalita                                      (font.getFlags() & SkPaint::kGenA8FromLCD_Flag));
24732d6b876163580711a07e96d9f29c9c1490a7271fmalita
24832d6b876163580711a07e96d9f29c9c1490a7271fmalita            it.next();
24932d6b876163580711a07e96d9f29c9c1490a7271fmalita        }
25032d6b876163580711a07e96d9f29c9c1490a7271fmalita
25132d6b876163580711a07e96d9f29c9c1490a7271fmalita    }
25232d6b876163580711a07e96d9f29c9c1490a7271fmalita
253c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalitaprivate:
254c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita    struct RunDef {
255c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita        unsigned                     count;
256c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita        SkTextBlob::GlyphPositioning pos;
257c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita        SkScalar                     x, y;
258c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita    };
259c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita
26051bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita    static void RunBuilderTest(skiatest::Reporter* reporter, SkTextBlobBuilder& builder,
261c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita                               const RunDef in[], unsigned inCount,
262c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita                               const RunDef out[], unsigned outCount) {
26351bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita        SkPaint font;
26451bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita        font.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
26551bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita
266c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita        unsigned glyphCount = 0;
267c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita        unsigned posCount = 0;
268c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita
269c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita        for (unsigned i = 0; i < inCount; ++i) {
27051bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita            AddRun(font, in[i].count, in[i].pos, SkPoint::Make(in[i].x, in[i].y), builder);
271c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            glyphCount += in[i].count;
272c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            posCount += in[i].count * in[i].pos;
273c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita        }
274c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita
27537283c28aa5bea2204c18956e74f83b238d7a891fmalita        sk_sp<SkTextBlob> blob(builder.make());
2763a9a7a310c5cff72bc1c2388a496af1b82326355Florin Malita        REPORTER_ASSERT(reporter, (inCount > 0) == SkToBool(blob));
2773a9a7a310c5cff72bc1c2388a496af1b82326355Florin Malita        if (!blob) {
2783a9a7a310c5cff72bc1c2388a496af1b82326355Florin Malita            return;
2793a9a7a310c5cff72bc1c2388a496af1b82326355Florin Malita        }
280c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita
28137283c28aa5bea2204c18956e74f83b238d7a891fmalita        SkTextBlobRunIterator it(blob.get());
282c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita        for (unsigned i = 0; i < outCount; ++i) {
283c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            REPORTER_ASSERT(reporter, !it.done());
284c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            REPORTER_ASSERT(reporter, out[i].pos == it.positioning());
285c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            REPORTER_ASSERT(reporter, out[i].count == it.glyphCount());
286c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            if (SkTextBlob::kDefault_Positioning == out[i].pos) {
287c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita                REPORTER_ASSERT(reporter, out[i].x == it.offset().x());
288c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita                REPORTER_ASSERT(reporter, out[i].y == it.offset().y());
289c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            } else if (SkTextBlob::kHorizontal_Positioning == out[i].pos) {
290c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita                REPORTER_ASSERT(reporter, out[i].y == it.offset().y());
291c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            }
292c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita
293c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            for (unsigned k = 0; k < it.glyphCount(); ++k) {
294c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita                REPORTER_ASSERT(reporter, k % 128 == it.glyphs()[k]);
295c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita                if (SkTextBlob::kHorizontal_Positioning == it.positioning()) {
296c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita                    REPORTER_ASSERT(reporter, SkIntToScalar(k % 128) == it.pos()[k]);
297c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita                } else if (SkTextBlob::kFull_Positioning == it.positioning()) {
298c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita                    REPORTER_ASSERT(reporter, SkIntToScalar(k % 128) == it.pos()[k * 2]);
299c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita                    REPORTER_ASSERT(reporter, -SkIntToScalar(k % 128) == it.pos()[k * 2 + 1]);
300c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita                }
301c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            }
302c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita
303c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            it.next();
304c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita        }
305c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita
306c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita        REPORTER_ASSERT(reporter, it.done());
307c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita    }
308c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita
30951bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita    static void AddRun(const SkPaint& font, int count, SkTextBlob::GlyphPositioning pos,
310c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita                       const SkPoint& offset, SkTextBlobBuilder& builder,
31196fcdcc219d2a0d3579719b84b28bede76efba64halcanary                       const SkRect* bounds = nullptr) {
312c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita        switch (pos) {
313c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita        case SkTextBlob::kDefault_Positioning: {
314c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            const SkTextBlobBuilder::RunBuffer& rb = builder.allocRun(font, count, offset.x(),
315c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita                                                                      offset.y(), bounds);
316c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            for (int i = 0; i < count; ++i) {
317c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita                rb.glyphs[i] = i;
318c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            }
319c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita        } break;
320c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita        case SkTextBlob::kHorizontal_Positioning: {
321c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            const SkTextBlobBuilder::RunBuffer& rb = builder.allocRunPosH(font, count, offset.y(),
322c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita                                                                          bounds);
323c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            for (int i = 0; i < count; ++i) {
324c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita                rb.glyphs[i] = i;
325c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita                rb.pos[i] = SkIntToScalar(i);
326c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            }
327c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita        } break;
328c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita        case SkTextBlob::kFull_Positioning: {
329c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            const SkTextBlobBuilder::RunBuffer& rb = builder.allocRunPos(font, count, bounds);
330c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            for (int i = 0; i < count; ++i) {
331c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita                rb.glyphs[i] = i;
332c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita                rb.pos[i * 2] = SkIntToScalar(i);
333c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita                rb.pos[i * 2 + 1] = -SkIntToScalar(i);
334c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita            }
335c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita        } break;
336c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita        default:
337b4aab9ae6d27c446af8302b79d15b832c816c633Ben Wagner            SK_ABORT("unhandled positioning value");
338c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita        }
339c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita    }
340c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita};
341c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita
342c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalitaDEF_TEST(TextBlob_builder, reporter) {
34351bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita    TextBlobTester::TestBuilder(reporter);
34451bf9573b8b875aec47cbeb9f4649f58bcbf56b7fmalita    TextBlobTester::TestBounds(reporter);
345c6765d69e3aceaa316fe2d2ef00a7f0d138def2ffmalita}
34632d6b876163580711a07e96d9f29c9c1490a7271fmalita
34732d6b876163580711a07e96d9f29c9c1490a7271fmalitaDEF_TEST(TextBlob_paint, reporter) {
34832d6b876163580711a07e96d9f29c9c1490a7271fmalita    TextBlobTester::TestPaintProps(reporter);
34932d6b876163580711a07e96d9f29c9c1490a7271fmalita}
3504f0a23a8d54f5eb0fdacfff7c109b9045b548978halcanary
3514f0a23a8d54f5eb0fdacfff7c109b9045b548978halcanaryDEF_TEST(TextBlob_extended, reporter) {
3524f0a23a8d54f5eb0fdacfff7c109b9045b548978halcanary    SkTextBlobBuilder textBlobBuilder;
3534f0a23a8d54f5eb0fdacfff7c109b9045b548978halcanary    SkPaint paint;
3544f0a23a8d54f5eb0fdacfff7c109b9045b548978halcanary    const char text1[] = "Foo";
3554f0a23a8d54f5eb0fdacfff7c109b9045b548978halcanary    const char text2[] = "Bar";
3564f0a23a8d54f5eb0fdacfff7c109b9045b548978halcanary
3574f0a23a8d54f5eb0fdacfff7c109b9045b548978halcanary    int glyphCount = paint.textToGlyphs(text1, strlen(text1), nullptr);
3584f0a23a8d54f5eb0fdacfff7c109b9045b548978halcanary    SkAutoTMalloc<uint16_t> glyphs(glyphCount);
3594f0a23a8d54f5eb0fdacfff7c109b9045b548978halcanary    (void)paint.textToGlyphs(text1, strlen(text1), glyphs.get());
3604f0a23a8d54f5eb0fdacfff7c109b9045b548978halcanary    paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
3614f0a23a8d54f5eb0fdacfff7c109b9045b548978halcanary
3624f0a23a8d54f5eb0fdacfff7c109b9045b548978halcanary    auto run = textBlobBuilder.allocRunText(
3634f0a23a8d54f5eb0fdacfff7c109b9045b548978halcanary            paint, glyphCount, 0, 0, SkToInt(strlen(text2)), SkString(), nullptr);
3644f0a23a8d54f5eb0fdacfff7c109b9045b548978halcanary    memcpy(run.glyphs, glyphs.get(), sizeof(uint16_t) * glyphCount);
3654f0a23a8d54f5eb0fdacfff7c109b9045b548978halcanary    memcpy(run.utf8text, text2, strlen(text2));
3664f0a23a8d54f5eb0fdacfff7c109b9045b548978halcanary    for (int i = 0; i < glyphCount; ++i) {
3674f0a23a8d54f5eb0fdacfff7c109b9045b548978halcanary        run.clusters[i] = SkTMin(SkToU32(i), SkToU32(strlen(text2)));
3684f0a23a8d54f5eb0fdacfff7c109b9045b548978halcanary    }
36937283c28aa5bea2204c18956e74f83b238d7a891fmalita    sk_sp<SkTextBlob> blob(textBlobBuilder.make());
3704f0a23a8d54f5eb0fdacfff7c109b9045b548978halcanary    REPORTER_ASSERT(reporter, blob);
3714f0a23a8d54f5eb0fdacfff7c109b9045b548978halcanary
3724f0a23a8d54f5eb0fdacfff7c109b9045b548978halcanary    for (SkTextBlobRunIterator it(blob.get()); !it.done(); it.next()) {
3734f0a23a8d54f5eb0fdacfff7c109b9045b548978halcanary        REPORTER_ASSERT(reporter, it.glyphCount() == (uint32_t)glyphCount);
3744f0a23a8d54f5eb0fdacfff7c109b9045b548978halcanary        for (uint32_t i = 0; i < it.glyphCount(); ++i) {
3754f0a23a8d54f5eb0fdacfff7c109b9045b548978halcanary            REPORTER_ASSERT(reporter, it.glyphs()[i] == glyphs[i]);
3764f0a23a8d54f5eb0fdacfff7c109b9045b548978halcanary        }
3774f0a23a8d54f5eb0fdacfff7c109b9045b548978halcanary        REPORTER_ASSERT(reporter, SkTextBlob::kDefault_Positioning == it.positioning());
3784f0a23a8d54f5eb0fdacfff7c109b9045b548978halcanary        REPORTER_ASSERT(reporter, (SkPoint{0.0f, 0.0f}) == it.offset());
3794f0a23a8d54f5eb0fdacfff7c109b9045b548978halcanary        REPORTER_ASSERT(reporter, it.textSize() > 0);
3804f0a23a8d54f5eb0fdacfff7c109b9045b548978halcanary        REPORTER_ASSERT(reporter, it.clusters());
3814f0a23a8d54f5eb0fdacfff7c109b9045b548978halcanary        for (uint32_t i = 0; i < it.glyphCount(); ++i) {
3824f0a23a8d54f5eb0fdacfff7c109b9045b548978halcanary            REPORTER_ASSERT(reporter, i == it.clusters()[i]);
3834f0a23a8d54f5eb0fdacfff7c109b9045b548978halcanary        }
3844f0a23a8d54f5eb0fdacfff7c109b9045b548978halcanary        REPORTER_ASSERT(reporter, 0 == strncmp(text2, it.text(), it.textSize()));
3854f0a23a8d54f5eb0fdacfff7c109b9045b548978halcanary    }
3864f0a23a8d54f5eb0fdacfff7c109b9045b548978halcanary}
387b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed
388b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed///////////////////////////////////////////////////////////////////////////////////////////////////
389b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed#include "SkCanvas.h"
390b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed#include "SkSurface.h"
391b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed#include "SkTDArray.h"
392b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed
393b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reedstatic void add_run(SkTextBlobBuilder* builder, const char text[], SkScalar x, SkScalar y,
394b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed                    sk_sp<SkTypeface> tf) {
395b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed    SkPaint paint;
396b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed    paint.setAntiAlias(true);
397b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed    paint.setSubpixelText(true);
398b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed    paint.setTextSize(16);
399b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed    paint.setTypeface(tf);
400b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed
401b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed    int glyphCount = paint.textToGlyphs(text, strlen(text), nullptr);
402b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed
403b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed    paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
404b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed    SkTextBlobBuilder::RunBuffer buffer = builder->allocRun(paint, glyphCount, x, y);
405b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed
406b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed    paint.setTextEncoding(SkPaint::kUTF8_TextEncoding);
407b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed    (void)paint.textToGlyphs(text, strlen(text), buffer.glyphs);
408b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed}
409b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed
410b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reedstatic sk_sp<SkImage> render(const SkTextBlob* blob) {
411b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed    auto surf = SkSurface::MakeRasterN32Premul(SkScalarRoundToInt(blob->bounds().width()),
412b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed                                               SkScalarRoundToInt(blob->bounds().height()));
4137e49d534d71d3e7b053fe6f23dfe018ddbceb45bMike Reed    if (!surf) {
4147e49d534d71d3e7b053fe6f23dfe018ddbceb45bMike Reed        return nullptr; // bounds are empty?
4157e49d534d71d3e7b053fe6f23dfe018ddbceb45bMike Reed    }
416b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed    surf->getCanvas()->clear(SK_ColorWHITE);
417b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed    surf->getCanvas()->drawTextBlob(blob, -blob->bounds().left(), -blob->bounds().top(), SkPaint());
418b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed    return surf->makeImageSnapshot();
419b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed}
420b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed
421b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed/*
422b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed *  Build a blob with more than one typeface.
423b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed *  Draw it into an offscreen,
424b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed *  then serialize and deserialize,
425b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed *  Then draw the new instance and assert it draws the same as the original.
426b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed */
427b99beddc7a0f6003d6dd88119e7f2734fc508322Mike ReedDEF_TEST(TextBlob_serialize, reporter) {
4284bcef3c40ad8d3a16bbca4ab74fa15256fb4b125Mike Reed    sk_sp<SkTextBlob> blob0 = []() {
4298e74cbcd6526a7542b9f704b9e40b0c60d475849Mike Reed        sk_sp<SkTypeface> tf = SkTypeface::MakeDefault();
430b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed
4314bcef3c40ad8d3a16bbca4ab74fa15256fb4b125Mike Reed        SkTextBlobBuilder builder;
4328e74cbcd6526a7542b9f704b9e40b0c60d475849Mike Reed        add_run(&builder, "Hello", 10, 20, nullptr);    // we don't flatten this in the paint
4338e74cbcd6526a7542b9f704b9e40b0c60d475849Mike Reed        add_run(&builder, "World", 10, 40, tf);         // we will flatten this in the paint
4344bcef3c40ad8d3a16bbca4ab74fa15256fb4b125Mike Reed        return builder.make();
4354bcef3c40ad8d3a16bbca4ab74fa15256fb4b125Mike Reed    }();
436b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed
437b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed    SkTDArray<SkTypeface*> array;
438aaa3056e46ed9004097dc784db94c3a97d070569Mike Reed    sk_sp<SkData> data = blob0->serialize([](SkTypeface* tf, void* ctx) {
439aaa3056e46ed9004097dc784db94c3a97d070569Mike Reed        auto array = (SkTDArray<SkTypeface*>*)ctx;
440aaa3056e46ed9004097dc784db94c3a97d070569Mike Reed        if (array->find(tf) < 0) {
441aaa3056e46ed9004097dc784db94c3a97d070569Mike Reed            *array->append() = tf;
442b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed        }
443aaa3056e46ed9004097dc784db94c3a97d070569Mike Reed    }, &array);
4448e74cbcd6526a7542b9f704b9e40b0c60d475849Mike Reed    // we only expect 1, since null would not have been serialized, but the default would
4458e74cbcd6526a7542b9f704b9e40b0c60d475849Mike Reed    REPORTER_ASSERT(reporter, array.count() == 1);
446b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed
447b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed    sk_sp<SkTextBlob> blob1 = SkTextBlob::Deserialize(data->data(), data->size(),
448aaa3056e46ed9004097dc784db94c3a97d070569Mike Reed                                                      [](uint32_t uniqueID, void* ctx) {
449aaa3056e46ed9004097dc784db94c3a97d070569Mike Reed        auto array = (SkTDArray<SkTypeface*>*)ctx;
450aaa3056e46ed9004097dc784db94c3a97d070569Mike Reed        for (int i = 0; i < array->count(); ++i) {
451aaa3056e46ed9004097dc784db94c3a97d070569Mike Reed            if ((*array)[i]->uniqueID() == uniqueID) {
452aaa3056e46ed9004097dc784db94c3a97d070569Mike Reed                return sk_ref_sp((*array)[i]);
453b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed            }
454b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed        }
455aaa3056e46ed9004097dc784db94c3a97d070569Mike Reed        SkASSERT(false);
456b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed        return sk_sp<SkTypeface>(nullptr);
457aaa3056e46ed9004097dc784db94c3a97d070569Mike Reed    }, &array);
458b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed
4597e49d534d71d3e7b053fe6f23dfe018ddbceb45bMike Reed    sk_sp<SkImage> img0 = render(blob0.get());
4607e49d534d71d3e7b053fe6f23dfe018ddbceb45bMike Reed    sk_sp<SkImage> img1 = render(blob1.get());
4617e49d534d71d3e7b053fe6f23dfe018ddbceb45bMike Reed    if (img0 && img1) {
4624bcef3c40ad8d3a16bbca4ab74fa15256fb4b125Mike Reed        REPORTER_ASSERT(reporter, sk_tool_utils::equal_pixels(img0.get(), img1.get()));
463b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed    }
464b99beddc7a0f6003d6dd88119e7f2734fc508322Mike Reed}
465