blob: 7681efe515f9c8f68a21719418bf6ca42892b1ef [file] [log] [blame]
// 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/toolkit/interop/impeller.h"
#include <sstream>
#include "flutter/fml/mapping.h"
#include "impeller/base/validation.h"
#include "impeller/core/texture.h"
#include "impeller/geometry/scalar.h"
#include "impeller/renderer/backend/gles/context_gles.h"
#include "impeller/renderer/backend/gles/texture_gles.h"
#include "impeller/renderer/context.h"
#include "impeller/toolkit/interop/color_filter.h"
#include "impeller/toolkit/interop/color_source.h"
#include "impeller/toolkit/interop/context.h"
#include "impeller/toolkit/interop/dl_builder.h"
#include "impeller/toolkit/interop/formats.h"
#include "impeller/toolkit/interop/image_filter.h"
#include "impeller/toolkit/interop/mask_filter.h"
#include "impeller/toolkit/interop/object.h"
#include "impeller/toolkit/interop/paint.h"
#include "impeller/toolkit/interop/paragraph.h"
#include "impeller/toolkit/interop/paragraph_builder.h"
#include "impeller/toolkit/interop/paragraph_style.h"
#include "impeller/toolkit/interop/path.h"
#include "impeller/toolkit/interop/path_builder.h"
#include "impeller/toolkit/interop/surface.h"
#include "impeller/toolkit/interop/texture.h"
#include "impeller/toolkit/interop/typography_context.h"
namespace impeller::interop {
#define DEFINE_PEER_GETTER(cxx_type, c_type) \
cxx_type* GetPeer(c_type object) { \
return reinterpret_cast<cxx_type*>(object); \
}
DEFINE_PEER_GETTER(ColorFilter, ImpellerColorFilter);
DEFINE_PEER_GETTER(ColorSource, ImpellerColorSource);
DEFINE_PEER_GETTER(Context, ImpellerContext);
DEFINE_PEER_GETTER(DisplayList, ImpellerDisplayList);
DEFINE_PEER_GETTER(DisplayListBuilder, ImpellerDisplayListBuilder);
DEFINE_PEER_GETTER(ImageFilter, ImpellerImageFilter);
DEFINE_PEER_GETTER(MaskFilter, ImpellerMaskFilter);
DEFINE_PEER_GETTER(Paint, ImpellerPaint);
DEFINE_PEER_GETTER(Paragraph, ImpellerParagraph);
DEFINE_PEER_GETTER(ParagraphBuilder, ImpellerParagraphBuilder);
DEFINE_PEER_GETTER(ParagraphStyle, ImpellerParagraphStyle);
DEFINE_PEER_GETTER(Path, ImpellerPath);
DEFINE_PEER_GETTER(PathBuilder, ImpellerPathBuilder);
DEFINE_PEER_GETTER(Surface, ImpellerSurface);
DEFINE_PEER_GETTER(Texture, ImpellerTexture);
DEFINE_PEER_GETTER(TypographyContext, ImpellerTypographyContext);
static std::string GetVersionAsString(uint32_t version) {
std::stringstream stream;
stream << IMPELLER_VERSION_GET_VARIANT(version) << "."
<< IMPELLER_VERSION_GET_MAJOR(version) << "."
<< IMPELLER_VERSION_GET_MINOR(version) << "."
<< IMPELLER_VERSION_GET_PATCH(version);
return stream.str();
}
IMPELLER_EXTERN_C
uint32_t ImpellerGetVersion() {
return IMPELLER_VERSION;
}
IMPELLER_EXTERN_C
ImpellerContext ImpellerContextCreateOpenGLESNew(
uint32_t version,
ImpellerProcAddressCallback gl_proc_address_callback,
void* gl_proc_address_callback_user_data) {
if (version != IMPELLER_VERSION) {
VALIDATION_LOG << "This version of Impeller ("
<< GetVersionAsString(ImpellerGetVersion()) << ") "
<< "doesn't match the version the user expects ("
<< GetVersionAsString(version) << ").";
return nullptr;
}
auto context = Context::CreateOpenGLES(
[gl_proc_address_callback,
gl_proc_address_callback_user_data](const char* proc_name) -> void* {
return gl_proc_address_callback(proc_name,
gl_proc_address_callback_user_data);
});
if (!context || !context->IsValid()) {
VALIDATION_LOG << "Could not create valid context.";
return nullptr;
}
return context.Leak();
}
IMPELLER_EXTERN_C
void ImpellerContextRetain(ImpellerContext context) {
ObjectBase::SafeRetain(context);
}
IMPELLER_EXTERN_C
void ImpellerContextRelease(ImpellerContext context) {
ObjectBase::SafeRelease(context);
}
IMPELLER_EXTERN_C
ImpellerDisplayListBuilder ImpellerDisplayListBuilderNew(
const ImpellerRect* cull_rect) {
return Create<DisplayListBuilder>(cull_rect).Leak();
}
IMPELLER_EXTERN_C
void ImpellerDisplayListBuilderRetain(ImpellerDisplayListBuilder builder) {
ObjectBase::SafeRetain(builder);
}
IMPELLER_EXTERN_C
void ImpellerDisplayListBuilderRelease(ImpellerDisplayListBuilder builder) {
ObjectBase::SafeRelease(builder);
}
IMPELLER_EXTERN_C
void ImpellerDisplayListBuilderSave(ImpellerDisplayListBuilder builder) {
GetPeer(builder)->Save();
}
IMPELLER_EXTERN_C
void ImpellerDisplayListBuilderSaveLayer(ImpellerDisplayListBuilder builder,
const ImpellerRect* bounds,
ImpellerPaint paint,
ImpellerImageFilter backdrop) {
GetPeer(builder)->SaveLayer(ToImpellerType(*bounds), //
GetPeer(paint), //
GetPeer(backdrop) //
);
}
IMPELLER_EXTERN_C
void ImpellerDisplayListBuilderRestore(ImpellerDisplayListBuilder builder) {
GetPeer(builder)->Restore();
}
IMPELLER_EXTERN_C
void ImpellerDisplayListBuilderScale(ImpellerDisplayListBuilder builder,
float x_scale,
float y_scale) {
GetPeer(builder)->Scale(Size{x_scale, y_scale});
}
IMPELLER_EXTERN_C
void ImpellerDisplayListBuilderRotate(ImpellerDisplayListBuilder builder,
float angle_degrees) {
GetPeer(builder)->Rotate(Degrees{angle_degrees});
}
IMPELLER_EXTERN_C
void ImpellerDisplayListBuilderTranslate(ImpellerDisplayListBuilder builder,
float x_translation,
float y_translation) {
GetPeer(builder)->Translate(Point{x_translation, y_translation});
}
IMPELLER_EXTERN_C
void ImpellerDisplayListBuilderSetTransform(ImpellerDisplayListBuilder builder,
const ImpellerMatrix* transform) {
GetPeer(builder)->SetTransform(ToImpellerType(*transform));
}
IMPELLER_EXTERN_C
void ImpellerDisplayListBuilderTransform(ImpellerDisplayListBuilder builder,
const ImpellerMatrix* transform) {
GetPeer(builder)->Transform(ToImpellerType(*transform));
}
IMPELLER_EXTERN_C
void ImpellerDisplayListBuilderGetTransform(ImpellerDisplayListBuilder builder,
ImpellerMatrix* out_transform) {
FromImpellerType(GetPeer(builder)->GetTransform(), *out_transform);
}
IMPELLER_EXTERN_C
void ImpellerDisplayListBuilderResetTransform(
ImpellerDisplayListBuilder builder) {
GetPeer(builder)->ResetTransform();
}
IMPELLER_EXTERN_C
uint32_t ImpellerDisplayListBuilderGetSaveCount(
ImpellerDisplayListBuilder builder) {
return GetPeer(builder)->GetSaveCount();
}
IMPELLER_EXTERN_C
void ImpellerDisplayListBuilderRestoreToCount(
ImpellerDisplayListBuilder builder,
uint32_t count) {
GetPeer(builder)->RestoreToCount(count);
}
IMPELLER_EXTERN_C
void ImpellerPathRetain(ImpellerPath path) {
ObjectBase::SafeRetain(path);
}
IMPELLER_EXTERN_C
void ImpellerPathRelease(ImpellerPath path) {
ObjectBase::SafeRelease(path);
}
IMPELLER_EXTERN_C
ImpellerPathBuilder ImpellerPathBuilderNew() {
return Create<PathBuilder>().Leak();
}
IMPELLER_EXTERN_C
void ImpellerPathBuilderRetain(ImpellerPathBuilder builder) {
ObjectBase::SafeRetain(builder);
}
IMPELLER_EXTERN_C
void ImpellerPathBuilderRelease(ImpellerPathBuilder builder) {
ObjectBase::SafeRelease(builder);
}
IMPELLER_EXTERN_C
void ImpellerPathBuilderMoveTo(ImpellerPathBuilder builder,
const ImpellerPoint* location) {
GetPeer(builder)->MoveTo(ToImpellerType(*location));
}
IMPELLER_EXTERN_C
void ImpellerPathBuilderLineTo(ImpellerPathBuilder builder,
const ImpellerPoint* location) {
GetPeer(builder)->LineTo(ToImpellerType(*location));
}
IMPELLER_EXTERN_C
void ImpellerPathBuilderQuadraticCurveTo(ImpellerPathBuilder builder,
const ImpellerPoint* control_point,
const ImpellerPoint* end_point) {
GetPeer(builder)->QuadraticCurveTo(ToImpellerType(*control_point),
ToImpellerType(*end_point));
}
IMPELLER_EXTERN_C
void ImpellerPathBuilderCubicCurveTo(ImpellerPathBuilder builder,
const ImpellerPoint* control_point_1,
const ImpellerPoint* control_point_2,
const ImpellerPoint* end_point) {
GetPeer(builder)->CubicCurveTo(ToImpellerType(*control_point_1), //
ToImpellerType(*control_point_2), //
ToImpellerType(*end_point) //
);
}
IMPELLER_EXTERN_C
void ImpellerPathBuilderAddRect(ImpellerPathBuilder builder,
const ImpellerRect* rect) {
GetPeer(builder)->AddRect(ToImpellerType(*rect));
}
IMPELLER_EXTERN_C
void ImpellerPathBuilderAddArc(ImpellerPathBuilder builder,
const ImpellerRect* oval_bounds,
float start_angle_degrees,
float end_angle_degrees) {
GetPeer(builder)->AddArc(ToImpellerType(*oval_bounds), //
Degrees{start_angle_degrees}, //
Degrees{end_angle_degrees} //
);
}
IMPELLER_EXTERN_C
void ImpellerPathBuilderAddOval(ImpellerPathBuilder builder,
const ImpellerRect* oval_bounds) {
GetPeer(builder)->AddOval(ToImpellerType(*oval_bounds));
}
IMPELLER_EXTERN_C
void ImpellerPathBuilderAddRoundedRect(
ImpellerPathBuilder builder,
const ImpellerRect* rect,
const ImpellerRoundingRadii* rounding_radii) {
GetPeer(builder)->AddRoundedRect(ToImpellerType(*rect),
ToImpellerType(*rounding_radii));
}
IMPELLER_EXTERN_C
void ImpellerPathBuilderClose(ImpellerPathBuilder builder) {
GetPeer(builder)->Close();
}
IMPELLER_EXTERN_C
ImpellerPath ImpellerPathBuilderCopyPathNew(ImpellerPathBuilder builder,
ImpellerFillType fill) {
return GetPeer(builder)->CopyPath(ToImpellerType(fill)).Leak();
}
IMPELLER_EXTERN_C
ImpellerPath ImpellerPathBuilderTakePathNew(ImpellerPathBuilder builder,
ImpellerFillType fill) {
return GetPeer(builder)->TakePath(ToImpellerType(fill)).Leak();
}
IMPELLER_EXTERN_C
void ImpellerDisplayListBuilderClipRect(ImpellerDisplayListBuilder builder,
const ImpellerRect* rect,
ImpellerClipOperation op) {
GetPeer(builder)->ClipRect(ToImpellerType(*rect), ToImpellerType(op));
}
IMPELLER_EXTERN_C
void ImpellerDisplayListBuilderClipOval(ImpellerDisplayListBuilder builder,
const ImpellerRect* oval_bounds,
ImpellerClipOperation op) {
GetPeer(builder)->ClipOval(ToImpellerType(*oval_bounds), ToImpellerType(op));
}
IMPELLER_EXTERN_C
void ImpellerDisplayListBuilderClipRoundedRect(
ImpellerDisplayListBuilder builder,
const ImpellerRect* rect,
const ImpellerRoundingRadii* radii,
ImpellerClipOperation op) {
GetPeer(builder)->ClipRoundedRect(ToImpellerType(*rect), //
ToImpellerType(*radii), //
ToImpellerType(op) //
);
}
IMPELLER_EXTERN_C
void ImpellerDisplayListBuilderClipPath(ImpellerDisplayListBuilder builder,
ImpellerPath path,
ImpellerClipOperation op) {
GetPeer(builder)->ClipPath(*GetPeer(path), ToImpellerType(op));
}
IMPELLER_EXTERN_C
ImpellerPaint ImpellerPaintNew() {
return Create<Paint>().Leak();
}
IMPELLER_EXTERN_C
void ImpellerPaintRetain(ImpellerPaint paint) {
ObjectBase::SafeRetain(paint);
}
IMPELLER_EXTERN_C
void ImpellerPaintRelease(ImpellerPaint paint) {
ObjectBase::SafeRelease(paint);
}
IMPELLER_EXTERN_C
void ImpellerPaintSetColor(ImpellerPaint paint, const ImpellerColor* color) {
GetPeer(paint)->SetColor(ToDisplayListType(*color));
}
IMPELLER_EXTERN_C
void ImpellerPaintSetBlendMode(ImpellerPaint paint, ImpellerBlendMode mode) {
GetPeer(paint)->SetBlendMode(ToImpellerType(mode));
}
IMPELLER_EXTERN_C
void ImpellerPaintSetDrawStyle(ImpellerPaint paint, ImpellerDrawStyle style) {
GetPeer(paint)->SetDrawStyle(ToDisplayListType(style));
}
IMPELLER_EXTERN_C
void ImpellerPaintSetStrokeCap(ImpellerPaint paint, ImpellerStrokeCap cap) {
GetPeer(paint)->SetStrokeCap(ToDisplayListType(cap));
}
IMPELLER_EXTERN_C
void ImpellerPaintSetStrokeJoin(ImpellerPaint paint, ImpellerStrokeJoin join) {
GetPeer(paint)->SetStrokeJoin(ToDisplayListType(join));
}
IMPELLER_EXTERN_C
void ImpellerPaintSetStrokeWidth(ImpellerPaint paint, float width) {
GetPeer(paint)->SetStrokeWidth(width);
}
IMPELLER_EXTERN_C
void ImpellerPaintSetStrokeMiter(ImpellerPaint paint, float miter) {
GetPeer(paint)->SetStrokeMiter(miter);
}
IMPELLER_EXTERN_C
void ImpellerDisplayListBuilderDrawPaint(ImpellerDisplayListBuilder builder,
ImpellerPaint paint) {
GetPeer(builder)->DrawPaint(*GetPeer(paint));
}
IMPELLER_EXTERN_C
void ImpellerDisplayListBuilderDrawLine(ImpellerDisplayListBuilder builder,
const ImpellerPoint* from,
const ImpellerPoint* to,
ImpellerPaint paint) {
GetPeer(builder)->DrawLine(ToImpellerType(*from), //
ToImpellerType(*to), //
*GetPeer(paint) //
);
}
IMPELLER_EXTERN_C
void ImpellerDisplayListBuilderDrawDashedLine(
ImpellerDisplayListBuilder builder,
const ImpellerPoint* from,
const ImpellerPoint* to,
float on_length,
float off_length,
ImpellerPaint paint) {
GetPeer(builder)->DrawDashedLine(ToImpellerType(*from), //
ToImpellerType(*to), //
on_length, //
off_length, //
*GetPeer(paint) //
);
}
IMPELLER_EXTERN_C
void ImpellerDisplayListBuilderDrawRect(ImpellerDisplayListBuilder builder,
const ImpellerRect* rect,
ImpellerPaint paint) {
GetPeer(builder)->DrawRect(ToImpellerType(*rect), *GetPeer(paint));
}
IMPELLER_EXTERN_C
void ImpellerDisplayListBuilderDrawOval(ImpellerDisplayListBuilder builder,
const ImpellerRect* oval_bounds,
ImpellerPaint paint) {
GetPeer(builder)->DrawOval(ToImpellerType(*oval_bounds), *GetPeer(paint));
}
IMPELLER_EXTERN_C
void ImpellerDisplayListBuilderDrawRoundedRect(
ImpellerDisplayListBuilder builder,
const ImpellerRect* rect,
const ImpellerRoundingRadii* radii,
ImpellerPaint paint) {
GetPeer(builder)->DrawRoundedRect(ToImpellerType(*rect), //
ToImpellerType(*radii), //
*GetPeer(paint) //
);
}
IMPELLER_EXTERN_C
void ImpellerDisplayListBuilderDrawRoundedRectDifference(
ImpellerDisplayListBuilder builder,
const ImpellerRect* outer_rect,
const ImpellerRoundingRadii* outer_radii,
const ImpellerRect* inner_rect,
const ImpellerRoundingRadii* inner_radii,
ImpellerPaint paint) {
GetPeer(builder)->DrawRoundedRectDifference(ToImpellerType(*outer_rect), //
ToImpellerType(*outer_radii), //
ToImpellerType(*inner_rect), //
ToImpellerType(*inner_radii), //
*GetPeer(paint) //
);
}
IMPELLER_EXTERN_C
void ImpellerDisplayListBuilderDrawPath(ImpellerDisplayListBuilder builder,
ImpellerPath path,
ImpellerPaint paint) {
GetPeer(builder)->DrawPath(*GetPeer(path), *GetPeer(paint));
}
IMPELLER_EXTERN_C
ImpellerTexture ImpellerTextureCreateWithContentsNew(
ImpellerContext context,
const ImpellerTextureDescriptor* descriptor,
const ImpellerMapping* contents,
void* contents_on_release_user_data) {
TextureDescriptor desc;
desc.storage_mode = StorageMode::kDevicePrivate;
desc.type = TextureType::kTexture2D;
desc.format = ToImpellerType(descriptor->pixel_format);
desc.size = ToImpellerType(descriptor->size);
desc.mip_count = std::min(descriptor->mip_count, 1u);
desc.usage = TextureUsage::kShaderRead;
desc.compression_type = CompressionType::kLossless;
auto texture = Create<Texture>(*GetPeer(context), desc);
if (!texture->IsValid()) {
VALIDATION_LOG << "Could not create texture.";
return nullptr;
}
// Depending on whether the de-allocation can be delayed, it may be possible
// to avoid a data copy.
if (contents->on_release) {
// Avoids data copy.
auto wrapped_contents = std::make_shared<fml::NonOwnedMapping>(
contents->data, // data ptr
contents->length, // data length
[on_release = contents->on_release, contents_on_release_user_data](
auto, auto) {
on_release(contents_on_release_user_data);
} // release callback
);
if (!texture->SetContents(std::move(wrapped_contents))) {
VALIDATION_LOG << "Could not set texture contents.";
return nullptr;
}
} else {
// May copy.
if (!texture->SetContents(contents->data, contents->length)) {
VALIDATION_LOG << "Could not set texture contents.";
return nullptr;
}
}
return texture.Leak();
}
IMPELLER_EXTERN_C
ImpellerTexture ImpellerTextureCreateWithOpenGLTextureHandleNew(
ImpellerContext context,
const ImpellerTextureDescriptor* descriptor,
uint64_t external_gl_handle) {
auto impeller_context = GetPeer(context)->GetContext();
if (impeller_context->GetBackendType() !=
impeller::Context::BackendType::kOpenGLES) {
VALIDATION_LOG << "Context is not OpenGL.";
return nullptr;
}
const auto& impeller_context_gl = ContextGLES::Cast(*impeller_context);
const auto& reactor = impeller_context_gl.GetReactor();
TextureDescriptor desc;
desc.storage_mode = StorageMode::kDevicePrivate;
desc.type = TextureType::kTexture2D;
desc.format = ToImpellerType(descriptor->pixel_format);
desc.size = ToImpellerType(descriptor->size);
desc.mip_count = std::min(descriptor->mip_count, 1u);
desc.usage = TextureUsage::kShaderRead;
desc.compression_type = CompressionType::kLossless;
auto texture = TextureGLES::WrapTexture(
reactor, //
desc, //
reactor->CreateHandle(HandleType::kTexture, external_gl_handle) //
);
if (!texture || !texture->IsValid()) {
VALIDATION_LOG << "Could not wrap external texture.";
return nullptr;
}
texture->SetCoordinateSystem(TextureCoordinateSystem::kUploadFromHost);
return Create<Texture>(impeller::Context::BackendType::kOpenGLES,
std::move(texture))
.Leak();
}
IMPELLER_EXTERN_C
void ImpellerTextureRetain(ImpellerTexture texture) {
ObjectBase::SafeRetain(texture);
}
IMPELLER_EXTERN_C
void ImpellerTextureRelease(ImpellerTexture texture) {
ObjectBase::SafeRelease(texture);
}
IMPELLER_EXTERN_C
uint64_t ImpellerTextureGetOpenGLHandle(ImpellerTexture texture) {
auto interop_texture = GetPeer(texture);
if (interop_texture->GetBackendType() !=
impeller::Context::BackendType::kOpenGLES) {
VALIDATION_LOG << "Can only fetch the texture handle of an OpenGL texture.";
return 0u;
}
return TextureGLES::Cast(*interop_texture->GetTexture())
.GetGLHandle()
.value_or(0u);
}
IMPELLER_EXTERN_C
void ImpellerDisplayListRetain(ImpellerDisplayList display_list) {
ObjectBase::SafeRetain(display_list);
}
IMPELLER_EXTERN_C
void ImpellerDisplayListRelease(ImpellerDisplayList display_list) {
ObjectBase::SafeRelease(display_list);
}
IMPELLER_EXTERN_C
ImpellerDisplayList ImpellerDisplayListBuilderCreateDisplayListNew(
ImpellerDisplayListBuilder builder) {
auto dl = GetPeer(builder)->Build();
if (!dl->IsValid()) {
return nullptr;
}
return dl.Leak();
}
IMPELLER_EXTERN_C
void ImpellerDisplayListBuilderDrawDisplayList(
ImpellerDisplayListBuilder builder,
ImpellerDisplayList display_list,
float opacity) {
GetPeer(builder)->DrawDisplayList(*GetPeer(display_list), opacity);
}
IMPELLER_EXTERN_C
ImpellerSurface ImpellerSurfaceCreateWrappedFBONew(ImpellerContext context,
uint64_t fbo,
ImpellerPixelFormat format,
const ImpellerISize* size) {
return Surface::WrapFBO(*GetPeer(context), //
fbo, //
ToImpellerType(format), //
ToImpellerType(*size)) //
.Leak();
}
IMPELLER_EXTERN_C
void ImpellerSurfaceRetain(ImpellerSurface surface) {
ObjectBase::SafeRetain(surface);
}
IMPELLER_EXTERN_C
void ImpellerSurfaceRelease(ImpellerSurface surface) {
ObjectBase::SafeRelease(surface);
}
IMPELLER_EXTERN_C
bool ImpellerSurfaceDrawDisplayList(ImpellerSurface surface,
ImpellerDisplayList display_list) {
return GetPeer(surface)->DrawDisplayList(*GetPeer(display_list));
}
IMPELLER_EXTERN_C
void ImpellerDisplayListBuilderDrawTexture(ImpellerDisplayListBuilder builder,
ImpellerTexture texture,
const ImpellerPoint* point,
ImpellerTextureSampling sampling,
ImpellerPaint paint) {
GetPeer(builder)->DrawTexture(*GetPeer(texture), //
ToImpellerType(*point), //
ToDisplayListType(sampling), //
GetPeer(paint) //
);
}
IMPELLER_EXTERN_C
void ImpellerDisplayListBuilderDrawTextureRect(
ImpellerDisplayListBuilder builder,
ImpellerTexture texture,
const ImpellerRect* src_rect,
const ImpellerRect* dst_rect,
ImpellerTextureSampling sampling,
ImpellerPaint paint) {
GetPeer(builder)->DrawTextureRect(*GetPeer(texture), //
ToImpellerType(*src_rect), //
ToImpellerType(*dst_rect), //
ToDisplayListType(sampling), //
GetPeer(paint) //
);
}
IMPELLER_EXTERN_C
void ImpellerColorSourceRetain(ImpellerColorSource color_source) {
ObjectBase::SafeRetain(color_source);
}
IMPELLER_EXTERN_C
void ImpellerColorSourceRelease(ImpellerColorSource color_source) {
ObjectBase::SafeRelease(color_source);
}
static std::pair<std::vector<flutter::DlColor>, std::vector<Scalar>>
ParseColorsAndStops(uint32_t stop_count,
const ImpellerColor* colors,
const float* stops) {
if (stop_count == 0) {
return {};
}
std::pair<std::vector<flutter::DlColor>, std::vector<Scalar>> result;
result.first.reserve(stop_count);
result.second.reserve(stop_count);
for (size_t i = 0; i < stop_count; i++) {
result.first.emplace_back(ToDisplayListType(colors[i]));
result.second.emplace_back(stops[i]);
}
return result;
}
IMPELLER_EXTERN_C
ImpellerColorSource ImpellerColorSourceCreateLinearGradientNew(
const ImpellerPoint* start_point,
const ImpellerPoint* end_point,
uint32_t stop_count,
const ImpellerColor* colors,
const float* stops,
ImpellerTileMode tile_mode,
const ImpellerMatrix* transformation) {
const auto colors_and_stops = ParseColorsAndStops(stop_count, colors, stops);
return ColorSource::MakeLinearGradient(
ToImpellerType(*start_point), //
ToImpellerType(*end_point), //
colors_and_stops.first, //
colors_and_stops.second, //
ToDisplayListType(tile_mode), //
transformation == nullptr ? Matrix{}
: ToImpellerType(*transformation) //
)
.Leak();
}
IMPELLER_EXTERN_C
ImpellerColorSource ImpellerColorSourceCreateRadialGradientNew(
const ImpellerPoint* center,
float radius,
uint32_t stop_count,
const ImpellerColor* colors,
const float* stops,
ImpellerTileMode tile_mode,
const ImpellerMatrix* transformation) {
const auto colors_and_stops = ParseColorsAndStops(stop_count, colors, stops);
return ColorSource::MakeRadialGradient(
ToImpellerType(*center), //
radius, //
colors_and_stops.first, //
colors_and_stops.second, //
ToDisplayListType(tile_mode), //
transformation == nullptr ? Matrix{}
: ToImpellerType(*transformation) //
)
.Leak();
}
IMPELLER_EXTERN_C
ImpellerColorSource ImpellerColorSourceCreateConicalGradientNew(
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) {
const auto colors_and_stops = ParseColorsAndStops(stop_count, colors, stops);
return ColorSource::MakeConicalGradient(
ToImpellerType(*start_center), //
start_radius, //
ToImpellerType(*end_center), //
end_radius, //
colors_and_stops.first, //
colors_and_stops.second, //
ToDisplayListType(tile_mode), //
transformation == nullptr ? Matrix{}
: ToImpellerType(*transformation) //
)
.Leak();
}
IMPELLER_EXTERN_C
ImpellerColorSource ImpellerColorSourceCreateSweepGradientNew(
const ImpellerPoint* center,
float start,
float end,
uint32_t stop_count,
const ImpellerColor* colors,
const float* stops,
ImpellerTileMode tile_mode,
const ImpellerMatrix* transformation) {
const auto colors_and_stops = ParseColorsAndStops(stop_count, colors, stops);
return ColorSource::MakeSweepGradient(
ToImpellerType(*center), //
start, //
end, //
colors_and_stops.first, //
colors_and_stops.second, //
ToDisplayListType(tile_mode), //
transformation == nullptr ? Matrix{}
: ToImpellerType(*transformation) //
)
.Leak();
}
IMPELLER_EXTERN_C
ImpellerColorSource ImpellerColorSourceCreateImageNew(
ImpellerTexture image,
ImpellerTileMode horizontal_tile_mode,
ImpellerTileMode vertical_tile_mode,
ImpellerTextureSampling sampling,
const ImpellerMatrix* transformation) {
return ColorSource::MakeImage(
*GetPeer(image), //
ToDisplayListType(horizontal_tile_mode), //
ToDisplayListType(vertical_tile_mode), //
ToDisplayListType(sampling), //
transformation == nullptr ? Matrix{}
: ToImpellerType(*transformation) //
)
.Leak();
}
IMPELLER_EXTERN_C
void ImpellerColorFilterRetain(ImpellerColorFilter color_filter) {
ObjectBase::SafeRetain(color_filter);
}
IMPELLER_EXTERN_C
void ImpellerColorFilterRelease(ImpellerColorFilter color_filter) {
ObjectBase::SafeRelease(color_filter);
}
IMPELLER_EXTERN_C
ImpellerColorFilter ImpellerColorFilterCreateBlendNew(
const ImpellerColor* color,
ImpellerBlendMode blend_mode) {
return ColorFilter::MakeBlend(ToImpellerType(*color),
ToImpellerType(blend_mode))
.Leak();
}
IMPELLER_EXTERN_C
ImpellerColorFilter ImpellerColorFilterCreateColorMatrixNew(
const ImpellerColorMatrix* color_matrix) {
return ColorFilter::MakeMatrix(color_matrix->m).Leak();
}
IMPELLER_EXTERN_C
void ImpellerMaskFilterRetain(ImpellerMaskFilter mask_filter) {
ObjectBase::SafeRetain(mask_filter);
}
IMPELLER_EXTERN_C
void ImpellerMaskFilterRelease(ImpellerMaskFilter mask_filter) {
ObjectBase::SafeRelease(mask_filter);
}
IMPELLER_EXTERN_C
ImpellerMaskFilter ImpellerMaskFilterCreateBlurNew(ImpellerBlurStyle style,
float sigma) {
return MaskFilter::MakeBlur(ToDisplayListType(style), sigma).Leak();
}
IMPELLER_EXTERN_C
void ImpellerImageFilterRetain(ImpellerImageFilter image_filter) {
ObjectBase::SafeRetain(image_filter);
}
IMPELLER_EXTERN_C
void ImpellerImageFilterRelease(ImpellerImageFilter image_filter) {
ObjectBase::SafeRelease(image_filter);
}
IMPELLER_EXTERN_C
ImpellerImageFilter ImpellerImageFilterCreateBlurNew(
float x_sigma,
float y_sigma,
ImpellerTileMode tile_mode) {
return ImageFilter::MakeBlur(x_sigma, y_sigma, ToDisplayListType(tile_mode))
.Leak();
}
IMPELLER_EXTERN_C
ImpellerImageFilter ImpellerImageFilterCreateDilateNew(float x_radius,
float y_radius) {
return ImageFilter::MakeDilate(x_radius, y_radius).Leak();
}
IMPELLER_EXTERN_C
ImpellerImageFilter ImpellerImageFilterCreateErodeNew(float x_radius,
float y_radius) {
return ImageFilter::MakeErode(x_radius, y_radius).Leak();
}
IMPELLER_EXTERN_C
ImpellerImageFilter ImpellerImageFilterCreateMatrixNew(
const ImpellerMatrix* matrix,
ImpellerTextureSampling sampling) {
return ImageFilter::MakeMatrix(ToImpellerType(*matrix),
ToDisplayListType(sampling))
.Leak();
}
IMPELLER_EXTERN_C
ImpellerImageFilter ImpellerImageFilterCreateComposeNew(
ImpellerImageFilter outer,
ImpellerImageFilter inner) {
return ImageFilter::MakeCompose(*GetPeer(outer), *GetPeer(inner)).Leak();
}
IMPELLER_EXTERN_C
void ImpellerPaintSetColorFilter(ImpellerPaint paint,
ImpellerColorFilter color_filter) {
GetPeer(paint)->SetColorFilter(*GetPeer(color_filter));
}
IMPELLER_EXTERN_C
void ImpellerPaintSetColorSource(ImpellerPaint paint,
ImpellerColorSource color_source) {
GetPeer(paint)->SetColorSource(*GetPeer(color_source));
}
IMPELLER_EXTERN_C
void ImpellerPaintSetImageFilter(ImpellerPaint paint,
ImpellerImageFilter image_filter) {
GetPeer(paint)->SetImageFilter(*GetPeer(image_filter));
}
IMPELLER_EXTERN_C
void ImpellerPaintSetMaskFilter(ImpellerPaint paint,
ImpellerMaskFilter mask_filter) {
GetPeer(paint)->SetMaskFilter(*GetPeer(mask_filter));
}
IMPELLER_EXTERN_C
ImpellerParagraphStyle ImpellerParagraphStyleNew() {
return Create<ParagraphStyle>().Leak();
}
IMPELLER_EXTERN_C
void ImpellerParagraphStyleRetain(ImpellerParagraphStyle paragraph_style) {
ObjectBase::SafeRetain(paragraph_style);
}
IMPELLER_EXTERN_C
void ImpellerParagraphStyleRelease(ImpellerParagraphStyle paragraph_style) {
ObjectBase::SafeRelease(paragraph_style);
}
IMPELLER_EXTERN_C
void ImpellerParagraphStyleSetForeground(ImpellerParagraphStyle paragraph_style,
ImpellerPaint paint) {
GetPeer(paragraph_style)->SetForeground(Ref(GetPeer(paint)));
}
IMPELLER_EXTERN_C
void ImpellerParagraphStyleSetBackground(ImpellerParagraphStyle paragraph_style,
ImpellerPaint paint) {
GetPeer(paragraph_style)->SetBackground(Ref(GetPeer(paint)));
}
IMPELLER_EXTERN_C
void ImpellerParagraphStyleSetFontWeight(ImpellerParagraphStyle paragraph_style,
ImpellerFontWeight weight) {
GetPeer(paragraph_style)->SetFontWeight(ToTxtType(weight));
}
IMPELLER_EXTERN_C
void ImpellerParagraphStyleSetFontStyle(ImpellerParagraphStyle paragraph_style,
ImpellerFontStyle style) {
GetPeer(paragraph_style)->SetFontStyle(ToTxtType(style));
}
static std::string ReadString(const char* string) {
if (string == nullptr) {
return "";
}
return std::string{string};
}
IMPELLER_EXTERN_C
void ImpellerParagraphStyleSetFontFamily(ImpellerParagraphStyle paragraph_style,
const char* family_name) {
GetPeer(paragraph_style)->SetFontFamily(ReadString(family_name));
}
IMPELLER_EXTERN_C
void ImpellerParagraphStyleSetFontSize(ImpellerParagraphStyle paragraph_style,
float size) {
GetPeer(paragraph_style)->SetFontSize(size);
}
IMPELLER_EXTERN_C
void ImpellerParagraphStyleSetHeight(ImpellerParagraphStyle paragraph_style,
float height) {
GetPeer(paragraph_style)->SetHeight(height);
}
IMPELLER_EXTERN_C
void ImpellerParagraphStyleSetTextAlignment(
ImpellerParagraphStyle paragraph_style,
ImpellerTextAlignment align) {
GetPeer(paragraph_style)->SetTextAlignment(ToTxtType(align));
}
IMPELLER_EXTERN_C
void ImpellerParagraphStyleSetTextDirection(
ImpellerParagraphStyle paragraph_style,
ImpellerTextDirection direction) {
GetPeer(paragraph_style)->SetTextDirection(ToTxtType(direction));
}
IMPELLER_EXTERN_C
void ImpellerParagraphStyleSetMaxLines(ImpellerParagraphStyle paragraph_style,
uint32_t max_lines) {
GetPeer(paragraph_style)->SetMaxLines(max_lines);
}
IMPELLER_EXTERN_C
void ImpellerParagraphStyleSetLocale(ImpellerParagraphStyle paragraph_style,
const char* locale) {
GetPeer(paragraph_style)->SetLocale(ReadString(locale));
}
IMPELLER_EXTERN_C
void ImpellerDisplayListBuilderDrawParagraph(ImpellerDisplayListBuilder builder,
ImpellerParagraph paragraph,
const ImpellerPoint* point) {
GetPeer(builder)->DrawParagraph(*GetPeer(paragraph), ToImpellerType(*point));
}
IMPELLER_EXTERN_C
ImpellerParagraphBuilder ImpellerParagraphBuilderNew(
ImpellerTypographyContext context) {
auto builder =
Create<ParagraphBuilder>(Ref<TypographyContext>(GetPeer(context)));
if (!builder->IsValid()) {
VALIDATION_LOG << "Could not create valid paragraph builder.";
return nullptr;
}
return builder.Leak();
}
IMPELLER_EXTERN_C
void ImpellerParagraphBuilderRetain(
ImpellerParagraphBuilder paragraph_builder) {
ObjectBase::SafeRetain(paragraph_builder);
}
IMPELLER_EXTERN_C
void ImpellerParagraphBuilderRelease(
ImpellerParagraphBuilder paragraph_builder) {
ObjectBase::SafeRelease(paragraph_builder);
}
IMPELLER_EXTERN_C
void ImpellerParagraphBuilderPushStyle(
ImpellerParagraphBuilder paragraph_builder,
ImpellerParagraphStyle style) {
GetPeer(paragraph_builder)->PushStyle(*GetPeer(style));
}
IMPELLER_EXTERN_C
void ImpellerParagraphBuilderPopStyle(
ImpellerParagraphBuilder paragraph_builder) {
GetPeer(paragraph_builder)->PopStyle();
}
IMPELLER_EXTERN_C
void ImpellerParagraphBuilderAddText(ImpellerParagraphBuilder paragraph_builder,
const uint8_t* data,
uint32_t length) {
if (data == nullptr) {
length = 0;
}
if (length == 0) {
return;
}
GetPeer(paragraph_builder)->AddText(data, length);
}
IMPELLER_EXTERN_C
ImpellerParagraph ImpellerParagraphBuilderBuildParagraphNew(
ImpellerParagraphBuilder paragraph_builder,
float width) {
return GetPeer(paragraph_builder)->Build(width).Leak();
}
IMPELLER_EXTERN_C
void ImpellerParagraphRetain(ImpellerParagraph paragraph) {
ObjectBase::SafeRetain(paragraph);
}
IMPELLER_EXTERN_C
void ImpellerParagraphRelease(ImpellerParagraph paragraph) {
ObjectBase::SafeRelease(paragraph);
}
IMPELLER_EXTERN_C
float ImpellerParagraphGetMaxWidth(ImpellerParagraph paragraph) {
return GetPeer(paragraph)->GetMaxWidth();
}
IMPELLER_EXTERN_C
float ImpellerParagraphGetHeight(ImpellerParagraph paragraph) {
return GetPeer(paragraph)->GetHeight();
}
IMPELLER_EXTERN_C
float ImpellerParagraphGetLongestLineWidth(ImpellerParagraph paragraph) {
return GetPeer(paragraph)->GetLongestLineWidth();
}
IMPELLER_EXTERN_C
float ImpellerParagraphGetMinIntrinsicWidth(ImpellerParagraph paragraph) {
return GetPeer(paragraph)->GetMinIntrinsicWidth();
}
IMPELLER_EXTERN_C
float ImpellerParagraphGetMaxIntrinsicWidth(ImpellerParagraph paragraph) {
return GetPeer(paragraph)->GetMaxIntrinsicWidth();
}
IMPELLER_EXTERN_C
float ImpellerParagraphGetIdeographicBaseline(ImpellerParagraph paragraph) {
return GetPeer(paragraph)->GetIdeographicBaseline();
}
IMPELLER_EXTERN_C
float ImpellerParagraphGetAlphabeticBaseline(ImpellerParagraph paragraph) {
return GetPeer(paragraph)->GetAlphabeticBaseline();
}
IMPELLER_EXTERN_C
uint32_t ImpellerParagraphGetLineCount(ImpellerParagraph paragraph) {
return GetPeer(paragraph)->GetLineCount();
}
IMPELLER_EXTERN_C
ImpellerTypographyContext ImpellerTypographyContextNew() {
auto context = Create<TypographyContext>();
if (!context->IsValid()) {
VALIDATION_LOG << "Could not create typography context.";
return nullptr;
}
return Create<TypographyContext>().Leak();
}
IMPELLER_EXTERN_C
void ImpellerTypographyContextRetain(ImpellerTypographyContext context) {
ObjectBase::SafeRetain(context);
}
IMPELLER_EXTERN_C
void ImpellerTypographyContextRelease(ImpellerTypographyContext context) {
ObjectBase::SafeRelease(context);
}
IMPELLER_EXTERN_C
bool ImpellerTypographyContextRegisterFont(ImpellerTypographyContext context,
const ImpellerMapping* contents,
void* contents_on_release_user_data,
const char* family_name_alias) {
auto wrapped_contents = std::make_unique<fml::NonOwnedMapping>(
contents->data, // data ptr
contents->length, // data length
[on_release = contents->on_release, contents_on_release_user_data](auto,
auto) {
on_release(contents_on_release_user_data);
} // release callback
);
return GetPeer(context)->RegisterFont(std::move(wrapped_contents),
family_name_alias);
}
} // namespace impeller::interop