1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2019 The Android Open Source Project
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "modules/skparagraph/tests/SkShaperJSONWriter.h"
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include "tests/Test.h"
11cb93a386Sopenharmony_ci
12cb93a386Sopenharmony_ci#include "include/core/SkSpan.h"
13cb93a386Sopenharmony_ci#include "src/base/SkUTF.h"
14cb93a386Sopenharmony_ci#include "src/utils/SkJSONWriter.h"
15cb93a386Sopenharmony_ci
16cb93a386Sopenharmony_ciDEF_TEST(SkShaperTest_cluster, reporter) {
17cb93a386Sopenharmony_ci
18cb93a386Sopenharmony_ci    struct Answer {
19cb93a386Sopenharmony_ci        size_t glyphStartIndex, glyphEndIndex;
20cb93a386Sopenharmony_ci        uint32_t utf8StartIndex, utf8EndIndex;
21cb93a386Sopenharmony_ci    };
22cb93a386Sopenharmony_ci
23cb93a386Sopenharmony_ci    struct TestCase {
24cb93a386Sopenharmony_ci        size_t utf8Len;
25cb93a386Sopenharmony_ci        std::vector<uint32_t> clusters;
26cb93a386Sopenharmony_ci        std::vector<Answer> answers;
27cb93a386Sopenharmony_ci    };
28cb93a386Sopenharmony_ci
29cb93a386Sopenharmony_ci    std::vector<TestCase> cases = {
30cb93a386Sopenharmony_ci            /*1:1*/ { 1, {0}, {{0, 1, 0, 1}} },
31cb93a386Sopenharmony_ci            /*1:2*/ { 1, {0, 0}, {{0, 2, 0, 1}} },
32cb93a386Sopenharmony_ci            /*2:1*/ { 2, {0}, {{0, 1, 0, 2}} },
33cb93a386Sopenharmony_ci            /*2:3*/ { 2, {0, 0, 0}, {{0, 3, 0, 2}} },
34cb93a386Sopenharmony_ci            /*3:2*/ { 3, {0, 0}, {{0, 2, 0, 3}} },
35cb93a386Sopenharmony_ci
36cb93a386Sopenharmony_ci            // cluster runs
37cb93a386Sopenharmony_ci            { 2, {0, 1}, {{0, 1, 0, 1}, {1, 2, 1, 2}} },
38cb93a386Sopenharmony_ci            { 2, {1, 0}, {{0, 1, 1, 2}, {1, 2, 0, 1}} },
39cb93a386Sopenharmony_ci            { 2, {0, 0, 1}, {{0, 2, 0, 1}, {2, 3, 1, 2}} },
40cb93a386Sopenharmony_ci            { 2, {1, 0, 0}, {{0, 1, 1, 2}, {1, 3, 0, 1}} },
41cb93a386Sopenharmony_ci            { 2, {0, 1, 1}, {{0, 1, 0, 1}, {1, 3, 1, 2}} },
42cb93a386Sopenharmony_ci            { 2, {1, 1, 0}, {{0, 2, 1, 2}, {2, 3, 0, 1}} },
43cb93a386Sopenharmony_ci            { 3, {0, 0, 1}, {{0, 2, 0, 1}, {2, 3, 1, 3}} },
44cb93a386Sopenharmony_ci            { 3, {1, 0, 0}, {{0, 1, 1, 3}, {1, 3, 0, 1}} },
45cb93a386Sopenharmony_ci            { 3, {0, 1, 1}, {{0, 1, 0, 1}, {1, 3, 1, 3}} },
46cb93a386Sopenharmony_ci            { 3, {1, 1, 0}, {{0, 2, 1, 3}, {2, 3, 0, 1}} },
47cb93a386Sopenharmony_ci            { 4, {3, 2, 1, 0}, {{0, 1, 3, 4}, {1, 2, 2, 3}, {2, 3, 1, 2}, {3, 4, 0, 1}} },
48cb93a386Sopenharmony_ci    };
49cb93a386Sopenharmony_ci
50cb93a386Sopenharmony_ci    for (auto& oneCase : cases) {
51cb93a386Sopenharmony_ci        size_t answerCount = 0;
52cb93a386Sopenharmony_ci        auto checker = [&](size_t glyphStartIndex, size_t glyphEndIndex,
53cb93a386Sopenharmony_ci                           uint32_t utf8StartIndex, uint32_t utf8EndIndex) {
54cb93a386Sopenharmony_ci            if (answerCount < oneCase.answers.size()) {
55cb93a386Sopenharmony_ci                Answer a = oneCase.answers[answerCount];
56cb93a386Sopenharmony_ci                REPORTER_ASSERT(reporter, a.glyphStartIndex == glyphStartIndex);
57cb93a386Sopenharmony_ci                REPORTER_ASSERT(reporter,   a.glyphEndIndex == glyphEndIndex  );
58cb93a386Sopenharmony_ci                REPORTER_ASSERT(reporter,  a.utf8StartIndex == utf8StartIndex );
59cb93a386Sopenharmony_ci                REPORTER_ASSERT(reporter,    a.utf8EndIndex == utf8EndIndex   );
60cb93a386Sopenharmony_ci
61cb93a386Sopenharmony_ci            } else {
62cb93a386Sopenharmony_ci                REPORTER_ASSERT(reporter, false, "Too many clusters");
63cb93a386Sopenharmony_ci            }
64cb93a386Sopenharmony_ci            answerCount++;
65cb93a386Sopenharmony_ci        };
66cb93a386Sopenharmony_ci
67cb93a386Sopenharmony_ci        SkShaperJSONWriter::BreakupClusters(
68cb93a386Sopenharmony_ci                0, oneCase.utf8Len, SkSpan(oneCase.clusters), checker);
69cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, answerCount == oneCase.answers.size());
70cb93a386Sopenharmony_ci    }
71cb93a386Sopenharmony_ci}
72cb93a386Sopenharmony_ci
73cb93a386Sopenharmony_ciDEF_TEST(SkShaperTest_VisualizeCluster, reporter) {
74cb93a386Sopenharmony_ci
75cb93a386Sopenharmony_ci    struct Answer {
76cb93a386Sopenharmony_ci        std::string utf8;
77cb93a386Sopenharmony_ci        std::vector<SkGlyphID> glyphIDs;
78cb93a386Sopenharmony_ci    };
79cb93a386Sopenharmony_ci    struct TestCase {
80cb93a386Sopenharmony_ci        std::string utf8;
81cb93a386Sopenharmony_ci        std::vector<SkGlyphID> glyphIDs;
82cb93a386Sopenharmony_ci        std::vector<uint32_t> clusters;
83cb93a386Sopenharmony_ci        std::vector<Answer> answers;
84cb93a386Sopenharmony_ci    };
85cb93a386Sopenharmony_ci
86cb93a386Sopenharmony_ci    std::vector<TestCase> cases = {
87cb93a386Sopenharmony_ci            { "A", {7}, {0}, {{"A", {7}}} },
88cb93a386Sopenharmony_ci            { "ABCD", {7, 8, 9, 10}, {0, 1, 2, 3}, {{"ABCD", {7, 8, 9, 10}}} },
89cb93a386Sopenharmony_ci            { "A", {7, 8}, {0, 0}, {{"A", {7, 8}}} },
90cb93a386Sopenharmony_ci            { "AB", {7}, {0}, {{"AB", {7}}} },
91cb93a386Sopenharmony_ci            { "AB", {7, 8, 9}, {0, 0, 0}, {{"AB", {7, 8, 9}}} },
92cb93a386Sopenharmony_ci            { "ABC", {7, 8}, {0, 0}, {{"ABC", {7, 8}}} },
93cb93a386Sopenharmony_ci            { "ABCD", {7, 8, 9, 10}, {3, 2, 1, 0}, {{"ABCD", {7, 8, 9, 10}}} },
94cb93a386Sopenharmony_ci            { "المادة", {246, 268, 241, 205, 240}, {10, 8, 6, 2, 0},
95cb93a386Sopenharmony_ci                        {{"ادة",  {246, 268, 241}}, {"لم", {205}}, {"ا", {240}}} },
96cb93a386Sopenharmony_ci    };
97cb93a386Sopenharmony_ci
98cb93a386Sopenharmony_ci    for (auto& oneCase : cases) {
99cb93a386Sopenharmony_ci        size_t answerCount = 0;
100cb93a386Sopenharmony_ci        auto checker = [&](
101cb93a386Sopenharmony_ci                int codePointCount, SkSpan<const char> utf1to1, SkSpan<const SkGlyphID> glyph1to1) {
102cb93a386Sopenharmony_ci            if (answerCount < oneCase.answers.size()) {
103cb93a386Sopenharmony_ci                Answer a = oneCase.answers[answerCount];
104cb93a386Sopenharmony_ci                std::string toCheckUtf8{utf1to1.data(), utf1to1.size()};
105cb93a386Sopenharmony_ci                REPORTER_ASSERT(reporter, a.utf8 == toCheckUtf8);
106cb93a386Sopenharmony_ci                std::vector<SkGlyphID> toCheckGlyphIDs{glyph1to1.begin(), glyph1to1.end()};
107cb93a386Sopenharmony_ci                REPORTER_ASSERT(reporter, a.glyphIDs == toCheckGlyphIDs);
108cb93a386Sopenharmony_ci
109cb93a386Sopenharmony_ci            } else {
110cb93a386Sopenharmony_ci                REPORTER_ASSERT(reporter, false, "Too many clusters");
111cb93a386Sopenharmony_ci            }
112cb93a386Sopenharmony_ci            answerCount++;
113cb93a386Sopenharmony_ci        };
114cb93a386Sopenharmony_ci
115cb93a386Sopenharmony_ci        SkShaperJSONWriter::VisualizeClusters(oneCase.utf8.c_str(),
116cb93a386Sopenharmony_ci                                              0, oneCase.utf8.size(),
117cb93a386Sopenharmony_ci                                              SkSpan(oneCase.glyphIDs),
118cb93a386Sopenharmony_ci                                              SkSpan(oneCase.clusters),
119cb93a386Sopenharmony_ci                                              checker);
120cb93a386Sopenharmony_ci    }
121cb93a386Sopenharmony_ci}
122cb93a386Sopenharmony_ci
123cb93a386Sopenharmony_ci// Example use of the SkShaperJSONWriter.
124cb93a386Sopenharmony_ci// Set to 1 to see use.
125cb93a386Sopenharmony_ci#if 0
126cb93a386Sopenharmony_ciDEF_TEST(SkShaperTest_basic, reporter) {
127cb93a386Sopenharmony_ci    std::unique_ptr<SkShaper> shaper = SkShaper::Make();
128cb93a386Sopenharmony_ci    SkFont font(nullptr, 14);
129cb93a386Sopenharmony_ci
130cb93a386Sopenharmony_ci    SkDynamicMemoryWStream out;
131cb93a386Sopenharmony_ci    SkJSONWriter jsonWriter{&out, SkJSONWriter::Mode::kPretty};
132cb93a386Sopenharmony_ci    std::string s = "المادة 1 يولد جميع الناس أحرارًا متساوين في الكرامة والحقوق. وقد وهبوا "
133cb93a386Sopenharmony_ci                    "عقلاً وضميرًا وعليهم أن يعامل بعضهم بعضًا بروح الإخاء.";
134cb93a386Sopenharmony_ci
135cb93a386Sopenharmony_ci    SkShaperJSONWriter shaperJSON{&jsonWriter, s.c_str(), s.size()};
136cb93a386Sopenharmony_ci
137cb93a386Sopenharmony_ci    jsonWriter.beginObject();
138cb93a386Sopenharmony_ci    shaper->shape(s.c_str(), s.size(), font, true /* right to left */,  256, &shaperJSON);
139cb93a386Sopenharmony_ci    jsonWriter.endObject();
140cb93a386Sopenharmony_ci    jsonWriter.flush();
141cb93a386Sopenharmony_ci
142cb93a386Sopenharmony_ci    std::string sout(out.bytesWritten(), 0);
143cb93a386Sopenharmony_ci    out.copyTo(&sout[0]);
144cb93a386Sopenharmony_ci    // Uncomment below to show the JSON.
145cb93a386Sopenharmony_ci    SkDebugf("%s", sout.c_str());
146cb93a386Sopenharmony_ci}
147cb93a386Sopenharmony_ci#endif
148