skia2/tests/SkShaperJSONWriterTest.cpp
Herb Derby 09db9d2175 Reland "SkShaper JSON output with cluster visualization"
This is a reland of 53610832a0

Fixes conversion of size_t to int.

Original change's description:
> SkShaper JSON output with cluster visualization
>
> A simple JSON output for diagnostic purposes.
> If the run is not 1:1 code points to glyphs, then
> break the run into clusters.
>
> Change-Id: I06980e0bac2cdca8a69b5b5ba0759a021fd4eb3b
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/209740
> Commit-Queue: Herb Derby <herb@google.com>
> Reviewed-by: Julia Lavrova <jlavrova@google.com>

Change-Id: I712293c4820eb23234d64fa019d28bac8b105637
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/211986
Reviewed-by: Herb Derby <herb@google.com>
Commit-Queue: Herb Derby <herb@google.com>
2019-05-03 15:48:46 +00:00

147 lines
5.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright 2019 The Android Open Source Project
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/utils/SkShaperJSONWriter.h"
#include "Test.h"
#include "src/core/SkSpan.h"
#include "src/utils/SkJSONWriter.h"
#include "src/utils/SkUTF.h"
DEF_TEST(SkShaperTest_cluster, reporter) {
struct Answer {
size_t glyphStartIndex, glyphEndIndex;
uint32_t utf8StartIndex, utf8EndIndex;
};
struct TestCase {
size_t utf8Len;
std::vector<uint32_t> clusters;
std::vector<Answer> answers;
};
std::vector<TestCase> cases = {
/*1:1*/ { 1, {0}, {{0, 1, 0, 1}} },
/*1:2*/ { 1, {0, 0}, {{0, 2, 0, 1}} },
/*2:1*/ { 2, {0}, {{0, 1, 0, 2}} },
/*2:3*/ { 2, {0, 0, 0}, {{0, 3, 0, 2}} },
/*3:2*/ { 3, {0, 0}, {{0, 2, 0, 3}} },
// cluster runs
{ 2, {0, 1}, {{0, 1, 0, 1}, {1, 2, 1, 2}} },
{ 2, {1, 0}, {{0, 1, 1, 2}, {1, 2, 0, 1}} },
{ 2, {0, 0, 1}, {{0, 2, 0, 1}, {2, 3, 1, 2}} },
{ 2, {1, 0, 0}, {{0, 1, 1, 2}, {1, 3, 0, 1}} },
{ 2, {0, 1, 1}, {{0, 1, 0, 1}, {1, 3, 1, 2}} },
{ 2, {1, 1, 0}, {{0, 2, 1, 2}, {2, 3, 0, 1}} },
{ 3, {0, 0, 1}, {{0, 2, 0, 1}, {2, 3, 1, 3}} },
{ 3, {1, 0, 0}, {{0, 1, 1, 3}, {1, 3, 0, 1}} },
{ 3, {0, 1, 1}, {{0, 1, 0, 1}, {1, 3, 1, 3}} },
{ 3, {1, 1, 0}, {{0, 2, 1, 3}, {2, 3, 0, 1}} },
{ 4, {3, 2, 1, 0}, {{0, 1, 3, 4}, {1, 2, 2, 3}, {2, 3, 1, 2}, {3, 4, 0, 1}} },
};
for (auto& oneCase : cases) {
size_t answerCount = 0;
auto checker = [&](size_t glyphStartIndex, size_t glyphEndIndex,
uint32_t utf8StartIndex, uint32_t utf8EndIndex) {
if (answerCount < oneCase.answers.size()) {
Answer a = oneCase.answers[answerCount];
REPORTER_ASSERT(reporter, a.glyphStartIndex == glyphStartIndex);
REPORTER_ASSERT(reporter, a.glyphEndIndex == glyphEndIndex );
REPORTER_ASSERT(reporter, a.utf8StartIndex == utf8StartIndex );
REPORTER_ASSERT(reporter, a.utf8EndIndex == utf8EndIndex );
} else {
REPORTER_ASSERT(reporter, false, "Too many clusters");
}
answerCount++;
};
SkShaperJSONWriter::BreakupClusters(
0, oneCase.utf8Len, SkSpan<const uint32_t>{oneCase.clusters}, checker);
REPORTER_ASSERT(reporter, answerCount == oneCase.answers.size());
}
}
DEF_TEST(SkShaperTest_VisualizeCluster, reporter) {
struct Answer {
std::string utf8;
std::vector<SkGlyphID> glyphIDs;
};
struct TestCase {
std::string utf8;
std::vector<SkGlyphID> glyphIDs;
std::vector<uint32_t> clusters;
std::vector<Answer> answers;
};
std::vector<TestCase> cases = {
{ "A", {7}, {0}, {{"A", {7}}} },
{ "ABCD", {7, 8, 9, 10}, {0, 1, 2, 3}, {{"ABCD", {7, 8, 9, 10}}} },
{ "A", {7, 8}, {0, 0}, {{"A", {7, 8}}} },
{ "AB", {7}, {0}, {{"AB", {7}}} },
{ "AB", {7, 8, 9}, {0, 0, 0}, {{"AB", {7, 8, 9}}} },
{ "ABC", {7, 8}, {0, 0}, {{"ABC", {7, 8}}} },
{ "ABCD", {7, 8, 9, 10}, {3, 2, 1, 0}, {{"ABCD", {7, 8, 9, 10}}} },
{ "المادة", {246, 268, 241, 205, 240}, {10, 8, 6, 2, 0},
{{"ادة", {246, 268, 241}}, {"لم", {205}}, {"ا", {240}}} },
};
for (auto& oneCase : cases) {
size_t answerCount = 0;
auto checker = [&](
int codePointCount, SkSpan<const char> utf1to1, SkSpan<const SkGlyphID> glyph1to1) {
if (answerCount < oneCase.answers.size()) {
Answer a = oneCase.answers[answerCount];
std::string toCheckUtf8{utf1to1.data(), utf1to1.size()};
REPORTER_ASSERT(reporter, a.utf8 == toCheckUtf8);
std::vector<SkGlyphID> toCheckGlyphIDs{glyph1to1.begin(), glyph1to1.end()};
REPORTER_ASSERT(reporter, a.glyphIDs == toCheckGlyphIDs);
} else {
REPORTER_ASSERT(reporter, false, "Too many clusters");
}
answerCount++;
};
SkShaperJSONWriter::VisualizeClusters(oneCase.utf8.c_str(),
0, oneCase.utf8.size(),
SkSpan<const SkGlyphID>{oneCase.glyphIDs},
SkSpan<const uint32_t>{oneCase.clusters},
checker);
}
}
// Example use of the SkShaperJSONWriter.
// Set to 1 to see use.
#if 0
DEF_TEST(SkShaperTest_basic, reporter) {
std::unique_ptr<SkShaper> shaper = SkShaper::Make();
SkFont font(nullptr, 14);
SkDynamicMemoryWStream out;
SkJSONWriter jsonWriter{&out, SkJSONWriter::Mode::kPretty};
std::string s = "المادة 1 يولد جميع الناس أحرارًا متساوين في الكرامة والحقوق. وقد وهبوا "
"عقلاً وضميرًا وعليهم أن يعامل بعضهم بعضًا بروح الإخاء.";
SkShaperJSONWriter shaperJSON{&jsonWriter, s.c_str(), s.size()};
jsonWriter.beginObject();
shaper->shape(s.c_str(), s.size(), font, true /* right to left */, 256, &shaperJSON);
jsonWriter.endObject();
jsonWriter.flush();
std::string sout(out.bytesWritten(), 0);
out.copyTo(&sout[0]);
// Uncomment below to show the JSON.
SkDebugf("%s", sout.c_str());
}
#endif