Flutter Engine
The Flutter Engine
Typedefs | Functions
GrTextBlobTest.cpp File Reference
#include "include/core/SkAlphaType.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkColorType.h"
#include "include/core/SkFont.h"
#include "include/core/SkFontStyle.h"
#include "include/core/SkFontTypes.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSurface.h"
#include "include/core/SkSurfaceProps.h"
#include "include/core/SkTextBlob.h"
#include "include/core/SkTypeface.h"
#include "include/core/SkTypes.h"
#include "include/gpu/GpuTypes.h"
#include "include/gpu/GrDirectContext.h"
#include "include/gpu/ganesh/SkSurfaceGanesh.h"
#include "src/core/SkDevice.h"
#include "src/core/SkScalerContext.h"
#include "src/text/GlyphRun.h"
#include "src/text/gpu/SDFTControl.h"
#include "src/text/gpu/SubRunAllocator.h"
#include "src/text/gpu/TextBlob.h"
#include "tests/CtsEnforcement.h"
#include "tests/Test.h"
#include "tools/ToolUtils.h"
#include "tools/fonts/FontToolUtils.h"
#include <cmath>
#include <cstddef>
#include <cstdint>
#include <limits>
#include <memory>
#include <tuple>
#include <utility>

Go to the source code of this file.

Typedefs

using BagOfBytes = sktext::gpu::BagOfBytes
 
using SubRunAllocator = sktext::gpu::SubRunAllocator
 
using TextBlob = sktext::gpu::TextBlob
 

Functions

SkBitmap rasterize_blob (SkTextBlob *blob, const SkPaint &paint, GrRecordingContext *rContext, const SkMatrix &matrix)
 
bool check_for_black (const SkBitmap &bm)
 
 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS (GrTextBlobScaleAnimation, reporter, ctxInfo, CtsEnforcement::kApiLevel_T)
 
 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS (GrTextBlobMoveAround, reporter, ctxInfo, CtsEnforcement::kApiLevel_T)
 
 DEF_TEST (BagOfBytesBasic, r)
 
 DEF_TEST (SubRunAllocator, r)
 
 DEF_TEST (KeyEqualityOnPerspective, r)
 

Typedef Documentation

◆ BagOfBytes

Definition at line 52 of file GrTextBlobTest.cpp.

◆ SubRunAllocator

Definition at line 53 of file GrTextBlobTest.cpp.

◆ TextBlob

Definition at line 354 of file GrTextBlobTest.cpp.

Function Documentation

◆ check_for_black()

bool check_for_black ( const SkBitmap bm)

Definition at line 72 of file GrTextBlobTest.cpp.

72 {
73 for (int y = 0; y < bm.height(); y++) {
74 for (int x = 0; x < bm.width(); x++) {
75 if (bm.getColor(x, y) == SK_ColorBLACK) {
76 return true;
77 }
78 }
79 }
80 return false;
81}
constexpr SkColor SK_ColorBLACK
Definition: SkColor.h:103
SkColor getColor(int x, int y) const
Definition: SkBitmap.h:874
int width() const
Definition: SkBitmap.h:149
int height() const
Definition: SkBitmap.h:158
double y
double x

◆ DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS() [1/2]

DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS ( GrTextBlobMoveAround  ,
reporter  ,
ctxInfo  ,
CtsEnforcement::kApiLevel_T   
)

Definition at line 114 of file GrTextBlobTest.cpp.

117 {
119 SkFont font{tf};
120 font.setHinting(SkFontHinting::kNormal);
121 font.setSize(12);
123 font.setSubpixel(true);
124
125 auto makeBlob = [&](SkPoint delta) {
127 const auto& runBuffer = builder.allocRunPos(font, 30, nullptr);
128
129 for (int i = 0; i < 30; i++) {
130 runBuffer.glyphs[i] = static_cast<SkGlyphID>(i);
131 runBuffer.points()[i] = SkPoint::Make(SkIntToScalar(i*10) + delta.x(), 50 + delta.y());
132 }
133 return builder.make();
134 };
135
136 auto dContext = ctxInfo.directContext();
137 auto rasterizeBlob = [&](SkTextBlob* blob, SkPoint origin, const SkMatrix& matrix) {
139 const SkImageInfo info =
140 SkImageInfo::Make(350, 80, kN32_SkColorType, kPremul_SkAlphaType);
142 auto canvas = surface->getCanvas();
143 canvas->drawColor(SK_ColorWHITE);
144 canvas->concat(matrix);
145 canvas->drawTextBlob(blob, 10 + origin.x(), 40 + origin.y(), paint);
147 bitmap.allocN32Pixels(350, 80);
148 surface->readPixels(bitmap, 0, 0);
149 return bitmap;
150 };
151
152 SkBitmap benchMark;
153 {
154 auto blob = makeBlob({0, 0});
155 benchMark = rasterizeBlob(blob.get(), {0,0}, SkMatrix::I());
156 }
157
158 auto checkBitmap = [&](const SkBitmap& bitmap) {
159 REPORTER_ASSERT(reporter, benchMark.width() == bitmap.width());
160 REPORTER_ASSERT(reporter, benchMark.width() == bitmap.width());
161
162 for (int y = 0; y < benchMark.height(); y++) {
163 for (int x = 0; x < benchMark.width(); x++) {
164 if (benchMark.getColor(x, y) != bitmap.getColor(x, y)) {
165 return false;
166 }
167 }
168 }
169 return true;
170 };
171
172 SkScalar interestingNumbers[] = {-10'000'000, -1'000'000, -1, 0, +1, +1'000'000, +10'000'000};
173 for (auto originX : interestingNumbers) {
174 for (auto originY : interestingNumbers) {
175 for (auto translateX : interestingNumbers) {
176 for (auto translateY : interestingNumbers) {
177 // Make sure everything adds to zero.
178 SkScalar deltaPosX = -(originX + translateX);
179 SkScalar deltaPosY = -(originY + translateY);
180 auto blob = makeBlob({deltaPosX, deltaPosY});
181 SkMatrix t = SkMatrix::Translate(translateX, translateY);
182 auto bitmap = rasterizeBlob(blob.get(), {originX, originY}, t);
183 REPORTER_ASSERT(reporter, checkBitmap(bitmap));
184 }
185 }
186 }
187 }
188}
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
reporter
Definition: FontMgrTest.cpp:39
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
Definition: SkAlphaType.h:29
constexpr SkColor SK_ColorWHITE
Definition: SkColor.h:122
@ kNormal
glyph outlines modified to improve constrast
#define SkIntToScalar(x)
Definition: SkScalar.h:57
uint16_t SkGlyphID
Definition: SkTypes.h:179
#define REPORTER_ASSERT(r, cond,...)
Definition: Test.h:286
Definition: SkFont.h:35
@ kAntiAlias
may have transparent pixels on glyph edges
static SkMatrix Translate(SkScalar dx, SkScalar dy)
Definition: SkMatrix.h:91
static const SkMatrix & I()
Definition: SkMatrix.cpp:1544
const Paint & paint
Definition: color_source.cc:38
VkSurfaceKHR surface
Definition: main.cc:49
float SkScalar
Definition: extension.cpp:12
unsigned useCenter Optional< SkMatrix > matrix
Definition: SkRecords.h:258
SK_API sk_sp< SkSurface > RenderTarget(GrRecordingContext *context, skgpu::Budgeted budgeted, const SkImageInfo &imageInfo, int sampleCount, GrSurfaceOrigin surfaceOrigin, const SkSurfaceProps *surfaceProps, bool shouldCreateWithMips=false, bool isProtected=false)
sk_sp< SkTypeface > CreatePortableTypeface(const char *name, SkFontStyle style)
Definition: bitmap.py:1
font
Font Metadata and Metrics.
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
static constexpr SkPoint Make(float x, float y)
Definition: SkPoint_impl.h:173

◆ DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS() [2/2]

DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS ( GrTextBlobScaleAnimation  ,
reporter  ,
ctxInfo  ,
CtsEnforcement::kApiLevel_T   
)

Definition at line 83 of file GrTextBlobTest.cpp.

86 {
88 SkFont font{tf};
89 font.setHinting(SkFontHinting::kNormal);
90 font.setSize(12);
92 font.setSubpixel(true);
93
95 const auto& runBuffer = builder.allocRunPosH(font, 30, 0, nullptr);
96
97 for (int i = 0; i < 30; i++) {
98 runBuffer.glyphs[i] = static_cast<SkGlyphID>(i);
99 runBuffer.pos[i] = SkIntToScalar(i);
100 }
101 auto blob = builder.make();
102
103 auto dContext = ctxInfo.directContext();
104 bool anyBlack = false;
105 for (int n = -13; n < 5; n++) {
106 SkMatrix m = SkMatrix::Scale(std::exp2(n), std::exp2(n));
107 auto bm = rasterize_blob(blob.get(), SkPaint(), dContext, m);
108 anyBlack |= check_for_black(bm);
109 }
110 REPORTER_ASSERT(reporter, anyBlack);
111}
SkBitmap rasterize_blob(SkTextBlob *blob, const SkPaint &paint, GrRecordingContext *rContext, const SkMatrix &matrix)
bool check_for_black(const SkBitmap &bm)
static SkMatrix Scale(SkScalar sx, SkScalar sy)
Definition: SkMatrix.h:75

◆ DEF_TEST() [1/3]

DEF_TEST ( BagOfBytesBasic  ,
 
)

Definition at line 190 of file GrTextBlobTest.cpp.

190 {
191 const int k4K = 1 << 12;
192 {
193 // GrBagOfBytes::MinimumSizeWithOverhead(-1); // This should fail
196 std::numeric_limits<int>::max() - k4K - 1, 16);
197 // GrBagOfBytes::MinimumSizeWithOverhead(std::numeric_limits<int>::max() - k4K); // Fail
207
214 }
215
216 {
217 BagOfBytes bob;
218 // bob.alignedBytes(0, 1); // This should fail
219 // bob.alignedBytes(1, 0); // This should fail
220 // bob.alignedBytes(1, 3); // This should fail
221
222 struct Big {
223 char stuff[std::numeric_limits<int>::max()];
224 };
225 // bob.alignedBytes(sizeof(Big), 1); // this should fail
226 // bob.allocateBytesFor<Big>(); // this should not compile
227 // The following should run, but should not be regularly tested.
228 // bob.allocateBytesFor<int>((std::numeric_limits<int>::max() - (1<<12)) / sizeof(int) - 1);
229 // The following should fail
230 // bob.allocateBytesFor<int>((std::numeric_limits<int>::max() - (1<<12)) / sizeof(int));
231 bob.alignedBytes(1, 1); // To avoid unused variable problems.
232 }
233
234 // Force multiple block allocation
235 {
236 BagOfBytes bob;
237 const int k64K = 1 << 16;
238 // By default allocation block sizes start at 1K and go up with fib. This should allocate
239 // 10 individual blocks.
240 for (int i = 0; i < 10; i++) {
241 bob.alignedBytes(k64K, 1);
242 }
243 }
244}
static constexpr int MinimumSizeWithOverhead(int requestedSize, int assumedAlignment, int blockSize, int maxAlignment)
void * alignedBytes(int unsafeSize, int unsafeAlignment)
static constexpr int PlatformMinimumSizeWithOverhead(int requestedSize, int assumedAlignment)
static float max(float r, float g, float b)
Definition: hsl.cpp:49

◆ DEF_TEST() [2/3]

DEF_TEST ( KeyEqualityOnPerspective  ,
 
)

Definition at line 356 of file GrTextBlobTest.cpp.

356 {
359 auto runBuffer = builder.allocRun(font, 1, 0.0f, 0.0f);
360 runBuffer.glyphs[0] = 3;
361 auto blob = builder.make();
362 sktext::GlyphRunBuilder grBuilder;
363 auto glyphRunList = grBuilder.blobToGlyphRunList(*blob, {100, 100});
365
366 // Build the strike device.
367 SkSurfaceProps props;
368#if !defined(SK_DISABLE_SDF_TEXT)
369 sktext::gpu::SDFTControl control(false, false, false, 1, 100);
370#else
371 sktext::gpu::SDFTControl control{};
372#endif
373 SkStrikeDeviceInfo strikeDevice{props, SkScalerContextFlags::kBoostContrast, &control};
374 SkMatrix matrix1;
375 matrix1.setAll(1, 0, 0, 0, 1, 0, 1, 1, 1);
376 SkMatrix matrix2;
377 matrix2.setAll(1, 0, 0, 0, 1, 0, 2, 2, 1);
378 auto key1 = std::get<1>(
379 TextBlob::Key::Make(glyphRunList, paint, matrix1, strikeDevice));
380 auto key2 = std::get<1>(
381 TextBlob::Key::Make(glyphRunList, paint, matrix1, strikeDevice));
382 auto key3 = std::get<1>(
383 TextBlob::Key::Make(glyphRunList, paint, matrix2, strikeDevice));
384 REPORTER_ASSERT(r, key1 == key2);
385 REPORTER_ASSERT(r, key1 == key3);
386}
SkMatrix & setAll(SkScalar scaleX, SkScalar skewX, SkScalar transX, SkScalar skewY, SkScalar scaleY, SkScalar transY, SkScalar persp0, SkScalar persp1, SkScalar persp2)
Definition: SkMatrix.h:562
const GlyphRunList & blobToGlyphRunList(const SkTextBlob &blob, SkPoint origin)
Definition: GlyphRun.cpp:233
sk_sp< SkTypeface > DefaultTypeface()
const myers::Point & get< 1 >(const myers::Segment &s)
Definition: Myers.h:81
static std::tuple< bool, Key > Make(const GlyphRunList &glyphRunList, const SkPaint &paint, const SkMatrix &drawMatrix, const SkStrikeDeviceInfo &strikeDevice)
Definition: TextBlob.cpp:84

◆ DEF_TEST() [3/3]

DEF_TEST ( SubRunAllocator  ,
 
)

Definition at line 246 of file GrTextBlobTest.cpp.

246 {
247 static int created = 0;
248 static int destroyed = 0;
249 struct Foo {
250 Foo() : fI{-2}, fX{-3} { created++; }
251 Foo(int i, float x) : fI{i}, fX{x} { created++; }
252 ~Foo() { destroyed++; }
253 int fI;
254 float fX;
255 };
256
257 struct alignas(8) OddAlignment {
258 char buf[10];
259 };
260
261 auto exercise = [&](SubRunAllocator* alloc) {
262 created = 0;
263 destroyed = 0;
264 {
265 int* p = alloc->makePOD<int>(3);
266 REPORTER_ASSERT(r, *p == 3);
267 int* q = alloc->makePOD<int>(7);
268 REPORTER_ASSERT(r, *q == 7);
269
270 REPORTER_ASSERT(r, *alloc->makePOD<int>(3) == 3);
271 auto foo = alloc->makeUnique<Foo>(3, 4.0f);
272 REPORTER_ASSERT(r, foo->fI == 3);
273 REPORTER_ASSERT(r, foo->fX == 4.0f);
274 REPORTER_ASSERT(r, created == 1);
275 REPORTER_ASSERT(r, destroyed == 0);
276
277 alloc->makePODArray<int>(10);
278
279 auto fooArray = alloc->makeUniqueArray<Foo>(10);
280 REPORTER_ASSERT(r, fooArray[3].fI == -2);
281 REPORTER_ASSERT(r, fooArray[4].fX == -3.0f);
282 REPORTER_ASSERT(r, created == 11);
283 REPORTER_ASSERT(r, destroyed == 0);
284 alloc->makePOD<OddAlignment>();
285 }
286
287 REPORTER_ASSERT(r, created == 11);
288 REPORTER_ASSERT(r, destroyed == 11);
289 };
290
291 // Exercise default arena
292 {
293 SubRunAllocator arena{0};
294 exercise(&arena);
295 }
296
297 // Exercise on stack arena
298 {
300 exercise(&arena);
301 }
302
303 // Exercise arena with a heap allocated starting block
304 {
305 std::unique_ptr<char[]> block{new char[1024]};
306 SubRunAllocator arena{block.get(), 1024, 0};
307 exercise(&arena);
308 }
309
310 // Exercise the singly-link list of unique_ptrs use case
311 {
312 created = 0;
313 destroyed = 0;
314 SubRunAllocator arena;
315
316 struct Node {
317 Node(std::unique_ptr<Node, SubRunAllocator::Destroyer> next)
318 : fNext{std::move(next)} { created++; }
319 ~Node() { destroyed++; }
320 std::unique_ptr<Node, SubRunAllocator::Destroyer> fNext;
321 };
322
323 std::unique_ptr<Node, SubRunAllocator::Destroyer> current = nullptr;
324 for (int i = 0; i < 128; i++) {
325 current = arena.makeUnique<Node>(std::move(current));
326 }
327 REPORTER_ASSERT(r, created == 128);
328 REPORTER_ASSERT(r, destroyed == 0);
329 }
330 REPORTER_ASSERT(r, created == 128);
331 REPORTER_ASSERT(r, destroyed == 128);
332
333 // Exercise the array ctor w/ a mapping function
334 {
335 struct I {
336 I(int v) : i{v} {}
337 ~I() {}
338 int i;
339 };
341 auto a = arena.makeUniqueArray<I>(8, [](size_t i) { return i; });
342 for (size_t i = 0; i < 8; i++) {
343 REPORTER_ASSERT(r, a[i].i == (int)i);
344 }
345 }
346
347 {
348 SubRunAllocator arena(4096);
349 void* ptr = arena.alignedBytes(4081, 8);
350 REPORTER_ASSERT(r, ((intptr_t)ptr & 7) == 0);
351 }
352}
Instance * fNext
static float next(float f)
std::unique_ptr< T[], ArrayDestroyer > makeUniqueArray(int n)
std::unique_ptr< T, Destroyer > makeUnique(Args &&... args)
void * alignedBytes(int size, int alignment)
struct MyStruct a[10]
Definition: dart.idl:29
#define I
Definition: ref_ptr.h:256
Definition: SkMD5.cpp:134

◆ rasterize_blob()

SkBitmap rasterize_blob ( SkTextBlob blob,
const SkPaint paint,
GrRecordingContext rContext,
const SkMatrix matrix 
)

Definition at line 55 of file GrTextBlobTest.cpp.

58 {
59 const SkImageInfo info =
60 SkImageInfo::Make(500, 500, kN32_SkColorType, kPremul_SkAlphaType);
62 auto canvas = surface->getCanvas();
63 canvas->drawColor(SK_ColorWHITE);
64 canvas->concat(matrix);
65 canvas->drawTextBlob(blob, 10, 250, paint);
67 bitmap.allocN32Pixels(500, 500);
68 surface->readPixels(bitmap, 0, 0);
69 return bitmap;
70}