From 407fd3265a7baf3555aef05e5bded80c69fc9a95 Mon Sep 17 00:00:00 2001 From: Chinmay Garde Date: Wed, 23 Oct 2024 11:59:45 -0700 Subject: [PATCH 1/3] [Impeller] libImpeller: A C++ wrapper to the Impeller API. * A single header C++ 17 library that only depends on impeller.h and standard libc++ utilities. * The C++ library proc. table is setup at runtime (via dlsym and related methods). Impeller users don't need to link against libimpeller.so as long as they can discover it at runtime. * RAII wrappers for all opaque objects. * Namespaces are configurable depending on target. * Included in the distributed SDK next to impeller.h. --- impeller/toolkit/interop/BUILD.gn | 10 +- impeller/toolkit/interop/impeller.hpp | 1475 +++++++++++++++++ impeller/toolkit/interop/impeller_cc.cc | 8 + .../toolkit/interop/impeller_unittests.cc | 223 +-- impeller/toolkit/interop/playground_test.cc | 20 +- 5 files changed, 1626 insertions(+), 110 deletions(-) create mode 100644 impeller/toolkit/interop/impeller.hpp create mode 100644 impeller/toolkit/interop/impeller_cc.cc diff --git a/impeller/toolkit/interop/BUILD.gn b/impeller/toolkit/interop/BUILD.gn index 393830c7dadee..500410359dcdb 100644 --- a/impeller/toolkit/interop/BUILD.gn +++ b/impeller/toolkit/interop/BUILD.gn @@ -31,7 +31,9 @@ impeller_component("interop") { "image_filter.h", "impeller.cc", "impeller.h", + "impeller.hpp", "impeller_c.c", + "impeller_cc.cc", "mask_filter.cc", "mask_filter.h", "object.cc", @@ -119,13 +121,17 @@ zip_bundle("sdk") { deps = [ ":library" ] files = [ + { + source = "README.md" + destination = "README.md" + }, { source = "impeller.h" destination = "include/impeller.h" }, { - source = "README.md" - destination = "README.md" + source = "impeller.hpp" + destination = "include/impeller.hpp" }, ] diff --git a/impeller/toolkit/interop/impeller.hpp b/impeller/toolkit/interop/impeller.hpp new file mode 100644 index 0000000000000..f102bcc3ecf16 --- /dev/null +++ b/impeller/toolkit/interop/impeller.hpp @@ -0,0 +1,1475 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_IMPELLER_TOOLKIT_INTEROP_IMPELLER_HPP_ +#define FLUTTER_IMPELLER_TOOLKIT_INTEROP_IMPELLER_HPP_ + +#include +#include +#include +#include +#include + +#include "impeller.h" + +//------------------------------------------------------------------------------ +/// A C++ 17 wrapper to the C Impeller API. This is a convenience wrapper for +/// the C++ API and only depends on standard libc++ utilities in addition to +/// impeller.h +/// + +#ifndef IMPELLER_HPP_NAMESPACE +#define IMPELLER_HPP_NAMESPACE impeller::hpp +#endif // IMPELLER_HPP_NAMESPACE + +// Tripping this assertion means that the C++ wrapper needs to be updated to +// account for impeller.h changes as necessary. +static_assert(IMPELLER_VERSION == IMPELLER_MAKE_VERSION(1, 1, 2, 0), + "C++ bindings must be for the same version as the C API."); + +namespace IMPELLER_HPP_NAMESPACE { + +template +struct Proc { + using FunctionType = T; + + const char* name = nullptr; + + FunctionType* function = nullptr; + + template + auto operator()(Args&&... args) const { + return function(std::forward(args)...); + } +}; + +#define IMPELLER_HPP_EACH_PROC(PROC) \ + PROC(ImpellerColorFilterCreateBlendNew) \ + PROC(ImpellerColorFilterCreateColorMatrixNew) \ + PROC(ImpellerColorFilterRelease) \ + PROC(ImpellerColorFilterRetain) \ + PROC(ImpellerColorSourceCreateConicalGradientNew) \ + PROC(ImpellerColorSourceCreateImageNew) \ + PROC(ImpellerColorSourceCreateLinearGradientNew) \ + PROC(ImpellerColorSourceCreateRadialGradientNew) \ + PROC(ImpellerColorSourceCreateSweepGradientNew) \ + PROC(ImpellerColorSourceRelease) \ + PROC(ImpellerColorSourceRetain) \ + PROC(ImpellerContextCreateOpenGLESNew) \ + PROC(ImpellerContextRelease) \ + PROC(ImpellerContextRetain) \ + PROC(ImpellerDisplayListBuilderClipOval) \ + PROC(ImpellerDisplayListBuilderClipPath) \ + PROC(ImpellerDisplayListBuilderClipRect) \ + PROC(ImpellerDisplayListBuilderClipRoundedRect) \ + PROC(ImpellerDisplayListBuilderCreateDisplayListNew) \ + PROC(ImpellerDisplayListBuilderDrawDashedLine) \ + PROC(ImpellerDisplayListBuilderDrawDisplayList) \ + PROC(ImpellerDisplayListBuilderDrawLine) \ + PROC(ImpellerDisplayListBuilderDrawOval) \ + PROC(ImpellerDisplayListBuilderDrawPaint) \ + PROC(ImpellerDisplayListBuilderDrawParagraph) \ + PROC(ImpellerDisplayListBuilderDrawPath) \ + PROC(ImpellerDisplayListBuilderDrawRect) \ + PROC(ImpellerDisplayListBuilderDrawRoundedRect) \ + PROC(ImpellerDisplayListBuilderDrawRoundedRectDifference) \ + PROC(ImpellerDisplayListBuilderDrawTexture) \ + PROC(ImpellerDisplayListBuilderDrawTextureRect) \ + PROC(ImpellerDisplayListBuilderGetSaveCount) \ + PROC(ImpellerDisplayListBuilderGetTransform) \ + PROC(ImpellerDisplayListBuilderNew) \ + PROC(ImpellerDisplayListBuilderRelease) \ + PROC(ImpellerDisplayListBuilderResetTransform) \ + PROC(ImpellerDisplayListBuilderRestore) \ + PROC(ImpellerDisplayListBuilderRestoreToCount) \ + PROC(ImpellerDisplayListBuilderRetain) \ + PROC(ImpellerDisplayListBuilderRotate) \ + PROC(ImpellerDisplayListBuilderSave) \ + PROC(ImpellerDisplayListBuilderSaveLayer) \ + PROC(ImpellerDisplayListBuilderScale) \ + PROC(ImpellerDisplayListBuilderSetTransform) \ + PROC(ImpellerDisplayListBuilderTransform) \ + PROC(ImpellerDisplayListBuilderTranslate) \ + PROC(ImpellerDisplayListRelease) \ + PROC(ImpellerDisplayListRetain) \ + PROC(ImpellerGetVersion) \ + PROC(ImpellerImageFilterCreateBlurNew) \ + PROC(ImpellerImageFilterCreateComposeNew) \ + PROC(ImpellerImageFilterCreateDilateNew) \ + PROC(ImpellerImageFilterCreateErodeNew) \ + PROC(ImpellerImageFilterCreateMatrixNew) \ + PROC(ImpellerImageFilterRelease) \ + PROC(ImpellerImageFilterRetain) \ + PROC(ImpellerMaskFilterCreateBlurNew) \ + PROC(ImpellerMaskFilterRelease) \ + PROC(ImpellerMaskFilterRetain) \ + PROC(ImpellerPaintNew) \ + PROC(ImpellerPaintRelease) \ + PROC(ImpellerPaintRetain) \ + PROC(ImpellerPaintSetBlendMode) \ + PROC(ImpellerPaintSetColor) \ + PROC(ImpellerPaintSetColorFilter) \ + PROC(ImpellerPaintSetColorSource) \ + PROC(ImpellerPaintSetDrawStyle) \ + PROC(ImpellerPaintSetImageFilter) \ + PROC(ImpellerPaintSetMaskFilter) \ + PROC(ImpellerPaintSetStrokeCap) \ + PROC(ImpellerPaintSetStrokeJoin) \ + PROC(ImpellerPaintSetStrokeMiter) \ + PROC(ImpellerPaintSetStrokeWidth) \ + PROC(ImpellerParagraphBuilderAddText) \ + PROC(ImpellerParagraphBuilderBuildParagraphNew) \ + PROC(ImpellerParagraphBuilderNew) \ + PROC(ImpellerParagraphBuilderPopStyle) \ + PROC(ImpellerParagraphBuilderPushStyle) \ + PROC(ImpellerParagraphBuilderRelease) \ + PROC(ImpellerParagraphBuilderRetain) \ + PROC(ImpellerParagraphGetAlphabeticBaseline) \ + PROC(ImpellerParagraphGetHeight) \ + PROC(ImpellerParagraphGetIdeographicBaseline) \ + PROC(ImpellerParagraphGetLineCount) \ + PROC(ImpellerParagraphGetLongestLineWidth) \ + PROC(ImpellerParagraphGetMaxIntrinsicWidth) \ + PROC(ImpellerParagraphGetMaxWidth) \ + PROC(ImpellerParagraphGetMinIntrinsicWidth) \ + PROC(ImpellerParagraphRelease) \ + PROC(ImpellerParagraphRetain) \ + PROC(ImpellerParagraphStyleNew) \ + PROC(ImpellerParagraphStyleRelease) \ + PROC(ImpellerParagraphStyleRetain) \ + PROC(ImpellerParagraphStyleSetBackground) \ + PROC(ImpellerParagraphStyleSetFontFamily) \ + PROC(ImpellerParagraphStyleSetFontSize) \ + PROC(ImpellerParagraphStyleSetFontStyle) \ + PROC(ImpellerParagraphStyleSetFontWeight) \ + PROC(ImpellerParagraphStyleSetForeground) \ + PROC(ImpellerParagraphStyleSetHeight) \ + PROC(ImpellerParagraphStyleSetLocale) \ + PROC(ImpellerParagraphStyleSetMaxLines) \ + PROC(ImpellerParagraphStyleSetTextAlignment) \ + PROC(ImpellerParagraphStyleSetTextDirection) \ + PROC(ImpellerPathBuilderAddArc) \ + PROC(ImpellerPathBuilderAddOval) \ + PROC(ImpellerPathBuilderAddRect) \ + PROC(ImpellerPathBuilderAddRoundedRect) \ + PROC(ImpellerPathBuilderClose) \ + PROC(ImpellerPathBuilderCopyPathNew) \ + PROC(ImpellerPathBuilderCubicCurveTo) \ + PROC(ImpellerPathBuilderLineTo) \ + PROC(ImpellerPathBuilderMoveTo) \ + PROC(ImpellerPathBuilderNew) \ + PROC(ImpellerPathBuilderQuadraticCurveTo) \ + PROC(ImpellerPathBuilderRelease) \ + PROC(ImpellerPathBuilderRetain) \ + PROC(ImpellerPathBuilderTakePathNew) \ + PROC(ImpellerPathRelease) \ + PROC(ImpellerPathRetain) \ + PROC(ImpellerSurfaceCreateWrappedFBONew) \ + PROC(ImpellerSurfaceDrawDisplayList) \ + PROC(ImpellerSurfaceRelease) \ + PROC(ImpellerSurfaceRetain) \ + PROC(ImpellerTextureCreateWithContentsNew) \ + PROC(ImpellerTextureCreateWithOpenGLTextureHandleNew) \ + PROC(ImpellerTextureGetOpenGLHandle) \ + PROC(ImpellerTextureRelease) \ + PROC(ImpellerTextureRetain) \ + PROC(ImpellerTypographyContextNew) \ + PROC(ImpellerTypographyContextRegisterFont) \ + PROC(ImpellerTypographyContextRelease) \ + PROC(ImpellerTypographyContextRetain) + +struct ProcTable { + bool Initialize(std::function resolver) { +#define IMPELLER_HPP_PROC(proc) \ + { \ + proc.function = \ + reinterpret_cast(resolver(proc.name)); \ + if (proc.function == nullptr) { \ + return false; \ + } \ + } + IMPELLER_HPP_EACH_PROC(IMPELLER_HPP_PROC) +#undef IMPELLER_HPP_PROC + return true; + } + +#define IMPELLER_HPP_PROC(name) Proc name = {#name, nullptr}; + IMPELLER_HPP_EACH_PROC(IMPELLER_HPP_PROC) +#undef IMPELLER_HPP_PROC +}; + +extern ProcTable gGlobalProcTable; + +enum class AdoptTag { + kAdopt, +}; + +template +class Object { + public: + Object() = default; + + Object(T object) { Reset(object); } + + Object(T object, AdoptTag) : object_(object) {} + + ~Object() { Reset(); } + + Object(Object&& other) { std::swap(object_, other.object_); } + + Object(const Object& other) { Reset(other.Get()); } + + Object& operator=(Object&& other) { + std::swap(object_, other.object_); + return *this; + } + + Object& operator=(const Object& other) { + Reset(other.Get()); + return *this; + } + + T Get() const { return object_; } + + explicit operator bool() const { return object_ != nullptr; } + + private: + T object_ = nullptr; + + void Reset(T other = nullptr) { + if (object_ == other) { + return; + } + if (object_) { + Traits::Release(object_); + object_ = nullptr; + } + if (other) { + Traits::Retain(other); + object_ = other; + } + } + + [[nodiscard]] T Leak() { + T result = object_; + object_ = nullptr; + return result; + } +}; + +#define IMPELLER_HPP_DEFINE_TRAITS(object) \ + struct object##Traits { \ + static void Retain(object ctx) { \ + gGlobalProcTable.object##Retain(ctx); \ + } \ + static void Release(object ctx) { \ + gGlobalProcTable.object##Release(ctx); \ + } \ + }; + +IMPELLER_HPP_DEFINE_TRAITS(ImpellerColorFilter); +IMPELLER_HPP_DEFINE_TRAITS(ImpellerColorSource); +IMPELLER_HPP_DEFINE_TRAITS(ImpellerContext); +IMPELLER_HPP_DEFINE_TRAITS(ImpellerDisplayList); +IMPELLER_HPP_DEFINE_TRAITS(ImpellerDisplayListBuilder); +IMPELLER_HPP_DEFINE_TRAITS(ImpellerImageFilter); +IMPELLER_HPP_DEFINE_TRAITS(ImpellerMaskFilter); +IMPELLER_HPP_DEFINE_TRAITS(ImpellerPaint); +IMPELLER_HPP_DEFINE_TRAITS(ImpellerParagraph); +IMPELLER_HPP_DEFINE_TRAITS(ImpellerParagraphBuilder); +IMPELLER_HPP_DEFINE_TRAITS(ImpellerParagraphStyle); +IMPELLER_HPP_DEFINE_TRAITS(ImpellerPath); +IMPELLER_HPP_DEFINE_TRAITS(ImpellerPathBuilder); +IMPELLER_HPP_DEFINE_TRAITS(ImpellerSurface); +IMPELLER_HPP_DEFINE_TRAITS(ImpellerTexture); +IMPELLER_HPP_DEFINE_TRAITS(ImpellerTypographyContext); + +#undef IMPELLER_HPP_DEFINE_TRAITS + +class Mapping final { + public: + Mapping(const uint8_t* mapping, + size_t size, + std::function release_callback) + : mapping_(mapping), + size_(size), + release_callback_(std::move(release_callback)) {} + + const uint8_t* GetMapping() const { return mapping_; } + + size_t GetSize() const { return size_; } + + private: + const uint8_t* mapping_ = nullptr; + size_t size_ = 0u; + std::function release_callback_; +}; + +//------------------------------------------------------------------------------ +/// @see ImpellerContext +/// +class Context final : public Object { + public: + Context(ImpellerContext context, AdoptTag tag) : Object(context, tag) {} + + //---------------------------------------------------------------------------- + /// @see ImpellerContextCreateOpenGLESNew + /// + static Context OpenGLES( + std::function gl_proc_address_resolver) { + struct UserData { + std::function resolver; + }; + UserData user_data; + user_data.resolver = gl_proc_address_resolver; + ImpellerProcAddressCallback callback = [](const char* proc_name, + void* user_data) -> void* { + return reinterpret_cast(user_data)->resolver(proc_name); + }; + return Context( + gGlobalProcTable.ImpellerContextCreateOpenGLESNew(IMPELLER_VERSION, // + callback, // + &user_data // + ), + AdoptTag::kAdopt); + } +}; + +//------------------------------------------------------------------------------ +/// @see ImpellerTexture +/// +class Texture final : public Object { + public: + Texture(ImpellerTexture texture, AdoptTag adopt) : Object(texture, adopt) {} + + //---------------------------------------------------------------------------- + /// @see ImpellerTextureCreateWithContentsNew + /// + static Texture WithContents(const Context& context, + const ImpellerTextureDescriptor& descriptor, + std::unique_ptr mapping = nullptr) { + if (mapping == nullptr) { + mapping = std::make_unique(nullptr, 0u, nullptr); + } + ImpellerMapping c_mapping = {}; + c_mapping.data = mapping->GetMapping(); + c_mapping.length = mapping->GetSize(); + c_mapping.on_release = [](void* user_data) -> void { + delete reinterpret_cast(user_data); + }; + return Texture(gGlobalProcTable.ImpellerTextureCreateWithContentsNew( + context.Get(), // + &descriptor, // + &c_mapping, // + mapping.release() // + ), + AdoptTag::kAdopt); + } + + //---------------------------------------------------------------------------- + /// @see ImpellerTextureCreateWithOpenGLTextureHandleNew + /// + static Texture WithOpenGLTexture(const Context& context, + const ImpellerTextureDescriptor& descriptor, + uint64_t handle) { + return Texture( + gGlobalProcTable.ImpellerTextureCreateWithOpenGLTextureHandleNew( + context.Get(), // + &descriptor, // + handle // + ), + AdoptTag::kAdopt); + } + + uint64_t GetOpenGLHandle() const { + return gGlobalProcTable.ImpellerTextureGetOpenGLHandle(Get()); + } +}; + +//------------------------------------------------------------------------------ +/// @see ImpellerColorFilter +/// +class ColorFilter final + : public Object { + public: + ColorFilter(ImpellerColorFilter filter, AdoptTag tag) : Object(filter, tag) {} + + //---------------------------------------------------------------------------- + /// @see ImpellerColorFilterCreateBlendNew + /// + static ColorFilter Blend(const ImpellerColor& color, ImpellerBlendMode mode) { + return ColorFilter( + gGlobalProcTable.ImpellerColorFilterCreateBlendNew(&color, mode), + AdoptTag::kAdopt); + } + + //---------------------------------------------------------------------------- + /// @see ImpellerColorFilterCreateColorMatrixNew + /// + static ColorFilter Matrix(const ImpellerColorMatrix& color_matrix) { + return ColorFilter( + gGlobalProcTable.ImpellerColorFilterCreateColorMatrixNew(&color_matrix), + AdoptTag::kAdopt); + } +}; + +//------------------------------------------------------------------------------ +/// @see ImpellerColorSource +/// +class ColorSource final + : public Object { + public: + ColorSource(ImpellerColorSource source, AdoptTag tag) : Object(source, tag) {} + + //---------------------------------------------------------------------------- + /// @see ImpellerColorSourceCreateConicalGradientNew + /// + static ColorSource ConicalGradient( + const ImpellerPoint& start_center, + float start_radius, + const ImpellerPoint& end_center, + float end_radius, + uint32_t stop_count, + const ImpellerColor* colors, + const float* stops, + ImpellerTileMode tile_mode, + const ImpellerMatrix* transformation = nullptr) { + return ColorSource( + gGlobalProcTable.ImpellerColorSourceCreateConicalGradientNew( + &start_center, // + start_radius, // + &end_center, // + end_radius, // + stop_count, // + colors, // + stops, // + tile_mode, // + transformation // + ), + AdoptTag::kAdopt); + } + + //---------------------------------------------------------------------------- + /// @see ImpellerColorSourceCreateImageNew + /// + static ColorSource Image(const Texture& image, + ImpellerTileMode horizontal_tile_mode, + ImpellerTileMode vertical_tile_mode, + ImpellerTextureSampling sampling, + const ImpellerMatrix* transformation = nullptr) { + return ColorSource(gGlobalProcTable.ImpellerColorSourceCreateImageNew( + image.Get(), // + horizontal_tile_mode, // + vertical_tile_mode, // + sampling, // + transformation // + ), + AdoptTag::kAdopt); + } + + //---------------------------------------------------------------------------- + /// @see ImpellerColorSourceCreateLinearGradientNew + /// + static ColorSource LinearGradient( + const ImpellerPoint& start_point, + const ImpellerPoint& end_point, + uint32_t stop_count, + const ImpellerColor* colors, + const float* stops, + ImpellerTileMode tile_mode, + const ImpellerMatrix* transformation = nullptr) { + return ColorSource( + gGlobalProcTable.ImpellerColorSourceCreateLinearGradientNew( + &start_point, + &end_point, // + stop_count, // + colors, // + stops, // + tile_mode, // + transformation // + ), + AdoptTag::kAdopt); + } + + //---------------------------------------------------------------------------- + /// @see ImpellerColorSourceCreateRadialGradientNew + /// + static ColorSource RadialGradient( + const ImpellerPoint& center, + float radius, + uint32_t stop_count, + const ImpellerColor* colors, + const float* stops, + ImpellerTileMode tile_mode, + const ImpellerMatrix* transformation = nullptr) { + return ColorSource( + gGlobalProcTable.ImpellerColorSourceCreateRadialGradientNew( + ¢er, // + radius, // + stop_count, // + colors, // + stops, // + tile_mode, // + transformation // + ), + AdoptTag::kAdopt); + } + + //---------------------------------------------------------------------------- + /// @see ImpellerColorSourceCreateSweepGradientNew + /// + static ColorSource SweepGradient( + const ImpellerPoint& center, + float start, + float end, + uint32_t stop_count, + const ImpellerColor* colors, + const float* stops, + ImpellerTileMode tile_mode, + const ImpellerMatrix* transformation = nullptr) { + return ColorSource( + gGlobalProcTable.ImpellerColorSourceCreateSweepGradientNew( + ¢er, // + start, // + end, // + stop_count, // + colors, // + stops, // + tile_mode, // + transformation // + ), + AdoptTag::kAdopt); + } +}; + +//------------------------------------------------------------------------------ +/// @see ImpellerImageFilter +/// +class ImageFilter final + : public Object { + public: + ImageFilter(ImpellerImageFilter filter, AdoptTag tag) : Object(filter, tag) {} + + //---------------------------------------------------------------------------- + /// @see ImpellerImageFilterCreateBlurNew + /// + static ImageFilter Blur(float x_sigma, + float y_sigma, + ImpellerTileMode tile_mode) { + return ImageFilter(gGlobalProcTable.ImpellerImageFilterCreateBlurNew( + x_sigma, y_sigma, tile_mode), + AdoptTag::kAdopt); + } + + //---------------------------------------------------------------------------- + /// @see ImpellerImageFilterCreateComposeNew + /// + static ImageFilter Compose(const ImageFilter& outer, + const ImageFilter& inner) { + return ImageFilter(gGlobalProcTable.ImpellerImageFilterCreateComposeNew( + outer.Get(), inner.Get()), + AdoptTag::kAdopt); + } + + //---------------------------------------------------------------------------- + /// @see ImpellerImageFilterCreateDilateNew + /// + static ImageFilter Dilate(float x_radius, float y_radius) { + return ImageFilter( + gGlobalProcTable.ImpellerImageFilterCreateDilateNew(x_radius, y_radius), + AdoptTag::kAdopt); + } + + //---------------------------------------------------------------------------- + /// @see ImpellerImageFilterCreateErodeNew + /// + static ImageFilter Erode(float x_radius, float y_radius) { + return ImageFilter( + gGlobalProcTable.ImpellerImageFilterCreateErodeNew(x_radius, y_radius), + AdoptTag::kAdopt); + } + + //---------------------------------------------------------------------------- + /// @see ImpellerImageFilterCreateMatrixNew + /// + static ImageFilter Matrix(const ImpellerMatrix& matrix, + ImpellerTextureSampling sampling) { + return ImageFilter( + gGlobalProcTable.ImpellerImageFilterCreateMatrixNew(&matrix, sampling), + AdoptTag::kAdopt); + } +}; + +//------------------------------------------------------------------------------ +/// @see ImpellerMaskFilter +/// +class MaskFilter final + : public Object { + public: + MaskFilter(ImpellerMaskFilter filter, AdoptTag tag) : Object(filter, tag) {} + + //---------------------------------------------------------------------------- + /// @see ImpellerMaskFilterCreateBlurNew + /// + static MaskFilter Blur(ImpellerBlurStyle style, float sigma) { + return MaskFilter( + gGlobalProcTable.ImpellerMaskFilterCreateBlurNew(style, sigma), + AdoptTag::kAdopt); + } +}; + +//------------------------------------------------------------------------------ +/// @see ImpellerParagraph +/// +class Paragraph final + : public Object { + public: + Paragraph(ImpellerParagraph paragraph, AdoptTag tag) + : Object(paragraph, AdoptTag::kAdopt) {} + + //---------------------------------------------------------------------------- + /// @see ImpellerParagraphGetAlphabeticBaseline + /// + float GetAlphabeticBaseline() { + return gGlobalProcTable.ImpellerParagraphGetAlphabeticBaseline(Get()); + } + + //---------------------------------------------------------------------------- + /// @see ImpellerParagraphGetHeight + /// + float GetHeight() { + return gGlobalProcTable.ImpellerParagraphGetHeight(Get()); + } + + //---------------------------------------------------------------------------- + /// @see ImpellerParagraphGetIdeographicBaseline + /// + float GetIdeographicBaseline() { + return gGlobalProcTable.ImpellerParagraphGetIdeographicBaseline(Get()); + } + + //---------------------------------------------------------------------------- + /// @see ImpellerParagraphGetLineCount + /// + uint32_t GetLineCount() { + return gGlobalProcTable.ImpellerParagraphGetLineCount(Get()); + } + + //---------------------------------------------------------------------------- + /// @see ImpellerParagraphGetLongestLineWidth + /// + float GetLongestLineWidth() { + return gGlobalProcTable.ImpellerParagraphGetLongestLineWidth(Get()); + } + + //---------------------------------------------------------------------------- + /// @see ImpellerParagraphGetMaxIntrinsicWidth + /// + float GetMaxIntrinsicWidth() { + return gGlobalProcTable.ImpellerParagraphGetMaxIntrinsicWidth(Get()); + } + + //---------------------------------------------------------------------------- + /// @see ImpellerParagraphGetMaxWidth + /// + float GetMaxWidth() { + return gGlobalProcTable.ImpellerParagraphGetMaxWidth(Get()); + } + + //---------------------------------------------------------------------------- + /// @see ImpellerParagraphGetMinIntrinsicWidth + /// + float GetMinIntrinsicWidth() { + return gGlobalProcTable.ImpellerParagraphGetMinIntrinsicWidth(Get()); + } +}; + +//------------------------------------------------------------------------------ +/// @see ImpellerPaint +/// +class Paint final : public Object { + public: + Paint() : Object(gGlobalProcTable.ImpellerPaintNew(), AdoptTag::kAdopt) {} + + //---------------------------------------------------------------------------- + /// @see ImpellerPaintSetColor + /// + Paint& SetColor(const ImpellerColor& color) { + gGlobalProcTable.ImpellerPaintSetColor(Get(), &color); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerPaintSetBlendMode + /// + Paint& SetBlendMode(ImpellerBlendMode mode) { + gGlobalProcTable.ImpellerPaintSetBlendMode(Get(), mode); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerPaintSetDrawStyle + /// + Paint& SetDrawStyle(ImpellerDrawStyle style) { + gGlobalProcTable.ImpellerPaintSetDrawStyle(Get(), style); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerPaintSetStrokeCap + /// + Paint& SetStrokeCap(ImpellerStrokeCap cap) { + gGlobalProcTable.ImpellerPaintSetStrokeCap(Get(), cap); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerPaintSetStrokeJoin + /// + Paint& SetStrokeJoin(ImpellerStrokeJoin join) { + gGlobalProcTable.ImpellerPaintSetStrokeJoin(Get(), join); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerPaintSetStrokeWidth + /// + Paint& SetStrokeWidth(float width) { + gGlobalProcTable.ImpellerPaintSetStrokeWidth(Get(), width); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerPaintSetStrokeMiter + /// + Paint& SetStrokeMiter(float miter) { + gGlobalProcTable.ImpellerPaintSetStrokeMiter(Get(), miter); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerPaintSetColorFilter + /// + Paint& SetColorFilter(const ColorFilter& filter) { + gGlobalProcTable.ImpellerPaintSetColorFilter(Get(), filter.Get()); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerPaintSetColorSource + /// + Paint& SetColorSource(const ColorSource& source) { + gGlobalProcTable.ImpellerPaintSetColorSource(Get(), source.Get()); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerPaintSetImageFilter + /// + Paint& SetImageFilter(const ImageFilter& filter) { + gGlobalProcTable.ImpellerPaintSetImageFilter(Get(), filter.Get()); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerPaintSetMaskFilter + /// + Paint& SetMaskFilter(const MaskFilter& filter) { + gGlobalProcTable.ImpellerPaintSetMaskFilter(Get(), filter.Get()); + return *this; + } +}; + +//------------------------------------------------------------------------------ +/// @see ImpellerParagraphStyle +/// +class ParagraphStyle final + : public Object { + public: + ParagraphStyle() + : Object(gGlobalProcTable.ImpellerParagraphStyleNew(), AdoptTag::kAdopt) { + } + + //---------------------------------------------------------------------------- + /// @see ImpellerParagraphStyleSetBackground + /// + ParagraphStyle& SetBackground(const Paint& paint) { + gGlobalProcTable.ImpellerParagraphStyleSetBackground(Get(), paint.Get()); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerParagraphStyleSetFontFamily + /// + ParagraphStyle& SetFontFamily(const char* family_name) { + gGlobalProcTable.ImpellerParagraphStyleSetFontFamily(Get(), family_name); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerParagraphStyleSetFontSize + /// + ParagraphStyle& SetFontSize(float size) { + gGlobalProcTable.ImpellerParagraphStyleSetFontSize(Get(), size); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerParagraphStyleSetFontStyle + /// + ParagraphStyle& SetFontStyle(ImpellerFontStyle style) { + gGlobalProcTable.ImpellerParagraphStyleSetFontStyle(Get(), style); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerParagraphStyleSetFontWeight + /// + ParagraphStyle& SetFontWeight(ImpellerFontWeight weight) { + gGlobalProcTable.ImpellerParagraphStyleSetFontWeight(Get(), weight); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerParagraphStyleSetForeground + /// + ParagraphStyle& SetForeground(const Paint& paint) { + gGlobalProcTable.ImpellerParagraphStyleSetForeground(Get(), paint.Get()); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerParagraphStyleSetHeight + /// + ParagraphStyle& SetHeight(float height) { + gGlobalProcTable.ImpellerParagraphStyleSetHeight(Get(), height); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerParagraphStyleSetLocale + /// + ParagraphStyle& SetLocale(const char* locale) { + gGlobalProcTable.ImpellerParagraphStyleSetLocale(Get(), locale); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerParagraphStyleSetMaxLines + /// + ParagraphStyle& SetMaxLines(uint32_t max_lines) { + gGlobalProcTable.ImpellerParagraphStyleSetMaxLines(Get(), max_lines); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerParagraphStyleSetTextAlignment + /// + ParagraphStyle& SetTextAlignment(ImpellerTextAlignment align) { + gGlobalProcTable.ImpellerParagraphStyleSetTextAlignment(Get(), align); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerParagraphStyleSetTextDirection + /// + ParagraphStyle& SetTextDirection(ImpellerTextDirection direction) { + gGlobalProcTable.ImpellerParagraphStyleSetTextDirection(Get(), direction); + return *this; + } +}; + +//------------------------------------------------------------------------------ +/// @see ImpellerTypographyContext +/// +class TypographyContext final : public Object { + public: + TypographyContext() + : Object(gGlobalProcTable.ImpellerTypographyContextNew(), + AdoptTag::kAdopt) {} + + //---------------------------------------------------------------------------- + /// @see ImpellerTypographyContextRegisterFont + /// + bool RegisterFont(std::unique_ptr mapping, + const char* optional_family_name_alias = nullptr) { + if (!mapping) { + return false; + } + ImpellerMapping c_mapping = {}; + c_mapping.data = mapping->GetMapping(); + c_mapping.length = mapping->GetSize(); + c_mapping.on_release = [](void* user_data) { + delete reinterpret_cast(user_data); + }; + return gGlobalProcTable.ImpellerTypographyContextRegisterFont( + Get(), // + &c_mapping, // + mapping.release(), // + optional_family_name_alias // + ); + } +}; + +//------------------------------------------------------------------------------ +/// @see ImpellerParagraphBuilder +/// +class ParagraphBuilder final + : public Object { + public: + ParagraphBuilder(const TypographyContext& context) + : Object(gGlobalProcTable.ImpellerParagraphBuilderNew(context.Get()), + AdoptTag::kAdopt) {} + + //---------------------------------------------------------------------------- + /// @see ImpellerParagraphBuilderBuildParagraphNew + /// + Paragraph Build(float width) { + return Paragraph( + gGlobalProcTable.ImpellerParagraphBuilderBuildParagraphNew(Get(), // + width // + ), + AdoptTag::kAdopt); + } + + //---------------------------------------------------------------------------- + /// @see ImpellerParagraphBuilderPushStyle + /// + ParagraphBuilder& PushStyle(const ParagraphStyle& style) { + gGlobalProcTable.ImpellerParagraphBuilderPushStyle(Get(), style.Get()); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerParagraphBuilderPopStyle + /// + ParagraphBuilder& PopStyle() { + gGlobalProcTable.ImpellerParagraphBuilderPopStyle(Get()); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerParagraphBuilderAddText + /// + ParagraphBuilder& AddText(const uint8_t* utf8_data, uint32_t length) { + gGlobalProcTable.ImpellerParagraphBuilderAddText(Get(), utf8_data, length); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerParagraphBuilderAddText + /// + ParagraphBuilder& AddText(const std::string& string) { + return AddText(reinterpret_cast(string.data()), + string.size()); + } + + //---------------------------------------------------------------------------- + /// @see ImpellerParagraphBuilderAddText + /// + ParagraphBuilder& AddText(const std::string_view& string) { + return AddText(reinterpret_cast(string.data()), + string.size()); + } +}; + +//------------------------------------------------------------------------------ +/// @see ImpellerPath +/// +class Path final : public Object { + public: + Path(ImpellerPath path, AdoptTag tag) : Object(path, tag) {} +}; + +//------------------------------------------------------------------------------ +/// @see ImpellerPathBuilder +/// +class PathBuilder final + : public Object { + public: + PathBuilder() + : Object(gGlobalProcTable.ImpellerPathBuilderNew(), AdoptTag::kAdopt) {} + + //---------------------------------------------------------------------------- + /// @see ImpellerPathBuilderCopyPathNew + /// + Path BuildCopy(ImpellerFillType fill = + ImpellerFillType::kImpellerFillTypeNonZero) const { + return Path(gGlobalProcTable.ImpellerPathBuilderCopyPathNew(Get(), fill), + AdoptTag::kAdopt); + } + + //---------------------------------------------------------------------------- + /// @see ImpellerPathBuilderTakePathNew + /// + Path Build( + ImpellerFillType fill = ImpellerFillType::kImpellerFillTypeNonZero) { + return Path(gGlobalProcTable.ImpellerPathBuilderTakePathNew(Get(), fill), + AdoptTag::kAdopt); + } + + //---------------------------------------------------------------------------- + /// @see ImpellerPathBuilderAddArc + /// + PathBuilder& AddArc(const ImpellerRect& oval_bounds, + float start_angle_degrees, + float end_angle_degrees) { + gGlobalProcTable.ImpellerPathBuilderAddArc(Get(), // + &oval_bounds, // + start_angle_degrees, // + end_angle_degrees // + ); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerPathBuilderAddOval + /// + PathBuilder& AddOval(const ImpellerRect& oval_bounds) { + gGlobalProcTable.ImpellerPathBuilderAddOval(Get(), &oval_bounds); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerPathBuilderAddRect + /// + PathBuilder& AddRect(const ImpellerRect& rect) { + gGlobalProcTable.ImpellerPathBuilderAddRect(Get(), &rect); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerPathBuilderAddRoundedRect + /// + PathBuilder& AddRoundedRect(const ImpellerRect& rect, + const ImpellerRoundingRadii& rounding_radii) { + gGlobalProcTable.ImpellerPathBuilderAddRoundedRect(Get(), &rect, + &rounding_radii); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerPathBuilderClose + /// + PathBuilder& Close() { + gGlobalProcTable.ImpellerPathBuilderClose(Get()); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerPathBuilderCubicCurveTo + /// + PathBuilder& CubicCurveTo(const ImpellerPoint& control_point_1, + const ImpellerPoint& control_point_2, + const ImpellerPoint& end_point) { + gGlobalProcTable.ImpellerPathBuilderCubicCurveTo( + Get(), &control_point_1, &control_point_2, &end_point); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerPathBuilderLineTo + /// + PathBuilder& LineTo(const ImpellerPoint& location) { + gGlobalProcTable.ImpellerPathBuilderLineTo(Get(), &location); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerPathBuilderMoveTo + /// + PathBuilder& MoveTo(const ImpellerPoint& location) { + gGlobalProcTable.ImpellerPathBuilderMoveTo(Get(), &location); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerPathBuilderQuadraticCurveTo + /// + PathBuilder& QuadraticCurveTo(const ImpellerPoint& control_point, + const ImpellerPoint& end_point) { + gGlobalProcTable.ImpellerPathBuilderQuadraticCurveTo(Get(), &control_point, + &end_point); + return *this; + } +}; + +//------------------------------------------------------------------------------ +/// @see ImpellerDisplayList +/// +class DisplayList final + : public Object { + public: + DisplayList(ImpellerDisplayList display_list, AdoptTag tag) + : Object(display_list, tag) {} +}; + +//------------------------------------------------------------------------------ +/// @see ImpellerSurface +/// +class Surface final : public Object { + public: + Surface(ImpellerSurface surface) : Object(surface) {} + + Surface(ImpellerSurface surface, AdoptTag tag) : Object(surface, tag) {} + + //---------------------------------------------------------------------------- + /// @see ImpellerSurfaceCreateWrappedFBONew + /// + static Surface WrapFBO(const Context& context, + uint64_t fbo, + ImpellerPixelFormat format, + const ImpellerISize& size) { + return Surface( + gGlobalProcTable.ImpellerSurfaceCreateWrappedFBONew(context.Get(), // + fbo, // + format, // + &size // + ), + AdoptTag::kAdopt); + } + + //---------------------------------------------------------------------------- + /// @see ImpellerSurfaceDrawDisplayList + /// + bool Draw(const DisplayList& display_list) { + return gGlobalProcTable.ImpellerSurfaceDrawDisplayList(Get(), + display_list.Get()); + } +}; + +//------------------------------------------------------------------------------ +/// @see ImpellerDisplayListBuilder +/// +class DisplayListBuilder final + : public Object { + public: + //---------------------------------------------------------------------------- + /// @see ImpellerDisplayListBuilderNew + /// + DisplayListBuilder(const ImpellerRect* cull_rect = nullptr) + : Object(gGlobalProcTable.ImpellerDisplayListBuilderNew(cull_rect), + AdoptTag::kAdopt) {} + + //---------------------------------------------------------------------------- + /// @see ImpellerDisplayListBuilderCreateDisplayListNew + /// + DisplayList Build() { + return DisplayList( + gGlobalProcTable.ImpellerDisplayListBuilderCreateDisplayListNew(Get()), + AdoptTag::kAdopt); + } + + //---------------------------------------------------------------------------- + /// @see ImpellerDisplayListBuilderClipOval + /// + DisplayListBuilder& ClipOval(const ImpellerRect& oval_bounds, + ImpellerClipOperation op) { + gGlobalProcTable.ImpellerDisplayListBuilderClipOval(Get(), // + &oval_bounds, // + op); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerDisplayListBuilderClipPath + /// + DisplayListBuilder& ClipPath(const Path& path, ImpellerClipOperation op) { + gGlobalProcTable.ImpellerDisplayListBuilderClipPath(Get(), // + path.Get(), // + op); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerDisplayListBuilderClipRect + /// + DisplayListBuilder& ClipRect(const ImpellerRect& rect, + ImpellerClipOperation op) { + gGlobalProcTable.ImpellerDisplayListBuilderClipRect(Get(), // + &rect, // + op); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerDisplayListBuilderClipRoundedRect + /// + DisplayListBuilder& ClipRoundedRect(const ImpellerRect& rect, + const ImpellerRoundingRadii& radii, + ImpellerClipOperation op) { + gGlobalProcTable.ImpellerDisplayListBuilderClipRoundedRect(Get(), // + &rect, // + &radii, // + op // + ); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerDisplayListBuilderDrawDashedLine + /// + DisplayListBuilder& DrawDashedLine(const ImpellerPoint& from, + const ImpellerPoint& to, + float on_length, + float off_length, + const Paint& paint) { + gGlobalProcTable.ImpellerDisplayListBuilderDrawDashedLine(Get(), // + &from, // + &to, // + on_length, // + off_length, // + paint.Get()); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerDisplayListBuilderDrawDisplayList + /// + DisplayListBuilder& DrawDisplayList(const DisplayList& display_list, + float opacity = 1.0f) { + gGlobalProcTable.ImpellerDisplayListBuilderDrawDisplayList( + Get(), display_list.Get(), opacity); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerDisplayListBuilderDrawLine + /// + DisplayListBuilder& DrawLine(const ImpellerPoint& from, + const ImpellerPoint& to, + const Paint& paint) { + gGlobalProcTable.ImpellerDisplayListBuilderDrawLine(Get(), // + &from, // + &to, // + paint.Get() // + ); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerDisplayListBuilderDrawOval + /// + DisplayListBuilder& DrawOval(const ImpellerRect& oval_bounds, + const Paint& paint) { + gGlobalProcTable.ImpellerDisplayListBuilderDrawOval(Get(), // + &oval_bounds, // + paint.Get() // + ); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerDisplayListBuilderDrawPaint + /// + DisplayListBuilder& DrawPaint(const Paint& paint) { + gGlobalProcTable.ImpellerDisplayListBuilderDrawPaint(Get(), paint.Get()); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerDisplayListBuilderDrawParagraph + /// + DisplayListBuilder& DrawParagraph(const Paragraph& paragraph, + const ImpellerPoint& point) { + gGlobalProcTable.ImpellerDisplayListBuilderDrawParagraph( + Get(), paragraph.Get(), &point); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerDisplayListBuilderDrawPath + /// + DisplayListBuilder& DrawPath(const Path& path, const Paint& paint) { + gGlobalProcTable.ImpellerDisplayListBuilderDrawPath(Get(), path.Get(), + paint.Get()); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerDisplayListBuilderDrawRect + /// + DisplayListBuilder& DrawRect(const ImpellerRect& rect, const Paint& paint) { + gGlobalProcTable.ImpellerDisplayListBuilderDrawRect(Get(), &rect, + paint.Get()); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerDisplayListBuilderDrawRoundedRect + /// + DisplayListBuilder& DrawRoundedRect(const ImpellerRect& rect, + const ImpellerRoundingRadii& radii, + const Paint& paint) { + gGlobalProcTable.ImpellerDisplayListBuilderDrawRoundedRect(Get(), // + &rect, // + &radii, // + paint.Get()); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerDisplayListBuilderDrawRoundedRectDifference + /// + DisplayListBuilder& DrawRoundedRectDifference( + const ImpellerRect& outer_rect, + const ImpellerRoundingRadii& outer_radii, + const ImpellerRect& inner_rect, + const ImpellerRoundingRadii& inner_radii, + const Paint& paint) { + gGlobalProcTable.ImpellerDisplayListBuilderDrawRoundedRectDifference( + Get(), // + &outer_rect, // + &outer_radii, // + &inner_rect, // + &inner_radii, // + paint.Get()); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerDisplayListBuilderDrawTexture + /// + DisplayListBuilder& DrawTexture(const Texture& texture, + const ImpellerPoint& point, + ImpellerTextureSampling sampling, + const Paint& paint) { + gGlobalProcTable.ImpellerDisplayListBuilderDrawTexture( + Get(), texture.Get(), &point, sampling, paint.Get()); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerDisplayListBuilderDrawTextureRect + /// + DisplayListBuilder& DrawTextureRect(const Texture& texture, + const ImpellerRect& src_rect, + const ImpellerRect& dst_rect, + ImpellerTextureSampling sampling, + const Paint& paint) { + gGlobalProcTable.ImpellerDisplayListBuilderDrawTextureRect( + Get(), texture.Get(), // + &src_rect, // + &dst_rect, // + sampling, // + paint.Get()); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerDisplayListBuilderGetSaveCount + /// + uint32_t GetSaveCount() { + return gGlobalProcTable.ImpellerDisplayListBuilderGetSaveCount(Get()); + } + + //---------------------------------------------------------------------------- + /// @see ImpellerDisplayListBuilderGetTransform + /// + ImpellerMatrix GetTransform() { + ImpellerMatrix result; + gGlobalProcTable.ImpellerDisplayListBuilderGetTransform(Get(), &result); + return result; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerDisplayListBuilderResetTransform + /// + DisplayListBuilder& ResetTransform() { + gGlobalProcTable.ImpellerDisplayListBuilderResetTransform(Get()); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerDisplayListBuilderRestore + /// + DisplayListBuilder& Restore() { + gGlobalProcTable.ImpellerDisplayListBuilderRestore(Get()); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerDisplayListBuilderRestoreToCount + /// + DisplayListBuilder& RestoreToCount(uint32_t count) { + gGlobalProcTable.ImpellerDisplayListBuilderRestoreToCount(Get(), // + count); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerDisplayListBuilderRotate + /// + DisplayListBuilder& Rotate(float angle_degrees) { + gGlobalProcTable.ImpellerDisplayListBuilderRotate(Get(), // + angle_degrees); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerDisplayListBuilderSave + /// + DisplayListBuilder& Save() { + gGlobalProcTable.ImpellerDisplayListBuilderSave(Get()); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerDisplayListBuilderSaveLayer + /// + DisplayListBuilder& SaveLayer(const ImpellerRect& bounds, + const Paint* paint = nullptr, + const ImageFilter* backdrop = nullptr) { + gGlobalProcTable.ImpellerDisplayListBuilderSaveLayer( + Get(), // + &bounds, // + paint ? paint->Get() : NULL, // + backdrop ? backdrop->Get() : NULL // + ); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerDisplayListBuilderScale + /// + DisplayListBuilder& Scale(float x_scale, float y_scale) { + gGlobalProcTable.ImpellerDisplayListBuilderScale(Get(), // + x_scale, // + y_scale); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerDisplayListBuilderSetTransform + /// + DisplayListBuilder& SetTransform(const ImpellerMatrix& transform) { + gGlobalProcTable.ImpellerDisplayListBuilderSetTransform(Get(), &transform); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerDisplayListBuilderTransform + /// + DisplayListBuilder& Transform(const ImpellerMatrix& transform) { + gGlobalProcTable.ImpellerDisplayListBuilderTransform(Get(), &transform); + return *this; + } + + //---------------------------------------------------------------------------- + /// @see ImpellerDisplayListBuilderTranslate + /// + DisplayListBuilder& Translate(float x_translation, float y_translation) { + gGlobalProcTable.ImpellerDisplayListBuilderTranslate(Get(), // + x_translation, // + y_translation // + ); + return *this; + } +}; + +} // namespace IMPELLER_HPP_NAMESPACE + +#endif // FLUTTER_IMPELLER_TOOLKIT_INTEROP_IMPELLER_HPP_ diff --git a/impeller/toolkit/interop/impeller_cc.cc b/impeller/toolkit/interop/impeller_cc.cc new file mode 100644 index 0000000000000..69323c90fd7fe --- /dev/null +++ b/impeller/toolkit/interop/impeller_cc.cc @@ -0,0 +1,8 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "impeller.hpp" + +// This C++ file is only present to make sure the C++ header can be imported +// cleanly in a C++ translation unit. diff --git a/impeller/toolkit/interop/impeller_unittests.cc b/impeller/toolkit/interop/impeller_unittests.cc index e2c90dd35f3f4..19b64cab4fd39 100644 --- a/impeller/toolkit/interop/impeller_unittests.cc +++ b/impeller/toolkit/interop/impeller_unittests.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "flutter/fml/native_library.h" #include "flutter/testing/testing.h" #include "impeller/base/allocation.h" #include "impeller/renderer/backend/gles/context_gles.h" @@ -10,6 +11,7 @@ #include "impeller/toolkit/interop/dl_builder.h" #include "impeller/toolkit/interop/formats.h" #include "impeller/toolkit/interop/impeller.h" +#include "impeller/toolkit/interop/impeller.hpp" #include "impeller/toolkit/interop/paint.h" #include "impeller/toolkit/interop/paragraph.h" #include "impeller/toolkit/interop/paragraph_builder.h" @@ -30,18 +32,14 @@ TEST_P(InteropPlaygroundTest, CanCreateContext) { } TEST_P(InteropPlaygroundTest, CanCreateDisplayListBuilder) { - auto builder = ImpellerDisplayListBuilderNew(nullptr); - ASSERT_NE(builder, nullptr); - ImpellerMatrix matrix; - ImpellerDisplayListBuilderGetTransform(builder, &matrix); - ASSERT_TRUE(ToImpellerType(matrix).IsIdentity()); - ASSERT_EQ(ImpellerDisplayListBuilderGetSaveCount(builder), 1u); - ImpellerDisplayListBuilderSave(builder); - ASSERT_EQ(ImpellerDisplayListBuilderGetSaveCount(builder), 2u); - // ImpellerDisplayListBuilderSave(nullptr); <-- Compiler error. - ImpellerDisplayListBuilderRestore(builder); - ASSERT_EQ(ImpellerDisplayListBuilderGetSaveCount(builder), 1u); - ImpellerDisplayListBuilderRelease(builder); + hpp::DisplayListBuilder builder; + ASSERT_TRUE(builder); + ASSERT_TRUE(ToImpellerType(builder.GetTransform()).IsIdentity()); + ASSERT_EQ(builder.GetSaveCount(), 1u); + builder.Save(); + ASSERT_EQ(builder.GetSaveCount(), 2u); + builder.Restore(); + ASSERT_EQ(builder.GetSaveCount(), 1u); } TEST_P(InteropPlaygroundTest, CanCreateSurface) { @@ -232,63 +230,88 @@ TEST_P(InteropPlaygroundTest, ClearsOpenGLStancilStateAfterTransition) { TEST_P(InteropPlaygroundTest, CanCreateParagraphs) { // Create a typography context. - auto type_context = Adopt(ImpellerTypographyContextNew()); + hpp::TypographyContext type_context; ASSERT_TRUE(type_context); // Create a builder. - auto builder = - Adopt(ImpellerParagraphBuilderNew(type_context.GetC())); + hpp::ParagraphBuilder builder(type_context); ASSERT_TRUE(builder); // Create a paragraph style with the font size and foreground and background // colors. - auto style = Adopt(ImpellerParagraphStyleNew()); + hpp::ParagraphStyle style; ASSERT_TRUE(style); - ImpellerParagraphStyleSetFontSize(style.GetC(), 150.0f); - ImpellerParagraphStyleSetHeight(style.GetC(), 2.0f); + style.SetFontSize(150.0f); + style.SetHeight(2.0f); { - auto paint = Adopt(ImpellerPaintNew()); + hpp::Paint paint; ASSERT_TRUE(paint); - ImpellerColor color = {1.0, 0.0, 0.0, 1.0}; - ImpellerPaintSetColor(paint.GetC(), &color); - ImpellerParagraphStyleSetForeground(style.GetC(), paint.GetC()); + paint.SetColor({1.0, 0.0, 0.0, 1.0}); + style.SetForeground(paint); } { - auto paint = Adopt(ImpellerPaintNew()); - ASSERT_TRUE(paint); - ImpellerColor color = {1.0, 1.0, 1.0, 1.0}; - ImpellerPaintSetColor(paint.GetC(), &color); - ImpellerParagraphStyleSetBackground(style.GetC(), paint.GetC()); + hpp::Paint paint; + paint.SetColor({1.0, 1.0, 1.0, 1.0}); + style.SetBackground(paint); } // Push the style onto the style stack. - ImpellerParagraphBuilderPushStyle(builder.GetC(), style.GetC()); + builder.PushStyle(style); std::string text = "the ⚡️ quick ⚡️ brown 🦊 fox jumps over the lazy dog 🐶."; // Add the paragraph text data. - ImpellerParagraphBuilderAddText(builder.GetC(), - reinterpret_cast(text.data()), - text.size()); + builder.AddText(text); // Layout and build the paragraph. - auto paragraph = Adopt( - ImpellerParagraphBuilderBuildParagraphNew(builder.GetC(), 1200.0f)); + auto paragraph = builder.Build(1200.0f); ASSERT_TRUE(paragraph); // Create a display list with just the paragraph drawn into it. - auto dl_builder = - Adopt(ImpellerDisplayListBuilderNew(nullptr)); - ImpellerPoint point = {20, 20}; - ImpellerDisplayListBuilderDrawParagraph(dl_builder.GetC(), paragraph.GetC(), - &point); - auto dl = Adopt( - ImpellerDisplayListBuilderCreateDisplayListNew(dl_builder.GetC())); + hpp::DisplayListBuilder dl_builder; + dl_builder.DrawParagraph(paragraph, {20, 20}); + + // Build the display list. + auto dl = dl_builder.Build(); ASSERT_TRUE( OpenPlaygroundHere([&](const auto& context, const auto& surface) -> bool { - ImpellerSurfaceDrawDisplayList(surface.GetC(), dl.GetC()); + hpp::Surface window(surface.GetC()); + window.Draw(dl); + return true; + })); +} + +TEST_P(InteropPlaygroundTest, CanCreateShapes) { + hpp::DisplayListBuilder builder; + + hpp::Paint red_paint; + red_paint.SetColor({1.0, 0.0, 0.0, 1.0}); + red_paint.SetStrokeWidth(10.0); + + builder.Translate(10, 10); + builder.DrawRect({0, 0, 100, 100}, red_paint); + builder.Translate(100, 100); + builder.DrawOval({0, 0, 100, 100}, red_paint); + builder.Translate(100, 100); + builder.DrawLine({0, 0}, {100, 100}, red_paint); + + builder.Translate(100, 100); + ImpellerRoundingRadii radii = {}; + radii.top_left = {10, 10}; + radii.bottom_right = {10, 10}; + builder.DrawRoundedRect({0, 0, 100, 100}, radii, red_paint); + + builder.Translate(100, 100); + builder.DrawPath(hpp::PathBuilder{}.AddOval({0, 0, 100, 100}).Build(), + red_paint); + + auto dl = builder.Build(); + ASSERT_TRUE( + OpenPlaygroundHere([&](const auto& context, const auto& surface) -> bool { + hpp::Surface window(surface.GetC()); + window.Draw(dl); return true; })); } @@ -367,97 +390,83 @@ TEST_P(InteropPlaygroundTest, CanCreateParagraphsWithCustomFont) { })); } // namespace impeller::interop::testing -static void DrawTextFrame(ImpellerTypographyContext tc, - ImpellerDisplayListBuilder builder, - ImpellerParagraphStyle p_style, - ImpellerPaint bg, +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) { const char text[] = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."; - ImpellerPaint fg = ImpellerPaintNew(); + hpp::Paint fg; // Draw a box. - ImpellerPaintSetColor(fg, &color); - ImpellerPaintSetDrawStyle(fg, kImpellerDrawStyleStroke); + fg.SetColor(color); + fg.SetDrawStyle(kImpellerDrawStyleStroke); ImpellerRect box_rect = {10 + x_offset, 10, 200, 200}; - ImpellerDisplayListBuilderDrawRect(builder, &box_rect, fg); + builder.DrawRect(box_rect, fg); // Draw text. - ImpellerPaintSetDrawStyle(fg, kImpellerDrawStyleFill); - ImpellerParagraphStyleSetForeground(p_style, fg); - ImpellerParagraphStyleSetBackground(p_style, bg); - ImpellerParagraphStyleSetTextAlignment(p_style, align); - ImpellerParagraphBuilder p_builder = ImpellerParagraphBuilderNew(tc); - ImpellerParagraphBuilderPushStyle(p_builder, p_style); - ImpellerParagraphBuilderAddText(p_builder, (const uint8_t*)text, - sizeof(text)); - ImpellerParagraph left_p = ImpellerParagraphBuilderBuildParagraphNew( - p_builder, box_rect.width - 20.0); + fg.SetDrawStyle(kImpellerDrawStyleFill); + p_style.SetForeground(fg); + p_style.SetBackground(bg); + p_style.SetTextAlignment(align); + + hpp::ParagraphBuilder p_builder(tc); + p_builder.PushStyle(p_style); + p_builder.AddText((const uint8_t*)text, sizeof(text)); + + auto left_p = p_builder.Build(box_rect.width - 20.0); ImpellerPoint pt = {20.0f + x_offset, 20.0f}; - float w = ImpellerParagraphGetMaxWidth(left_p); - float h = ImpellerParagraphGetHeight(left_p); - ImpellerDisplayListBuilderDrawParagraph(builder, left_p, &pt); - ImpellerPaintSetDrawStyle(fg, kImpellerDrawStyleStroke); + float w = left_p.GetMaxWidth(); + float h = left_p.GetHeight(); + builder.DrawParagraph(left_p, pt); + fg.SetDrawStyle(kImpellerDrawStyleStroke); // Draw an inner box around the paragraph layout. ImpellerRect inner_box_rect = {pt.x, pt.y, w, h}; - ImpellerDisplayListBuilderDrawRect(builder, &inner_box_rect, fg); - - ImpellerParagraphRelease(left_p); - ImpellerParagraphBuilderRelease(p_builder); - ImpellerPaintRelease(fg); + builder.DrawRect(inner_box_rect, fg); } TEST_P(InteropPlaygroundTest, CanRenderTextAlignments) { - ImpellerTypographyContext tc = ImpellerTypographyContextNew(); + hpp::TypographyContext tc; - ImpellerDisplayList dl = NULL; + hpp::DisplayListBuilder builder; + hpp::Paint bg; + hpp::ParagraphStyle p_style; + p_style.SetFontFamily("Roboto"); + p_style.SetFontSize(24.0); + p_style.SetFontWeight(kImpellerFontWeight400); - { - ImpellerDisplayListBuilder builder = ImpellerDisplayListBuilderNew(NULL); - ImpellerPaint bg = ImpellerPaintNew(); - ImpellerParagraphStyle p_style = ImpellerParagraphStyleNew(); - ImpellerParagraphStyleSetFontFamily(p_style, "Roboto"); - ImpellerParagraphStyleSetFontSize(p_style, 24.0); - ImpellerParagraphStyleSetFontWeight(p_style, kImpellerFontWeight400); - - // Clear the background to a white color. - ImpellerColor clear_color = {1.0, 1.0, 1.0, 1.0}; - ImpellerPaintSetColor(bg, &clear_color); - ImpellerDisplayListBuilderDrawPaint(builder, bg); - - // Draw red, left-aligned text. - ImpellerColor red = {1.0, 0.0, 0.0, 1.0}; - DrawTextFrame(tc, builder, p_style, bg, red, kImpellerTextAlignmentLeft, - 0.0); - - // Draw green, centered text. - ImpellerColor green = {0.0, 1.0, 0.0, 1.0}; - DrawTextFrame(tc, builder, p_style, bg, green, kImpellerTextAlignmentCenter, - 220.0); - - // Draw blue, right-aligned text. - ImpellerColor blue = {0.0, 0.0, 1.0, 1.0}; - DrawTextFrame(tc, builder, p_style, bg, blue, kImpellerTextAlignmentRight, - 440.0); - - dl = ImpellerDisplayListBuilderCreateDisplayListNew(builder); - - ImpellerPaintRelease(bg); - ImpellerDisplayListBuilderRelease(builder); - } + // Clear the background to a white color. + ImpellerColor clear_color = {1.0, 1.0, 1.0, 1.0}; + bg.SetColor(clear_color); + builder.DrawPaint(bg); + + // Draw red, left-aligned text. + ImpellerColor red = {1.0, 0.0, 0.0, 1.0}; + DrawTextFrame(tc, builder, p_style, bg, red, kImpellerTextAlignmentLeft, 0.0); + + // Draw green, centered text. + ImpellerColor green = {0.0, 1.0, 0.0, 1.0}; + DrawTextFrame(tc, builder, p_style, bg, green, kImpellerTextAlignmentCenter, + 220.0); + + // Draw blue, right-aligned text. + ImpellerColor blue = {0.0, 0.0, 1.0, 1.0}; + DrawTextFrame(tc, builder, p_style, bg, blue, kImpellerTextAlignmentRight, + 440.0); + + auto dl = builder.Build(); ASSERT_TRUE( OpenPlaygroundHere([&](const auto& context, const auto& surface) -> bool { - ImpellerSurfaceDrawDisplayList(surface.GetC(), dl); + hpp::Surface window(surface.GetC()); + window.Draw(dl); return true; })); - - ImpellerDisplayListRelease(dl); - ImpellerTypographyContextRelease(tc); } } // namespace impeller::interop::testing diff --git a/impeller/toolkit/interop/playground_test.cc b/impeller/toolkit/interop/playground_test.cc index f23a9276878b6..6c22fec44b79e 100644 --- a/impeller/toolkit/interop/playground_test.cc +++ b/impeller/toolkit/interop/playground_test.cc @@ -4,9 +4,27 @@ #include "impeller/toolkit/interop/playground_test.h" +#include + +#include "flutter/fml/mapping.h" +#include "impeller/toolkit/interop/impeller.hpp" + +namespace IMPELLER_HPP_NAMESPACE { +ProcTable gGlobalProcTable; +} + namespace impeller::interop::testing { -PlaygroundTest::PlaygroundTest() = default; +PlaygroundTest::PlaygroundTest() { + static std::once_flag sOnceFlag; + std::call_once(sOnceFlag, []() { + static auto library = fml::NativeLibrary::CreateForCurrentProcess(); + hpp::gGlobalProcTable.Initialize([&](auto name) { + return const_cast( + reinterpret_cast(library->ResolveSymbol(name))); + }); + }); +} PlaygroundTest::~PlaygroundTest() = default; From cd6aa176c69d17cdd23addea0b7d145b6720fd2d Mon Sep 17 00:00:00 2001 From: Chinmay Garde Date: Mon, 18 Nov 2024 14:00:21 -0800 Subject: [PATCH 2/3] Bots --- ci/licenses_golden/licenses_flutter | 4 ++++ impeller/toolkit/interop/impeller.hpp | 13 +++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index c8b2aeae37e3e..5547fbb3408ed 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -43486,7 +43486,9 @@ ORIGIN: ../../../flutter/impeller/toolkit/interop/image_filter.cc + ../../../flu ORIGIN: ../../../flutter/impeller/toolkit/interop/image_filter.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/toolkit/interop/impeller.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/toolkit/interop/impeller.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/interop/impeller.hpp + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/toolkit/interop/impeller_c.c + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/toolkit/interop/impeller_cc.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/toolkit/interop/mask_filter.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/toolkit/interop/mask_filter.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/toolkit/interop/object.cc + ../../../flutter/LICENSE @@ -46358,7 +46360,9 @@ FILE: ../../../flutter/impeller/toolkit/interop/image_filter.cc FILE: ../../../flutter/impeller/toolkit/interop/image_filter.h FILE: ../../../flutter/impeller/toolkit/interop/impeller.cc FILE: ../../../flutter/impeller/toolkit/interop/impeller.h +FILE: ../../../flutter/impeller/toolkit/interop/impeller.hpp FILE: ../../../flutter/impeller/toolkit/interop/impeller_c.c +FILE: ../../../flutter/impeller/toolkit/interop/impeller_cc.cc FILE: ../../../flutter/impeller/toolkit/interop/mask_filter.cc FILE: ../../../flutter/impeller/toolkit/interop/mask_filter.h FILE: ../../../flutter/impeller/toolkit/interop/object.cc diff --git a/impeller/toolkit/interop/impeller.hpp b/impeller/toolkit/interop/impeller.hpp index f102bcc3ecf16..25a75d9323c81 100644 --- a/impeller/toolkit/interop/impeller.hpp +++ b/impeller/toolkit/interop/impeller.hpp @@ -180,7 +180,8 @@ struct Proc { PROC(ImpellerTypographyContextRetain) struct ProcTable { - bool Initialize(std::function resolver) { + bool Initialize( + const std::function& resolver) { #define IMPELLER_HPP_PROC(proc) \ { \ proc.function = \ @@ -210,7 +211,7 @@ class Object { public: Object() = default; - Object(T object) { Reset(object); } + explicit Object(T object) { Reset(object); } Object(T object, AdoptTag) : object_(object) {} @@ -317,7 +318,7 @@ class Context final : public Object { /// @see ImpellerContextCreateOpenGLESNew /// static Context OpenGLES( - std::function gl_proc_address_resolver) { + const std::function& gl_proc_address_resolver) { struct UserData { std::function resolver; }; @@ -919,7 +920,7 @@ class TypographyContext final : public Object { public: - ParagraphBuilder(const TypographyContext& context) + explicit ParagraphBuilder(const TypographyContext& context) : Object(gGlobalProcTable.ImpellerParagraphBuilderNew(context.Get()), AdoptTag::kAdopt) {} @@ -1111,7 +1112,7 @@ class DisplayList final /// class Surface final : public Object { public: - Surface(ImpellerSurface surface) : Object(surface) {} + explicit Surface(ImpellerSurface surface) : Object(surface) {} Surface(ImpellerSurface surface, AdoptTag tag) : Object(surface, tag) {} @@ -1150,7 +1151,7 @@ class DisplayListBuilder final //---------------------------------------------------------------------------- /// @see ImpellerDisplayListBuilderNew /// - DisplayListBuilder(const ImpellerRect* cull_rect = nullptr) + explicit DisplayListBuilder(const ImpellerRect* cull_rect = nullptr) : Object(gGlobalProcTable.ImpellerDisplayListBuilderNew(cull_rect), AdoptTag::kAdopt) {} From fd2e13cb11255ad706746564b47df2d0b9c30002 Mon Sep 17 00:00:00 2001 From: Chinmay Garde Date: Thu, 21 Nov 2024 15:37:36 -0800 Subject: [PATCH 3/3] Dont depend on vagaries of symbol lookup. --- impeller/toolkit/interop/playground_test.cc | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/impeller/toolkit/interop/playground_test.cc b/impeller/toolkit/interop/playground_test.cc index 6c22fec44b79e..03b100dbe9e6e 100644 --- a/impeller/toolkit/interop/playground_test.cc +++ b/impeller/toolkit/interop/playground_test.cc @@ -4,25 +4,24 @@ #include "impeller/toolkit/interop/playground_test.h" -#include - -#include "flutter/fml/mapping.h" #include "impeller/toolkit/interop/impeller.hpp" namespace IMPELLER_HPP_NAMESPACE { ProcTable gGlobalProcTable; -} +} // namespace IMPELLER_HPP_NAMESPACE namespace impeller::interop::testing { PlaygroundTest::PlaygroundTest() { static std::once_flag sOnceFlag; std::call_once(sOnceFlag, []() { - static auto library = fml::NativeLibrary::CreateForCurrentProcess(); - hpp::gGlobalProcTable.Initialize([&](auto name) { - return const_cast( - reinterpret_cast(library->ResolveSymbol(name))); - }); + std::map proc_map; +#define IMPELLER_HPP_PROC(name) \ + proc_map[#name] = reinterpret_cast(&name); + IMPELLER_HPP_EACH_PROC(IMPELLER_HPP_PROC) +#undef IMPELLER_HPP_PROC + hpp::gGlobalProcTable.Initialize( + [&](auto name) { return proc_map.at(name); }); }); }