5 #include "flutter/fml/native_library.h"
6 #include "flutter/fml/string_conversion.h"
7 #include "flutter/testing/testing.h"
39 hpp::DisplayListBuilder builder;
42 ASSERT_EQ(builder.GetSaveCount(), 1u);
44 ASSERT_EQ(builder.GetSaveCount(), 2u);
46 ASSERT_EQ(builder.GetSaveCount(), 1u);
52 <<
"This test checks wrapping FBOs which is an OpenGL ES only call.";
57 const auto window_size = GetWindowSize();
76 color = {1.0, 0.0, 0.0, 1.0};
89 auto dl = Adopt<DisplayList>(
93 OpenPlaygroundHere([&](
const auto& context,
const auto& surface) ->
bool {
100 auto compressed = LoadFixtureImageCompressed(
101 flutter::testing::OpenFixtureAsMapping(
"boston.jpg"));
102 ASSERT_NE(compressed,
nullptr);
103 auto decompressed = std::make_shared<impeller::DecompressedImage>(
104 compressed->Decode().ConvertToRGBA());
105 ASSERT_TRUE(decompressed->IsValid());
106 auto mapping = std::make_unique<hpp::Mapping>(
107 decompressed->GetAllocation()->GetMapping(),
108 decompressed->GetAllocation()->GetSize(), [decompressed]() {
112 auto context = GetHPPContext();
115 desc.
size = {decompressed->GetSize().
width, decompressed->GetSize().height};
117 auto texture = hpp::Texture::WithContents(context, desc, std::move(mapping));
118 ASSERT_TRUE(texture);
120 auto dl = hpp::DisplayListBuilder{}
121 .DrawTexture(texture, {100, 100},
126 OpenPlaygroundHere([&](
const auto& context,
const auto& surface) ->
bool {
127 hpp::Surface window(surface.GetC());
134 auto context = GetInteropContext();
136 auto impeller_context = context->GetContext();
138 if (impeller_context->GetBackendType() !=
140 GTEST_SKIP() <<
"This test works with OpenGL handles is only suitable for "
146 const auto& gl = gl_context.GetReactor()->GetProcTable();
148 constexpr
ISize external_texture_size = {200, 300};
152 texture_data.
Truncate(
Bytes{external_texture_size.Area() * 4u},
false));
156 for (
size_t i = 0; i < external_texture_size.Area() * 4u; i += 4u) {
157 memcpy(texture_data.
GetBuffer() + i, kClearColor.data(), 4);
160 GLuint external_texture = GL_NONE;
161 gl.GenTextures(1u, &external_texture);
162 ASSERT_NE(external_texture, 0u);
163 gl.BindTexture(GL_TEXTURE_2D, external_texture);
164 gl.TexImage2D(GL_TEXTURE_2D,
167 external_texture_size.width,
168 external_texture_size.height,
177 desc.
size = {external_texture_size.
width, external_texture_size.height};
184 ASSERT_TRUE(texture);
194 auto dl = Adopt<DisplayList>(
197 OpenPlaygroundHere([&](
const auto& context,
const auto& surface) ->
bool {
204 auto context = GetInteropContext();
205 auto impeller_context = context->GetContext();
206 if (impeller_context->GetBackendType() !=
208 GTEST_SKIP() <<
"This test works with OpenGL handles is only suitable for "
213 const auto& gl = gl_context.GetReactor()->GetProcTable();
221 color = {1.0, 0.0, 0.0, 1.0};
227 auto dl = Adopt<DisplayList>(
231 OpenPlaygroundHere([&](
const auto& context,
const auto& surface) ->
bool {
235 GLboolean stencil_enabled =
true;
236 gl.GetBooleanv(GL_STENCIL_TEST, &stencil_enabled);
237 return stencil_enabled == GL_FALSE;
243 hpp::TypographyContext type_context;
244 ASSERT_TRUE(type_context);
247 hpp::ParagraphBuilder builder(type_context);
248 ASSERT_TRUE(builder);
252 hpp::ParagraphStyle style;
254 style.SetFontSize(150.0f);
255 style.SetHeight(2.0f);
260 paint.SetColor({1.0, 0.0, 0.0, 1.0});
261 style.SetForeground(paint);
266 paint.SetColor({1.0, 1.0, 1.0, 1.0});
267 style.SetBackground(paint);
271 builder.PushStyle(style);
272 std::string text =
"the ⚡️ quick ⚡️ brown 🦊 fox jumps over the lazy dog 🐶.";
275 builder.AddText(text);
278 auto paragraph = builder.Build(1200.0f);
279 ASSERT_TRUE(paragraph);
282 hpp::DisplayListBuilder dl_builder;
283 dl_builder.DrawParagraph(paragraph, {20, 20});
286 auto dl = dl_builder.Build();
289 OpenPlaygroundHere([&](
const auto& context,
const auto& surface) ->
bool {
290 hpp::Surface window(surface.GetC());
297 hpp::TypographyContext context;
299 hpp::ParagraphBuilder(context)
301 hpp::ParagraphStyle{}
302 .SetForeground(hpp::Paint{}.SetColor({1.0, 0.0, 0.0, 1.0}))
309 .thickness_multiplier = 1.5,
311 .AddText(std::string{
"Holy text decorations Batman!"})
313 auto dl = hpp::DisplayListBuilder{}.DrawParagraph(para, {100, 100}).Build();
315 OpenPlaygroundHere([&](
const auto& context,
const auto& surface) ->
bool {
316 hpp::Surface window(surface.GetC());
323 hpp::DisplayListBuilder builder;
325 hpp::Paint red_paint;
326 red_paint.SetColor({1.0, 0.0, 0.0, 1.0});
327 red_paint.SetStrokeWidth(10.0);
329 builder.Translate(10, 10);
330 builder.DrawRect({0, 0, 100, 100}, red_paint);
331 builder.Translate(100, 100);
332 builder.DrawOval({0, 0, 100, 100}, red_paint);
333 builder.Translate(100, 100);
334 builder.DrawLine({0, 0}, {100, 100}, red_paint);
336 builder.Translate(100, 100);
340 builder.DrawRoundedRect({0, 0, 100, 100}, radii, red_paint);
342 builder.Translate(100, 100);
346 auto dl = builder.Build();
348 OpenPlaygroundHere([&](
const auto& context,
const auto& surface) ->
bool {
349 hpp::Surface window(surface.GetC());
358 ASSERT_TRUE(type_context);
361 std::unique_ptr<fml::Mapping> font_data =
362 flutter::testing::OpenFixtureAsMapping(
"wtf.otf");
363 ASSERT_NE(font_data,
nullptr);
364 ASSERT_GT(font_data->GetSize(), 0u);
366 .
data = font_data->GetMapping(),
367 .length = font_data->GetSize(),
368 .on_release = [](
auto ctx) {
369 delete reinterpret_cast<fml::Mapping*
>(ctx);
377 ASSERT_TRUE(registered);
382 ASSERT_TRUE(builder);
401 std::string text =
"0F0F0F0";
405 reinterpret_cast<const uint8_t*
>(text.data()),
409 auto paragraph = Adopt<Paragraph>(
411 ASSERT_TRUE(paragraph);
419 auto dl = Adopt<DisplayList>(
423 OpenPlaygroundHere([&](
const auto& context,
const auto& surface) ->
bool {
430 hpp::DisplayListBuilder& builder,
431 hpp::ParagraphStyle& p_style,
432 const hpp::Paint& bg,
437 "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
445 builder.DrawRect(box_rect, fg);
449 p_style.SetForeground(fg);
450 p_style.SetBackground(bg);
451 p_style.SetTextAlignment(align);
453 hpp::ParagraphBuilder p_builder(tc);
454 p_builder.PushStyle(p_style);
455 p_builder.AddText(
reinterpret_cast<const uint8_t*
>(text),
sizeof(text));
457 auto left_p = p_builder.Build(box_rect.
width - 20.0);
459 float w = left_p.GetMaxWidth();
460 float h = left_p.GetHeight();
461 builder.DrawParagraph(left_p, pt);
466 builder.DrawRect(inner_box_rect, fg);
470 hpp::TypographyContext tc;
472 hpp::DisplayListBuilder builder;
474 hpp::ParagraphStyle p_style;
475 p_style.SetFontFamily(
"Roboto");
476 p_style.SetFontSize(24.0);
481 bg.SetColor(clear_color);
482 builder.DrawPaint(bg);
498 auto dl = builder.Build();
501 OpenPlaygroundHere([&](
const auto& context,
const auto& surface) ->
bool {
502 hpp::Surface window(surface.GetC());
509 hpp::DisplayListBuilder builder;
518 path_builder.AddRect(box);
520 builder.DrawShadow(path_builder.Build(), shadow_color, 4.0f,
false, 1.0f);
523 hpp::Paint red_paint;
526 builder.DrawRect(box, red_paint);
528 auto dl = builder.Build();
530 OpenPlaygroundHere([&](
const auto& context,
const auto& surface) ->
bool {
531 hpp::Surface window(surface.GetC());
538 hpp::TypographyContext type_context;
539 hpp::ParagraphBuilder paragraph_builder(type_context);
540 hpp::ParagraphStyle paragraph_style;
541 paragraph_style.SetFontSize(50);
542 paragraph_builder.PushStyle(paragraph_style);
543 const std::string text =
544 "🏁 Can 👨👨👦👦 Measure 🔍 Text\nAnd this is line "
545 "two.\nWhoa! Three lines. How high does this go?\r\nI stopped counting.";
546 const auto u16text = fml::Utf8ToUtf16(text);
547 ASSERT_NE(text.size(), u16text.size());
548 paragraph_builder.AddText(
reinterpret_cast<const uint8_t*
>(text.data()),
550 hpp::DisplayListBuilder builder;
553 hpp::Paragraph paragraph = paragraph_builder.Build(FLT_MAX);
554 const auto line_count = paragraph.GetLineCount();
555 ASSERT_EQ(line_count, 4u);
559 auto metrics = paragraph.GetLineMetrics();
560 ASSERT_GT(metrics.GetAscent(0), 0.0);
561 ASSERT_GT(metrics.GetUnscaledAscent(0), 0.0);
562 ASSERT_GT(metrics.GetDescent(0), 0.0);
563 ASSERT_GT(metrics.GetBaseline(0), 0.0);
564 ASSERT_TRUE(metrics.IsHardbreak(0));
565 ASSERT_DOUBLE_EQ(metrics.GetLeft(0), 0.0);
566 ASSERT_EQ(metrics.GetCodeUnitStartIndex(0), 0u);
567 ASSERT_EQ(metrics.GetCodeUnitEndIndexIncludingNewline(0),
568 metrics.GetCodeUnitEndIndex(0) + 1u);
569 ASSERT_GT(metrics.GetCodeUnitStartIndex(1), 0u);
571 ASSERT_EQ(metrics.GetCodeUnitEndIndex(3), u16text.size());
576 auto glyph = paragraph.GlyphInfoAtCodeUnitIndex(0u);
578 ASSERT_EQ(glyph.GetGraphemeClusterCodeUnitRangeBegin(), 0u);
579 ASSERT_EQ(glyph.GetGraphemeClusterCodeUnitRangeEnd(),
580 fml::Utf8ToUtf16(
"🏁").size());
581 auto bounds = glyph.GetGraphemeClusterBounds();
582 ASSERT_GT(bounds.width, 0.0);
583 ASSERT_GT(bounds.height, 0.0);
584 ASSERT_FALSE(glyph.IsEllipsis());
589 ASSERT_EQ(bounds.width, bounds2.
width);
590 ASSERT_EQ(bounds.height, bounds2.
height);
595 auto glyph = paragraph.GlyphInfoAtParagraphCoordinates(0.0, 0.0);
597 ASSERT_EQ(glyph.GetGraphemeClusterCodeUnitRangeEnd(),
598 fml::Utf8ToUtf16(
"🏁").size());
603 auto glyph = paragraph.GlyphInfoAtCodeUnitIndex(0u);
606 paragraph.GetWordBoundary(glyph.GetGraphemeClusterCodeUnitRangeEnd());
607 ASSERT_GT(range.end, 0u);
610 paragraph.Get(), glyph.GetGraphemeClusterCodeUnitRangeEnd(), &range2);
611 ASSERT_EQ(range.start, range2.
start);
612 ASSERT_EQ(range.end, range2.
end);
616 auto dl = builder.Build();
618 OpenPlaygroundHere([&](
const auto& context,
const auto& surface) ->
bool {
619 hpp::Surface window(surface.GetC());
628 const auto bounds = path.GetBounds();
629 ASSERT_EQ(bounds.x, 100);
630 ASSERT_EQ(bounds.y, 100);
631 ASSERT_EQ(bounds.width, 100);
632 ASSERT_EQ(bounds.height, 100);
636 hpp::TypographyContext context;
637 auto style = hpp::ParagraphStyle{};
638 style.SetFontSize(50);
639 style.SetForeground(hpp::Paint{}.SetColor({.red = 1.0, .alpha = 1.0}));
640 const auto text = std::string{
"The quick brown fox jumped over the lazy dog"};
641 style.SetEllipsis(
"🐶");
643 hpp::ParagraphBuilder{context}.PushStyle(style).AddText(text).Build(250);
644 style.SetForeground(hpp::Paint{}.SetColor({.green = 1.0, .alpha = 1.0}));
645 style.SetEllipsis(
nullptr);
647 hpp::ParagraphBuilder{context}.PushStyle(style).AddText(text).Build(250);
648 auto dl = hpp::DisplayListBuilder{}
649 .DrawParagraph(para1, {100, 100})
650 .DrawParagraph(para2, {100, 200})
653 OpenPlaygroundHere([&](
const auto& context,
const auto& surface) ->
bool {
654 hpp::Surface window(surface.GetC());
661 auto iplr = OpenAssetAsHPPMapping(
"interop_runtime_stage_cs.frag.iplr");
663 auto program = hpp::FragmentProgram::WithData(std::move(iplr));
664 ASSERT_TRUE(program);
665 auto context = GetHPPContext();
667 hpp::ImageFilter::FragmentProgram(context, program, {},
nullptr);
669 auto bay_bridge = OpenAssetAsHPPTexture(
"bay_bridge.jpg");
670 ASSERT_TRUE(bay_bridge);
672 float size_data[4] = {500, 500};
673 auto uniform_data = hpp::Mapping{
reinterpret_cast<const uint8_t*
>(&size_data),
674 sizeof(size_data),
nullptr};
676 auto dl = hpp::DisplayListBuilder{}
677 .DrawRect({10, 10, 500, 500},
679 .SetColor({1.0, 1.0, 1.0, 1.0})
680 .SetColorSource(hpp::ColorSource::FragmentProgram(
688 OpenPlaygroundHere([&](
const auto& context,
const auto& surface) ->
bool {
689 hpp::Surface window(surface.GetC());
696 bool deleted =
false;
698 hpp::Mapping mapping(
nullptr, 0, [&deleted]() { deleted =
true; });
700 ASSERT_TRUE(deleted);
Describes an allocation on the heap.
uint8_t * GetBuffer() const
Gets the pointer to the start of the allocation.
bool Truncate(Bytes length, bool npot=true)
Resize the underlying allocation to at least given number of bytes.
static ContextGLES & Cast(Context &base)
@ kImpellerTextDirectionLTR
@ kImpellerTextureSamplingLinear
@ kImpellerTextDecorationTypeLineThrough
@ kImpellerTextDecorationTypeUnderline
@ kImpellerTextDecorationStyleWavy
@ kImpellerDrawStyleStroke
@ kImpellerColorSpaceSRGB
@ kImpellerTextAlignmentLeft
@ kImpellerTextAlignmentCenter
@ kImpellerTextAlignmentRight
@ kImpellerClipOperationDifference
@ kImpellerPixelFormatRGBA8888
std::shared_ptr< Context > CreateContext()
TEST_P(InteropPlaygroundTest, CanCreateContext)
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)
INSTANTIATE_PLAYGROUND_SUITE(InteropPlaygroundTest)
IMPELLER_EXTERN_C void ImpellerParagraphGetWordBoundary(ImpellerParagraph paragraph, size_t code_unit_index, ImpellerRange *out_range)
IMPELLER_EXTERN_C uint64_t ImpellerTextureGetOpenGLHandle(ImpellerTexture texture)
IMPELLER_EXTERN_C ImpellerSurface ImpellerSurfaceCreateWrappedFBONew(ImpellerContext context, uint64_t fbo, ImpellerPixelFormat format, const ImpellerISize *size)
IMPELLER_EXTERN_C ImpellerDisplayList ImpellerDisplayListBuilderCreateDisplayListNew(ImpellerDisplayListBuilder builder)
IMPELLER_EXTERN_C ImpellerParagraphBuilder ImpellerParagraphBuilderNew(ImpellerTypographyContext context)
IMPELLER_EXTERN_C ImpellerDisplayListBuilder ImpellerDisplayListBuilderNew(const ImpellerRect *cull_rect)
IMPELLER_EXTERN_C ImpellerPaint ImpellerPaintNew()
IMPELLER_EXTERN_C ImpellerParagraph ImpellerParagraphBuilderBuildParagraphNew(ImpellerParagraphBuilder paragraph_builder, float width)
IMPELLER_EXTERN_C void ImpellerParagraphBuilderPushStyle(ImpellerParagraphBuilder paragraph_builder, ImpellerParagraphStyle style)
IMPELLER_EXTERN_C ImpellerTypographyContext ImpellerTypographyContextNew()
IMPELLER_EXTERN_C void ImpellerDisplayListBuilderClipRect(ImpellerDisplayListBuilder builder, const ImpellerRect *rect, ImpellerClipOperation op)
constexpr Matrix ToImpellerType(const ImpellerMatrix &m)
IMPELLER_EXTERN_C void ImpellerGlyphInfoGetGraphemeClusterBounds(ImpellerGlyphInfo glyph_info, ImpellerRect *out_bounds)
IMPELLER_EXTERN_C ImpellerTexture ImpellerTextureCreateWithOpenGLTextureHandleNew(ImpellerContext context, const ImpellerTextureDescriptor *descriptor, uint64_t external_gl_handle)
IMPELLER_EXTERN_C void ImpellerDisplayListBuilderTransform(ImpellerDisplayListBuilder builder, const ImpellerMatrix *transform)
IMPELLER_EXTERN_C bool ImpellerTypographyContextRegisterFont(ImpellerTypographyContext context, const ImpellerMapping *contents, void *contents_on_release_user_data, const char *family_name_alias)
IMPELLER_EXTERN_C void ImpellerParagraphStyleSetFontSize(ImpellerParagraphStyle paragraph_style, float size)
IMPELLER_EXTERN_C void ImpellerDisplayListBuilderDrawParagraph(ImpellerDisplayListBuilder builder, ImpellerParagraph paragraph, const ImpellerPoint *point)
IMPELLER_EXTERN_C void ImpellerParagraphStyleSetFontFamily(ImpellerParagraphStyle paragraph_style, const char *family_name)
IMPELLER_EXTERN_C bool ImpellerSurfaceDrawDisplayList(ImpellerSurface surface, ImpellerDisplayList display_list)
IMPELLER_EXTERN_C void ImpellerDisplayListBuilderTranslate(ImpellerDisplayListBuilder builder, float x_translation, float y_translation)
IMPELLER_EXTERN_C void ImpellerParagraphStyleSetForeground(ImpellerParagraphStyle paragraph_style, ImpellerPaint paint)
IMPELLER_EXTERN_C ImpellerParagraphStyle ImpellerParagraphStyleNew()
IMPELLER_EXTERN_C void ImpellerDisplayListBuilderDrawTexture(ImpellerDisplayListBuilder builder, ImpellerTexture texture, const ImpellerPoint *point, ImpellerTextureSampling sampling, ImpellerPaint paint)
IMPELLER_EXTERN_C void ImpellerDisplayListBuilderDrawRect(ImpellerDisplayListBuilder builder, const ImpellerRect *rect, ImpellerPaint paint)
IMPELLER_EXTERN_C void ImpellerPaintSetColor(ImpellerPaint paint, const ImpellerColor *color)
IMPELLER_EXTERN_C void ImpellerParagraphBuilderAddText(ImpellerParagraphBuilder paragraph_builder, const uint8_t *data, uint32_t length)
flutter::DlPathBuilder PathBuilder
void LineTo(PathBuilder *builder, Scalar x, Scalar y)
const uint8_t *IMPELLER_NONNULL data
ImpellerPoint bottom_right
int types
A mask of ImpellerTextDecorationTypes to enable.
ImpellerPixelFormat pixel_format
std::array< uint8_t, 4 > ToR8G8B8A8() const
Convert to R8G8B8A8 representation.
static constexpr Color Fuchsia()
constexpr bool IsIdentity() const