Update rive-cpp to 2.0 version
[platform/core/uifw/rive-tizen.git] / submodule / skia / tests / SkGlyphBufferTest.cpp
1 /*
2  * Copyright 2019 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7
8 #include "src/core/SkEnumerate.h"
9 #include "src/core/SkGlyphBuffer.h"
10 #include "src/core/SkGlyphRunPainter.h"
11 #include "src/core/SkScalerContext.h"
12 #include "tests/Test.h"
13
14 DEF_TEST(SkPackedGlyphIDCtor, reporter) {
15     using PG = SkPackedGlyphID;
16     // x and y are in one quarter the sub-pixel sampling frequency.
17     // Number of steps on the interval [0, 1)
18     const int perUnit = 1u << (PG::kSubPixelPosLen + 2);
19     const float step = 1.f / perUnit;
20     const int testLimit = 2 * perUnit;
21     auto freqRound = [](uint32_t x) -> uint32_t {
22         return ((x + 2) >> 2) & PG::kSubPixelPosMask;
23     };
24
25     {
26         // Normal sub-pixel with y-axis snapping.
27         auto roundingSpec = SkGlyphPositionRoundingSpec(true, SkAxisAlignment::kX);
28         SkIPoint mask = roundingSpec.ignorePositionFieldMask;
29         for (int x = -testLimit; x < testLimit; x++) {
30             float fx = x * step;
31             SkPoint roundedPos = SkPoint{fx, 0} + roundingSpec.halfAxisSampleFreq;
32             SkPackedGlyphID packedID{3, roundedPos, mask};
33             uint32_t subX = freqRound(x);
34             uint32_t subY = 0;
35             SkPackedGlyphID correctID(3, subX, subY);
36             SkASSERT(packedID == correctID);
37             REPORTER_ASSERT(reporter, packedID == correctID);
38         }
39     }
40
41     {
42         // No subpixel positioning.
43         auto roundingSpec = SkGlyphPositionRoundingSpec(false, SkAxisAlignment::kNone);
44         SkIPoint mask = roundingSpec.ignorePositionFieldMask;
45         for (int y = -testLimit; y < testLimit; y++) {
46             for (int x = -testLimit; x < testLimit; x++) {
47                 float fx = x * step, fy = y * step;
48                 SkPoint roundedPos = SkPoint{fx, fy} + roundingSpec.halfAxisSampleFreq;
49                 SkPackedGlyphID packedID{3, roundedPos, mask};
50                 uint32_t subX = 0;
51                 uint32_t subY = 0;
52                 SkPackedGlyphID correctID(3, subX, subY);
53                 REPORTER_ASSERT(reporter, packedID == correctID);
54             }
55         }
56     }
57
58     {
59         // Subpixel with no axis snapping.
60         auto roundingSpec = SkGlyphPositionRoundingSpec(true, SkAxisAlignment::kNone);
61         SkIPoint mask = roundingSpec.ignorePositionFieldMask;
62         for (int y = -testLimit; y < testLimit; y++) {
63             for (int x = -testLimit; x < testLimit; x++) {
64                 float fx = x * step, fy = y * step;
65                 SkPoint roundedPos = SkPoint{fx, fy} + roundingSpec.halfAxisSampleFreq;
66                 SkPackedGlyphID packedID{3, roundedPos, mask};
67                 uint32_t subX = freqRound(x);
68                 uint32_t subY = freqRound(y);
69                 SkPackedGlyphID correctID(3, subX, subY);
70                 REPORTER_ASSERT(reporter, packedID == correctID);
71             }
72         }
73     }
74
75     {
76         // Test dynamic range by transposing a large distance.
77         // Floating point numbers have 24 bits of precision. The largest distance is 24 - 2 (for
78         // sub-pixel) - 1 (for truncation to floor trick in the code). This leaves 21 bits. Large
79         // Distance is 2^21 - 2 (because the test is on the interval [-2, 2).
80         const uint32_t kLogLargeDistance = 24 - PG::kSubPixelPosLen - 1;
81         const int64_t kLargeDistance = (1ull << kLogLargeDistance) - 2;
82         auto roundingSpec = SkGlyphPositionRoundingSpec(true, SkAxisAlignment::kNone);
83         SkIPoint mask = roundingSpec.ignorePositionFieldMask;
84         for (int y = -32; y < 33; y++) {
85             for (int x = -32; x < 33; x++) {
86                 float fx = x * step + kLargeDistance, fy = y * step + kLargeDistance;
87                 SkPoint roundedPos = SkPoint{fx, fy} + roundingSpec.halfAxisSampleFreq;
88                 SkPackedGlyphID packedID{3, roundedPos, mask};
89                 uint32_t subX = freqRound(x);
90                 uint32_t subY = freqRound(y);
91                 SkPackedGlyphID correctID(3, subX, subY);
92                 REPORTER_ASSERT(reporter, packedID == correctID);
93             }
94         }
95     }
96 }
97
98 DEF_TEST(SkSourceGlyphBufferBasic, reporter) {
99     SkSourceGlyphBuffer rejects;
100     // Positions are picked to avoid precision problems.
101     const SkPoint positions[] = {{10.25,10.25}, {20.5,10.25}, {30.75,10.25}, {40,10.25}};
102     const SkGlyphID glyphIDs[] = {1, 2, 3, 4};
103     auto source = SkMakeZip(glyphIDs, positions);
104
105     rejects.setSource(source);
106     for (auto [i, glyphID, pos] : SkMakeEnumerate(rejects.source())) {
107         REPORTER_ASSERT(reporter, glyphID == std::get<0>(source[i]));
108         REPORTER_ASSERT(reporter, pos == std::get<1>(source[i]));
109     }
110     // Reject a couple of glyphs.
111     rejects.reject(1);
112     rejects.reject(2, 100);
113     rejects.flipRejectsToSource();
114     REPORTER_ASSERT(reporter, std::get<1>(rejects.maxDimensionHint()) == 100);
115     for (auto [i, glyphID, pos] : SkMakeEnumerate(rejects.source())) {
116         // This will index 1 and 2 from the original source.
117         size_t j = i + 1;
118         REPORTER_ASSERT(reporter, glyphID == std::get<0>(source[j]));
119         REPORTER_ASSERT(reporter, pos == std::get<1>(source[j]));
120     }
121
122     // Reject an additional glyph
123     rejects.reject(0, 10);
124     rejects.flipRejectsToSource();
125     REPORTER_ASSERT(reporter, std::get<1>(rejects.maxDimensionHint()) == 10);
126     for (auto [i, glyphID, pos] : SkMakeEnumerate(rejects.source())) {
127         // This will index 1 from the original source.
128         size_t j = i + 1;
129         REPORTER_ASSERT(reporter, glyphID == std::get<0>(source[j]));
130         REPORTER_ASSERT(reporter, pos == std::get<1>(source[j]));
131     }
132
133     // Start all over
134     rejects.setSource(source);
135     for (auto [i, glyphID, pos] : SkMakeEnumerate(rejects.source())) {
136         REPORTER_ASSERT(reporter, glyphID == std::get<0>(source[i]));
137         REPORTER_ASSERT(reporter, pos == std::get<1>(source[i]));
138     }
139
140     // Check that everything is working after calling setSource.
141     rejects.reject(1);
142     rejects.reject(2, 100);
143     rejects.flipRejectsToSource();
144     REPORTER_ASSERT(reporter, std::get<1>(rejects.maxDimensionHint()) == 100);
145     for (auto [i, glyphID, pos] : SkMakeEnumerate(rejects.source())) {
146         // This will index 1 and 2 from the original source.
147         size_t j = i + 1;
148         REPORTER_ASSERT(reporter, glyphID == std::get<0>(source[j]));
149         REPORTER_ASSERT(reporter, pos == std::get<1>(source[j]));
150     }
151 }
152
153 DEF_TEST(SkDrawableGlyphBufferBasic, reporter) {
154     // Positions are picked to avoid precision problems.
155     const SkPoint positions[] = {{10.25,10.25}, {20.5,10.25}, {30.75,10.25}, {40,10.25}};
156     const SkGlyphID glyphIDs[] = {1, 2, 3, 4};
157     SkGlyph glyphs[100];
158     auto source = SkMakeZip(glyphIDs, positions);
159
160     {
161         SkDrawableGlyphBuffer accepted;
162         accepted.ensureSize(100);
163         accepted.startSource(source);
164         for (auto [i, packedID, pos] : SkMakeEnumerate(accepted.input())) {
165             REPORTER_ASSERT(reporter, packedID.packedID().glyphID() == glyphIDs[i]);
166             REPORTER_ASSERT(reporter, pos == positions[i]);
167         }
168     }
169
170     {
171         SkDrawableGlyphBuffer accepted;
172         accepted.ensureSize(100);
173         SkMatrix matrix = SkMatrix::Scale(0.5, 0.5);
174         SkGlyphPositionRoundingSpec rounding{true, SkAxisAlignment::kX};
175         SkMatrix positionMatrix{matrix};
176         positionMatrix.preTranslate(100, 100);
177         accepted.startDevicePositioning(source, positionMatrix, rounding);
178         for (auto [i, packedID, pos] : SkMakeEnumerate(accepted.input())) {
179             REPORTER_ASSERT(reporter, glyphIDs[i] == packedID.packedID().glyphID());
180             REPORTER_ASSERT(reporter,
181                 pos.x() == SkScalarFloorToInt(positions[i].x() * 0.5 + 50 +
182                                               SkPackedGlyphID::kSubpixelRound));
183             REPORTER_ASSERT(reporter,
184                             pos.y() == SkScalarFloorToInt(positions[i].y() * 0.5 + 50 + 0.5));
185         }
186     }
187
188     {
189         SkDrawableGlyphBuffer accepted;
190         accepted.ensureSize(100);
191         accepted.startSource(source);
192         for (auto [i, packedID, pos] : SkMakeEnumerate(accepted.input())) {
193             accepted.accept(&glyphs[i], i);
194         }
195         for (auto [i, glyph, pos] : SkMakeEnumerate(accepted.accepted())) {
196             REPORTER_ASSERT(reporter, glyph.glyph() == &glyphs[i]);
197         }
198     }
199 }