| Flutter Impeller |

impeller_unittests.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "flutter/fml/native_library.h"
6 #include "flutter/fml/string_conversion.h"
7 #include "flutter/testing/testing.h"
8 #include "impeller/base/allocation.h"
9 #include "impeller/renderer/backend/gles/context_gles.h"
10 #include "impeller/toolkit/interop/context.h"
11 #include "impeller/toolkit/interop/dl.h"
12 #include "impeller/toolkit/interop/dl_builder.h"
13 #include "impeller/toolkit/interop/formats.h"
14 #include "impeller/toolkit/interop/impeller.h"
15 #include "impeller/toolkit/interop/impeller.hpp"
16 #include "impeller/toolkit/interop/paint.h"
17 #include "impeller/toolkit/interop/paragraph.h"
18 #include "impeller/toolkit/interop/paragraph_builder.h"
19 #include "impeller/toolkit/interop/paragraph_style.h"
20 #include "impeller/toolkit/interop/playground_test.h"
21 #include "impeller/toolkit/interop/surface.h"
22 #include "impeller/toolkit/interop/texture.h"
23 #include "impeller/toolkit/interop/typography_context.h"
24
25 namespace impeller::interop::testing {
26
27 using InteropPlaygroundTest = PlaygroundTest;
28 INSTANTIATE_PLAYGROUND_SUITE(InteropPlaygroundTest);
29
30 TEST_P(InteropPlaygroundTest, CanCreateContext) {
31 auto context = CreateContext();
32 ASSERT_TRUE(context);
33 }
34
35 TEST_P(InteropPlaygroundTest, CanCreateDisplayListBuilder) {
36 hpp::DisplayListBuilder builder;
37 ASSERT_TRUE(builder);
38 ASSERT_TRUE(ToImpellerType(builder.GetTransform()).IsIdentity());
39 ASSERT_EQ(builder.GetSaveCount(), 1u);
40 builder.Save();
41 ASSERT_EQ(builder.GetSaveCount(), 2u);
42 builder.Restore();
43 ASSERT_EQ(builder.GetSaveCount(), 1u);
44 }
45
46 TEST_P(InteropPlaygroundTest, CanCreateSurface) {
47 if (GetBackend() != PlaygroundBackend::kOpenGLES) {
48 GTEST_SKIP()
49 << "This test checks wrapping FBOs which is an OpenGL ES only call.";
50 return;
51 }
52 auto context = CreateContext();
53 ASSERT_TRUE(context);
54 const auto window_size = GetWindowSize();
55 ImpellerISize size = {window_size.width, window_size.height};
56 auto surface = Adopt<Surface>(ImpellerSurfaceCreateWrappedFBONew(
57 context.GetC(), //
58 0u, //
59 ImpellerPixelFormat::kImpellerPixelFormatRGBA8888, //
60 &size) //
61 );
62 ASSERT_TRUE(surface);
63 }
64
65 TEST_P(InteropPlaygroundTest, CanDrawRect) {
66 auto builder =
67 Adopt<DisplayListBuilder>(ImpellerDisplayListBuilderNew(nullptr));
68 auto paint = Adopt<Paint>(ImpellerPaintNew());
69 ImpellerColor color = {0.0, 0.0, 1.0, 1.0};
70 ImpellerPaintSetColor(paint.GetC(), &color);
71 ImpellerRect rect = {10, 20, 100, 200};
72 ImpellerDisplayListBuilderDrawRect(builder.GetC(), &rect, paint.GetC());
73 color = {1.0, 0.0, 0.0, 1.0};
74 ImpellerPaintSetColor(paint.GetC(), &color);
75 ImpellerDisplayListBuilderTranslate(builder.GetC(), 110, 210);
76 ImpellerMatrix scale_transform = {
77 // clang-format off
78 2.0, 0.0, 0.0, 0.0, //
79 0.0, 2.0, 0.0, 0.0, //
80 0.0, 0.0, 1.0, 0.0, //
81 0.0, 0.0, 0.0, 1.0, //
82 // clang-format on
83 };
84 ImpellerDisplayListBuilderTransform(builder.GetC(), &scale_transform);
85 ImpellerDisplayListBuilderDrawRect(builder.GetC(), &rect, paint.GetC());
86 auto dl = Adopt<DisplayList>(
87 ImpellerDisplayListBuilderCreateDisplayListNew(builder.GetC()));
88 ASSERT_TRUE(dl);
89 ASSERT_TRUE(
90 OpenPlaygroundHere([&](const auto& context, const auto& surface) -> bool {
91 ImpellerSurfaceDrawDisplayList(surface.GetC(), dl.GetC());
92 return true;
93 }));
94 }
95
96 TEST_P(InteropPlaygroundTest, CanDrawImage) {
97 auto compressed = LoadFixtureImageCompressed(
98 flutter::testing::OpenFixtureAsMapping("boston.jpg"));
99 ASSERT_NE(compressed, nullptr);
100 auto decompressed = compressed->Decode().ConvertToRGBA();
101 ASSERT_TRUE(decompressed.IsValid());
102 ImpellerMapping mapping = {};
103 mapping.data = decompressed.GetAllocation()->GetMapping();
104 mapping.length = decompressed.GetAllocation()->GetSize();
105
106 auto context = GetInteropContext();
107 ImpellerTextureDescriptor desc = {};
108 desc.pixel_format = ImpellerPixelFormat::kImpellerPixelFormatRGBA8888;
109 desc.size = {decompressed.GetSize().width, decompressed.GetSize().height};
110 desc.mip_count = 1u;
111 auto texture = Adopt<Texture>(ImpellerTextureCreateWithContentsNew(
112 context.GetC(), &desc, &mapping, nullptr));
113 ASSERT_TRUE(texture);
114 auto builder =
115 Adopt<DisplayListBuilder>(ImpellerDisplayListBuilderNew(nullptr));
116 ImpellerPoint point = {100, 100};
117 ImpellerDisplayListBuilderDrawTexture(builder.GetC(), texture.GetC(), &point,
118 kImpellerTextureSamplingLinear,
119 nullptr);
120 auto dl = Adopt<DisplayList>(
121 ImpellerDisplayListBuilderCreateDisplayListNew(builder.GetC()));
122 ASSERT_TRUE(
123 OpenPlaygroundHere([&](const auto& context, const auto& surface) -> bool {
124 ImpellerSurfaceDrawDisplayList(surface.GetC(), dl.GetC());
125 return true;
126 }));
127 }
128
129 TEST_P(InteropPlaygroundTest, CanCreateOpenGLImage) {
130 auto context = GetInteropContext();
131
132 auto impeller_context = context->GetContext();
133
134 if (impeller_context->GetBackendType() !=
135 impeller::Context::BackendType::kOpenGLES) {
136 GTEST_SKIP() << "This test works with OpenGL handles is only suitable for "
137 "that backend.";
138 return;
139 }
140
141 const auto& gl_context = ContextGLES::Cast(*impeller_context);
142 const auto& gl = gl_context.GetReactor()->GetProcTable();
143
144 constexpr ISize external_texture_size = {200, 300};
145
146 Allocation texture_data;
147 ASSERT_TRUE(
148 texture_data.Truncate(Bytes{external_texture_size.Area() * 4u}, false));
149
150 const auto kClearColor = Color::Fuchsia().ToR8G8B8A8();
151
152 for (size_t i = 0; i < external_texture_size.Area() * 4u; i += 4u) {
153 memcpy(texture_data.GetBuffer() + i, kClearColor.data(), 4);
154 }
155
156 GLuint external_texture = GL_NONE;
157 gl.GenTextures(1u, &external_texture);
158 ASSERT_NE(external_texture, 0u);
159 gl.BindTexture(GL_TEXTURE_2D, external_texture);
160 gl.TexImage2D(GL_TEXTURE_2D, //
161 0, //
162 GL_RGBA, //
163 external_texture_size.width, //
164 external_texture_size.height, //
165 0, //
166 GL_RGBA, //
167 GL_UNSIGNED_BYTE, //
168 texture_data.GetBuffer() //
169 );
170
171 ImpellerTextureDescriptor desc = {};
172 desc.pixel_format = ImpellerPixelFormat::kImpellerPixelFormatRGBA8888;
173 desc.size = {external_texture_size.width, external_texture_size.height};
174 desc.mip_count = 1u;
175 auto texture = Adopt<Texture>(ImpellerTextureCreateWithOpenGLTextureHandleNew(
176 context.GetC(), //
177 &desc, //
178 external_texture //
179 ));
180 ASSERT_TRUE(texture);
181
182 ASSERT_EQ(ImpellerTextureGetOpenGLHandle(texture.GetC()), external_texture);
183
184 auto builder =
185 Adopt<DisplayListBuilder>(ImpellerDisplayListBuilderNew(nullptr));
186 ImpellerPoint point = {100, 100};
187 ImpellerDisplayListBuilderDrawTexture(builder.GetC(), texture.GetC(), &point,
188 kImpellerTextureSamplingLinear,
189 nullptr);
190 auto dl = Adopt<DisplayList>(
191 ImpellerDisplayListBuilderCreateDisplayListNew(builder.GetC()));
192 ASSERT_TRUE(
193 OpenPlaygroundHere([&](const auto& context, const auto& surface) -> bool {
194 ImpellerSurfaceDrawDisplayList(surface.GetC(), dl.GetC());
195 return true;
196 }));
197 }
198
199 TEST_P(InteropPlaygroundTest, ClearsOpenGLStancilStateAfterTransition) {
200 auto context = GetInteropContext();
201 auto impeller_context = context->GetContext();
202 if (impeller_context->GetBackendType() !=
203 impeller::Context::BackendType::kOpenGLES) {
204 GTEST_SKIP() << "This test works with OpenGL handles is only suitable for "
205 "that backend.";
206 return;
207 }
208 const auto& gl_context = ContextGLES::Cast(*impeller_context);
209 const auto& gl = gl_context.GetReactor()->GetProcTable();
210 auto builder =
211 Adopt<DisplayListBuilder>(ImpellerDisplayListBuilderNew(nullptr));
212 auto paint = Adopt<Paint>(ImpellerPaintNew());
213 ImpellerColor color = {0.0, 0.0, 1.0, 1.0};
214 ImpellerPaintSetColor(paint.GetC(), &color);
215 ImpellerRect rect = {10, 20, 100, 200};
216 ImpellerDisplayListBuilderDrawRect(builder.GetC(), &rect, paint.GetC());
217 color = {1.0, 0.0, 0.0, 1.0};
218 ImpellerPaintSetColor(paint.GetC(), &color);
219 ImpellerDisplayListBuilderTranslate(builder.GetC(), 110, 210);
220 ImpellerDisplayListBuilderClipRect(builder.GetC(), &rect,
221 kImpellerClipOperationDifference);
222 ImpellerDisplayListBuilderDrawRect(builder.GetC(), &rect, paint.GetC());
223 auto dl = Adopt<DisplayList>(
224 ImpellerDisplayListBuilderCreateDisplayListNew(builder.GetC()));
225 ASSERT_TRUE(dl);
226 ASSERT_TRUE(
227 OpenPlaygroundHere([&](const auto& context, const auto& surface) -> bool {
228 ImpellerSurfaceDrawDisplayList(surface.GetC(), dl.GetC());
229 // OpenGL state is reset even though the operations above enable a
230 // stencil check.
231 GLboolean stencil_enabled = true;
232 gl.GetBooleanv(GL_STENCIL_TEST, &stencil_enabled);
233 return stencil_enabled == GL_FALSE;
234 }));
235 }
236
237 TEST_P(InteropPlaygroundTest, CanCreateParagraphs) {
238 // Create a typography context.
239 hpp::TypographyContext type_context;
240 ASSERT_TRUE(type_context);
241
242 // Create a builder.
243 hpp::ParagraphBuilder builder(type_context);
244 ASSERT_TRUE(builder);
245
246 // Create a paragraph style with the font size and foreground and background
247 // colors.
248 hpp::ParagraphStyle style;
249 ASSERT_TRUE(style);
250 style.SetFontSize(150.0f);
251 style.SetHeight(2.0f);
252
253 {
254 hpp::Paint paint;
255 ASSERT_TRUE(paint);
256 paint.SetColor({1.0, 0.0, 0.0, 1.0});
257 style.SetForeground(paint);
258 }
259
260 {
261 hpp::Paint paint;
262 paint.SetColor({1.0, 1.0, 1.0, 1.0});
263 style.SetBackground(paint);
264 }
265
266 // Push the style onto the style stack.
267 builder.PushStyle(style);
268 std::string text = "the ⚡️ quick ⚡️ brown 🦊 fox jumps over the lazy dog 🐶.";
269
270 // Add the paragraph text data.
271 builder.AddText(text);
272
273 // Layout and build the paragraph.
274 auto paragraph = builder.Build(1200.0f);
275 ASSERT_TRUE(paragraph);
276
277 // Create a display list with just the paragraph drawn into it.
278 hpp::DisplayListBuilder dl_builder;
279 dl_builder.DrawParagraph(paragraph, {20, 20});
280
281 // Build the display list.
282 auto dl = dl_builder.Build();
283
284 ASSERT_TRUE(
285 OpenPlaygroundHere([&](const auto& context, const auto& surface) -> bool {
286 hpp::Surface window(surface.GetC());
287 window.Draw(dl);
288 return true;
289 }));
290 }
291
292 TEST_P(InteropPlaygroundTest, CanCreateShapes) {
293 hpp::DisplayListBuilder builder;
294
295 hpp::Paint red_paint;
296 red_paint.SetColor({1.0, 0.0, 0.0, 1.0});
297 red_paint.SetStrokeWidth(10.0);
298
299 builder.Translate(10, 10);
300 builder.DrawRect({0, 0, 100, 100}, red_paint);
301 builder.Translate(100, 100);
302 builder.DrawOval({0, 0, 100, 100}, red_paint);
303 builder.Translate(100, 100);
304 builder.DrawLine({0, 0}, {100, 100}, red_paint);
305
306 builder.Translate(100, 100);
307 ImpellerRoundingRadii radii = {};
308 radii.top_left = {10, 10};
309 radii.bottom_right = {10, 10};
310 builder.DrawRoundedRect({0, 0, 100, 100}, radii, red_paint);
311
312 builder.Translate(100, 100);
313 builder.DrawPath(hpp::PathBuilder{}.AddOval({0, 0, 100, 100}).Build(),
314 red_paint);
315
316 auto dl = builder.Build();
317 ASSERT_TRUE(
318 OpenPlaygroundHere([&](const auto& context, const auto& surface) -> bool {
319 hpp::Surface window(surface.GetC());
320 window.Draw(dl);
321 return true;
322 }));
323 }
324
325 TEST_P(InteropPlaygroundTest, CanCreateParagraphsWithCustomFont) {
326 // Create a typography context.
327 auto type_context = Adopt<TypographyContext>(ImpellerTypographyContextNew());
328 ASSERT_TRUE(type_context);
329
330 // Open the custom font file.
331 std::unique_ptr<fml::Mapping> font_data =
332 flutter::testing::OpenFixtureAsMapping("wtf.otf");
333 ASSERT_NE(font_data, nullptr);
334 ASSERT_GT(font_data->GetSize(), 0u);
335 ImpellerMapping font_data_mapping = {
336 .data = font_data->GetMapping(),
337 .length = font_data->GetSize(),
338 .on_release = [](auto ctx) {
339 delete reinterpret_cast<fml::Mapping*>(ctx);
340 }};
341 auto registered =
342 ImpellerTypographyContextRegisterFont(type_context.GetC(), //
343 &font_data_mapping, //
344 font_data.release(), //
345 nullptr //
346 );
347 ASSERT_TRUE(registered);
348
349 // Create a builder.
350 auto builder =
351 Adopt<ParagraphBuilder>(ImpellerParagraphBuilderNew(type_context.GetC()));
352 ASSERT_TRUE(builder);
353
354 // Create a paragraph style with the font size and foreground and background
355 // colors.
356 auto style = Adopt<ParagraphStyle>(ImpellerParagraphStyleNew());
357 ASSERT_TRUE(style);
358 ImpellerParagraphStyleSetFontSize(style.GetC(), 150.0f);
359 ImpellerParagraphStyleSetFontFamily(style.GetC(), "WhatTheFlutter");
360
361 {
362 auto paint = Adopt<Paint>(ImpellerPaintNew());
363 ASSERT_TRUE(paint);
364 ImpellerColor color = {0.0, 1.0, 1.0, 1.0};
365 ImpellerPaintSetColor(paint.GetC(), &color);
366 ImpellerParagraphStyleSetForeground(style.GetC(), paint.GetC());
367 }
368
369 // Push the style onto the style stack.
370 ImpellerParagraphBuilderPushStyle(builder.GetC(), style.GetC());
371 std::string text = "0F0F0F0";
372
373 // Add the paragraph text data.
374 ImpellerParagraphBuilderAddText(builder.GetC(),
375 reinterpret_cast<const uint8_t*>(text.data()),
376 text.size());
377
378 // Layout and build the paragraph.
379 auto paragraph = Adopt<Paragraph>(
380 ImpellerParagraphBuilderBuildParagraphNew(builder.GetC(), 1200.0f));
381 ASSERT_TRUE(paragraph);
382
383 // Create a display list with just the paragraph drawn into it.
384 auto dl_builder =
385 Adopt<DisplayListBuilder>(ImpellerDisplayListBuilderNew(nullptr));
386 ImpellerPoint point = {20, 20};
387 ImpellerDisplayListBuilderDrawParagraph(dl_builder.GetC(), paragraph.GetC(),
388 &point);
389 auto dl = Adopt<DisplayList>(
390 ImpellerDisplayListBuilderCreateDisplayListNew(dl_builder.GetC()));
391
392 ASSERT_TRUE(
393 OpenPlaygroundHere([&](const auto& context, const auto& surface) -> bool {
394 ImpellerSurfaceDrawDisplayList(surface.GetC(), dl.GetC());
395 return true;
396 }));
397 } // namespace impeller::interop::testing
398
399 static void DrawTextFrame(const hpp::TypographyContext& tc,
400 hpp::DisplayListBuilder& builder,
401 hpp::ParagraphStyle& p_style,
402 const hpp::Paint& bg,
403 ImpellerColor color,
404 ImpellerTextAlignment align,
405 float x_offset) {
406 const char text[] =
407 "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
408
409 hpp::Paint fg;
410
411 // Draw a box.
412 fg.SetColor(color);
413 fg.SetDrawStyle(kImpellerDrawStyleStroke);
414 ImpellerRect box_rect = {10 + x_offset, 10, 200, 200};
415 builder.DrawRect(box_rect, fg);
416
417 // Draw text.
418 fg.SetDrawStyle(kImpellerDrawStyleFill);
419 p_style.SetForeground(fg);
420 p_style.SetBackground(bg);
421 p_style.SetTextAlignment(align);
422
423 hpp::ParagraphBuilder p_builder(tc);
424 p_builder.PushStyle(p_style);
425 p_builder.AddText(reinterpret_cast<const uint8_t*>(text), sizeof(text));
426
427 auto left_p = p_builder.Build(box_rect.width - 20.0);
428 ImpellerPoint pt = {20.0f + x_offset, 20.0f};
429 float w = left_p.GetMaxWidth();
430 float h = left_p.GetHeight();
431 builder.DrawParagraph(left_p, pt);
432 fg.SetDrawStyle(kImpellerDrawStyleStroke);
433
434 // Draw an inner box around the paragraph layout.
435 ImpellerRect inner_box_rect = {pt.x, pt.y, w, h};
436 builder.DrawRect(inner_box_rect, fg);
437 }
438
439 TEST_P(InteropPlaygroundTest, CanRenderTextAlignments) {
440 hpp::TypographyContext tc;
441
442 hpp::DisplayListBuilder builder;
443 hpp::Paint bg;
444 hpp::ParagraphStyle p_style;
445 p_style.SetFontFamily("Roboto");
446 p_style.SetFontSize(24.0);
447 p_style.SetFontWeight(kImpellerFontWeight400);
448
449 // Clear the background to a white color.
450 ImpellerColor clear_color = {1.0, 1.0, 1.0, 1.0};
451 bg.SetColor(clear_color);
452 builder.DrawPaint(bg);
453
454 // Draw red, left-aligned text.
455 ImpellerColor red = {1.0, 0.0, 0.0, 1.0};
456 DrawTextFrame(tc, builder, p_style, bg, red, kImpellerTextAlignmentLeft, 0.0);
457
458 // Draw green, centered text.
459 ImpellerColor green = {0.0, 1.0, 0.0, 1.0};
460 DrawTextFrame(tc, builder, p_style, bg, green, kImpellerTextAlignmentCenter,
461 220.0);
462
463 // Draw blue, right-aligned text.
464 ImpellerColor blue = {0.0, 0.0, 1.0, 1.0};
465 DrawTextFrame(tc, builder, p_style, bg, blue, kImpellerTextAlignmentRight,
466 440.0);
467
468 auto dl = builder.Build();
469
470 ASSERT_TRUE(
471 OpenPlaygroundHere([&](const auto& context, const auto& surface) -> bool {
472 hpp::Surface window(surface.GetC());
473 window.Draw(dl);
474 return true;
475 }));
476 }
477
478 TEST_P(InteropPlaygroundTest, CanRenderShadows) {
479 hpp::DisplayListBuilder builder;
480 {
481 builder.DrawRect(ImpellerRect{0, 0, 400, 400},
482 hpp::Paint{}.SetColor(ImpellerColor{
483 0.0, 1.0, 0.0, 1.0, kImpellerColorSpaceSRGB}));
484 }
485 ImpellerRect box = {100, 100, 100, 100};
486 {
487 hpp::PathBuilder path_builder;
488 path_builder.AddRect(box);
489 ImpellerColor shadow_color = {0.0, 0.0, 0.0, 1.0, kImpellerColorSpaceSRGB};
490 builder.DrawShadow(path_builder.Build(), shadow_color, 4.0f, false, 1.0f);
491 }
492 {
493 hpp::Paint red_paint;
494 red_paint.SetColor(
495 ImpellerColor{1.0, 0.0, 0.0, 1.0, kImpellerColorSpaceSRGB});
496 builder.DrawRect(box, red_paint);
497 }
498 auto dl = builder.Build();
499 ASSERT_TRUE(
500 OpenPlaygroundHere([&](const auto& context, const auto& surface) -> bool {
501 hpp::Surface window(surface.GetC());
502 window.Draw(dl);
503 return true;
504 }));
505 }
506
507 TEST_P(InteropPlaygroundTest, CanMeasureText) {
508 hpp::TypographyContext type_context;
509 hpp::ParagraphBuilder paragraph_builder(type_context);
510 hpp::ParagraphStyle paragraph_style;
511 paragraph_style.SetFontSize(50);
512 paragraph_builder.PushStyle(paragraph_style);
513 const std::string text =
514 "🏁 Can 👨‍👨‍👦‍👦 Measure 🔍 Text\nAnd this is line "
515 "two.\nWhoa! Three lines. How high does this go?\r\nI stopped counting.";
516 const auto u16text = fml::Utf8ToUtf16(text);
517 ASSERT_NE(text.size(), u16text.size());
518 paragraph_builder.AddText(reinterpret_cast<const uint8_t*>(text.data()),
519 text.size());
520 hpp::DisplayListBuilder builder;
521 // Don't rely on implicit line breaks in this test to make it less brittle to
522 // different fonts being picked.
523 hpp::Paragraph paragraph = paragraph_builder.Build(FLT_MAX);
524 const auto line_count = paragraph.GetLineCount();
525 ASSERT_EQ(line_count, 4u);
526
527 // Line Metrics.
528 {
529 auto metrics = paragraph.GetLineMetrics();
530 ASSERT_GT(metrics.GetAscent(0), 0.0);
531 ASSERT_GT(metrics.GetUnscaledAscent(0), 0.0);
532 ASSERT_GT(metrics.GetDescent(0), 0.0);
533 ASSERT_GT(metrics.GetBaseline(0), 0.0);
534 ASSERT_TRUE(metrics.IsHardbreak(0));
535 ASSERT_DOUBLE_EQ(metrics.GetLeft(0), 0.0);
536 ASSERT_EQ(metrics.GetCodeUnitStartIndex(0), 0u);
537 ASSERT_EQ(metrics.GetCodeUnitEndIndexIncludingNewline(0),
538 metrics.GetCodeUnitEndIndex(0) + 1u);
539 ASSERT_GT(metrics.GetCodeUnitStartIndex(1), 0u);
540 // Last line should cover the entire range.
541 ASSERT_EQ(metrics.GetCodeUnitEndIndex(3), u16text.size());
542 }
543
544 // Glyph info by code point.
545 {
546 auto glyph = paragraph.GlyphInfoAtCodeUnitIndex(0u);
547 ASSERT_TRUE(glyph);
548 ASSERT_EQ(glyph.GetGraphemeClusterCodeUnitRangeBegin(), 0u);
549 ASSERT_EQ(glyph.GetGraphemeClusterCodeUnitRangeEnd(),
550 fml::Utf8ToUtf16("🏁").size());
551 auto bounds = glyph.GetGraphemeClusterBounds();
552 ASSERT_GT(bounds.width, 0.0);
553 ASSERT_GT(bounds.height, 0.0);
554 ASSERT_FALSE(glyph.IsEllipsis());
555 ASSERT_EQ(glyph.GetTextDirection(), kImpellerTextDirectionLTR);
556 }
557
558 // Glyph info by coordinates.
559 {
560 auto glyph = paragraph.GlyphInfoAtParagraphCoordinates(0.0, 0.0);
561 ASSERT_TRUE(glyph);
562 ASSERT_EQ(glyph.GetGraphemeClusterCodeUnitRangeEnd(),
563 fml::Utf8ToUtf16("🏁").size());
564 }
565
566 // Glyph Figure out word boundaries.
567 {
568 auto glyph = paragraph.GlyphInfoAtCodeUnitIndex(0u);
569 ASSERT_TRUE(glyph);
570 auto range =
571 paragraph.GetWordBoundary(glyph.GetGraphemeClusterCodeUnitRangeEnd());
572 ASSERT_GT(range.end, 0u);
573 }
574
575 builder.DrawParagraph(paragraph, ImpellerPoint{100, 100});
576 auto dl = builder.Build();
577 ASSERT_TRUE(
578 OpenPlaygroundHere([&](const auto& context, const auto& surface) -> bool {
579 hpp::Surface window(surface.GetC());
580 window.Draw(dl);
581 return true;
582 }));
583 }
584
585 } // namespace impeller::interop::testing
allocation.h
impeller::Allocation
Describes an allocation on the heap.
Definition: allocation.h:22
impeller::Allocation::GetBuffer
uint8_t * GetBuffer() const
Gets the pointer to the start of the allocation.
Definition: allocation.cc:20
impeller::Allocation::Truncate
bool Truncate(Bytes length, bool npot=true)
Resize the underlying allocation to at least given number of bytes.
Definition: allocation.cc:32
impeller::AllocationSize< 1u >
impeller::BackendCast< ContextGLES, Context >::Cast
static ContextGLES & Cast(Context &base)
Definition: backend_cast.h:13
impeller::Context::BackendType::kOpenGLES
@ kOpenGLES
impeller::interop::testing::PlaygroundTest
Definition: playground_test.h:16
dl.h
dl_builder.h
impeller.h
kImpellerTextDirectionLTR
@ kImpellerTextDirectionLTR
Definition: impeller.h:472
kImpellerTextureSamplingLinear
@ kImpellerTextureSamplingLinear
Definition: impeller.h:421
kImpellerFontWeight400
@ kImpellerFontWeight400
Definition: impeller.h:448
kImpellerDrawStyleStroke
@ kImpellerDrawStyleStroke
Definition: impeller.h:399
kImpellerDrawStyleFill
@ kImpellerDrawStyleFill
Definition: impeller.h:398
kImpellerColorSpaceSRGB
@ kImpellerColorSpaceSRGB
Definition: impeller.h:439
ImpellerTextAlignment
ImpellerTextAlignment
Definition: impeller.h:461
kImpellerTextAlignmentLeft
@ kImpellerTextAlignmentLeft
Definition: impeller.h:462
kImpellerTextAlignmentCenter
@ kImpellerTextAlignmentCenter
Definition: impeller.h:464
kImpellerTextAlignmentRight
@ kImpellerTextAlignmentRight
Definition: impeller.h:463
kImpellerClipOperationDifference
@ kImpellerClipOperationDifference
Definition: impeller.h:361
kImpellerPixelFormatRGBA8888
@ kImpellerPixelFormatRGBA8888
Definition: impeller.h:416
impeller.hpp
impeller::android::testing::CreateContext
std::shared_ptr< Context > CreateContext()
Definition: ahb_texture_source_vk_unittests.cc:19
impeller::interop::testing
Definition: impeller_unittests.cc:25
impeller::interop::testing::TEST_P
TEST_P(InteropPlaygroundTest, CanCreateContext)
Definition: impeller_unittests.cc:30
impeller::interop::testing::DrawTextFrame
static void DrawTextFrame(const hpp::TypographyContext &tc, hpp::DisplayListBuilder &builder, hpp::ParagraphStyle &p_style, const hpp::Paint &bg, ImpellerColor color, ImpellerTextAlignment align, float x_offset)
Definition: impeller_unittests.cc:399
impeller::interop::testing::INSTANTIATE_PLAYGROUND_SUITE
INSTANTIATE_PLAYGROUND_SUITE(InteropPlaygroundTest)
impeller::interop::ImpellerTextureGetOpenGLHandle
IMPELLER_EXTERN_C uint64_t ImpellerTextureGetOpenGLHandle(ImpellerTexture texture)
Definition: impeller.cc:683
impeller::interop::ImpellerSurfaceCreateWrappedFBONew
IMPELLER_EXTERN_C ImpellerSurface ImpellerSurfaceCreateWrappedFBONew(ImpellerContext context, uint64_t fbo, ImpellerPixelFormat format, const ImpellerISize *size)
Definition: impeller.cc:724
impeller::interop::ImpellerDisplayListBuilderCreateDisplayListNew
IMPELLER_EXTERN_C ImpellerDisplayList ImpellerDisplayListBuilderCreateDisplayListNew(ImpellerDisplayListBuilder builder)
Definition: impeller.cc:706
impeller::interop::ImpellerParagraphBuilderNew
IMPELLER_EXTERN_C ImpellerParagraphBuilder ImpellerParagraphBuilderNew(ImpellerTypographyContext context)
Definition: impeller.cc:1173
impeller::interop::ImpellerDisplayListBuilderNew
IMPELLER_EXTERN_C ImpellerDisplayListBuilder ImpellerDisplayListBuilderNew(const ImpellerRect *cull_rect)
Definition: impeller.cc:224
impeller::interop::ImpellerPaintNew
IMPELLER_EXTERN_C ImpellerPaint ImpellerPaintNew()
Definition: impeller.cc:456
impeller::interop::ImpellerParagraphBuilderBuildParagraphNew
IMPELLER_EXTERN_C ImpellerParagraph ImpellerParagraphBuilderBuildParagraphNew(ImpellerParagraphBuilder paragraph_builder, float width)
Definition: impeller.cc:1223
impeller::interop::ImpellerParagraphBuilderPushStyle
IMPELLER_EXTERN_C void ImpellerParagraphBuilderPushStyle(ImpellerParagraphBuilder paragraph_builder, ImpellerParagraphStyle style)
Definition: impeller.cc:1197
impeller::interop::ImpellerTypographyContextNew
IMPELLER_EXTERN_C ImpellerTypographyContext ImpellerTypographyContextNew()
Definition: impeller.cc:1286
impeller::interop::ImpellerDisplayListBuilderClipRect
IMPELLER_EXTERN_C void ImpellerDisplayListBuilderClipRect(ImpellerDisplayListBuilder builder, const ImpellerRect *rect, ImpellerClipOperation op)
Definition: impeller.cc:423
impeller::interop::ToImpellerType
constexpr Matrix ToImpellerType(const ImpellerMatrix &m)
Definition: formats.h:201
impeller::interop::ImpellerTextureCreateWithOpenGLTextureHandleNew
IMPELLER_EXTERN_C ImpellerTexture ImpellerTextureCreateWithOpenGLTextureHandleNew(ImpellerContext context, const ImpellerTextureDescriptor *descriptor, uint64_t external_gl_handle)
Definition: impeller.cc:633
impeller::interop::ImpellerTextureCreateWithContentsNew
IMPELLER_EXTERN_C ImpellerTexture ImpellerTextureCreateWithContentsNew(ImpellerContext context, const ImpellerTextureDescriptor *descriptor, const ImpellerMapping *contents, void *contents_on_release_user_data)
Definition: impeller.cc:588
impeller::interop::ImpellerDisplayListBuilderTransform
IMPELLER_EXTERN_C void ImpellerDisplayListBuilderTransform(ImpellerDisplayListBuilder builder, const ImpellerMatrix *transform)
Definition: impeller.cc:287
impeller::interop::ImpellerTypographyContextRegisterFont
IMPELLER_EXTERN_C bool ImpellerTypographyContextRegisterFont(ImpellerTypographyContext context, const ImpellerMapping *contents, void *contents_on_release_user_data, const char *family_name_alias)
Definition: impeller.cc:1306
impeller::interop::ImpellerParagraphStyleSetFontSize
IMPELLER_EXTERN_C void ImpellerParagraphStyleSetFontSize(ImpellerParagraphStyle paragraph_style, float size)
Definition: impeller.cc:1113
impeller::interop::ImpellerDisplayListBuilderDrawParagraph
IMPELLER_EXTERN_C void ImpellerDisplayListBuilderDrawParagraph(ImpellerDisplayListBuilder builder, ImpellerParagraph paragraph, const ImpellerPoint *point)
Definition: impeller.cc:1151
impeller::interop::ImpellerParagraphStyleSetFontFamily
IMPELLER_EXTERN_C void ImpellerParagraphStyleSetFontFamily(ImpellerParagraphStyle paragraph_style, const char *family_name)
Definition: impeller.cc:1107
impeller::interop::ImpellerSurfaceDrawDisplayList
IMPELLER_EXTERN_C bool ImpellerSurfaceDrawDisplayList(ImpellerSurface surface, ImpellerDisplayList display_list)
Definition: impeller.cc:770
impeller::interop::ImpellerDisplayListBuilderTranslate
IMPELLER_EXTERN_C void ImpellerDisplayListBuilderTranslate(ImpellerDisplayListBuilder builder, float x_translation, float y_translation)
Definition: impeller.cc:274
impeller::interop::ImpellerParagraphStyleSetForeground
IMPELLER_EXTERN_C void ImpellerParagraphStyleSetForeground(ImpellerParagraphStyle paragraph_style, ImpellerPaint paint)
Definition: impeller.cc:1076
impeller::interop::ImpellerParagraphStyleNew
IMPELLER_EXTERN_C ImpellerParagraphStyle ImpellerParagraphStyleNew()
Definition: impeller.cc:1061
impeller::interop::ImpellerDisplayListBuilderDrawTexture
IMPELLER_EXTERN_C void ImpellerDisplayListBuilderDrawTexture(ImpellerDisplayListBuilder builder, ImpellerTexture texture, const ImpellerPoint *point, ImpellerTextureSampling sampling, ImpellerPaint paint)
Definition: impeller.cc:781
impeller::interop::ImpellerDisplayListBuilderDrawRect
IMPELLER_EXTERN_C void ImpellerDisplayListBuilderDrawRect(ImpellerDisplayListBuilder builder, const ImpellerRect *rect, ImpellerPaint paint)
Definition: impeller.cc:539
impeller::interop::ImpellerPaintSetColor
IMPELLER_EXTERN_C void ImpellerPaintSetColor(ImpellerPaint paint, const ImpellerColor *color)
Definition: impeller.cc:471
impeller::interop::ImpellerParagraphBuilderAddText
IMPELLER_EXTERN_C void ImpellerParagraphBuilderAddText(ImpellerParagraphBuilder paragraph_builder, const uint8_t *data, uint32_t length)
Definition: impeller.cc:1210
impeller::PlaygroundBackend::kOpenGLES
@ kOpenGLES
paragraph.h
paragraph_builder.h
paragraph_style.h
context_gles.h
ImpellerColor
Definition: impeller.h:588
ImpellerISize
Definition: impeller.h:495
ImpellerISize::width
int64_t width
Definition: impeller.h:496
ImpellerMapping
Definition: impeller.h:602
ImpellerMapping::length
uint64_t length
Definition: impeller.h:604
ImpellerMapping::data
const uint8_t *IMPELLER_NONNULL data
Definition: impeller.h:603
ImpellerMatrix
Definition: impeller.h:515
ImpellerPoint
Definition: impeller.h:485
ImpellerPoint::x
float x
Definition: impeller.h:486
ImpellerPoint::y
float y
Definition: impeller.h:487
ImpellerRect
Definition: impeller.h:478
ImpellerRect::width
float width
Definition: impeller.h:481
ImpellerRoundingRadii
Definition: impeller.h:581
ImpellerRoundingRadii::top_left
ImpellerPoint top_left
Definition: impeller.h:582
ImpellerRoundingRadii::bottom_right
ImpellerPoint bottom_right
Definition: impeller.h:585
ImpellerTextureDescriptor
Definition: impeller.h:596
ImpellerTextureDescriptor::mip_count
uint32_t mip_count
Definition: impeller.h:599
ImpellerTextureDescriptor::pixel_format
ImpellerPixelFormat pixel_format
Definition: impeller.h:597
ImpellerTextureDescriptor::size
ImpellerISize size
Definition: impeller.h:598
impeller::Color::ToR8G8B8A8
constexpr std::array< uint8_t, 4 > ToR8G8B8A8() const
Convert to R8G8B8A8 representation.
Definition: color.h:246
impeller::Color::Fuchsia
static constexpr Color Fuchsia()
Definition: color.h:466
impeller::Matrix::IsIdentity
constexpr bool IsIdentity() const
Definition: matrix.h:414
impeller::TSize
Definition: size.h:25
context.h
formats.h
paint.h
playground_test.h
surface.h
texture.h
typography_context.h