///|
fn path_mesh_payload(mesh : @render_common.PathMesh) -> String {
let values : Array[String] = []
for vertex in mesh.vertices() {
for component in vertex.components() {
values.push(component.to_string())
}
}
values.join(",")
}
///|
priv struct HostLayerMaskPayload {
kind : Int
rect : @core.Rect
radius : Double
}
///|
fn layer_mask_payload(mask : @core.LayerMask) -> HostLayerMaskPayload {
match mask {
@core.LayerMask::NoMask =>
{
kind: 0,
rect: @core.Rect::new(x=0.0, y=0.0, width=0.0, height=0.0),
radius: 0.0,
}
@core.LayerMask::RectMask(rect) => { kind: 1, rect, radius: 0.0 }
@core.LayerMask::RoundedMask(rounded) =>
{ kind: 2, rect: rounded.rect, radius: rounded.radius }
}
}
///|
priv struct HostFilterPayload {
kind : Int
amount : Double
matrix_values : String
}
///|
fn filter_effect_payload(filter : @core.FilterEffect) -> HostFilterPayload {
match filter {
@core.FilterEffect::Blur(radius) =>
{ kind: 0, amount: radius.max(0.0), matrix_values: "" }
@core.FilterEffect::Saturate(amount) =>
{ kind: 1, amount, matrix_values: "" }
@core.FilterEffect::Brightness(amount) =>
{ kind: 2, amount, matrix_values: "" }
@core.FilterEffect::Contrast(amount) =>
{ kind: 3, amount, matrix_values: "" }
@core.FilterEffect::ColorMatrix(values) =>
{ kind: 4, amount: 1.0, matrix_values: double_array_string(values) }
}
}
///|
fn blend_mode_host_code(mode : @core.BlendMode) -> Int {
match mode {
@core.BlendMode::SourceOver => 0
@core.BlendMode::Multiply => 1
@core.BlendMode::Screen => 2
@core.BlendMode::Overlay => 3
@core.BlendMode::Darken => 4
@core.BlendMode::Lighten => 5
}
}
///|
fn brush_payload(brush : @core.Brush, frame : @core.Rect) -> HostBrushPayload {
match brush {
@core.Brush::Solid(color) =>
{
start: frame.origin,
end: @core.Point::new(x=frame.origin.x + 1.0, y=frame.origin.y),
start_color: color,
end_color: color,
}
@core.Brush::LinearGradient(gradient) =>
{
start: gradient.start,
end: gradient.end,
start_color: gradient.start_color,
end_color: gradient.end_color,
}
@core.Brush::RadialGradient(gradient) =>
{
start: gradient.center,
end: @core.Point::new(
x=gradient.center.x + gradient.radius.max(1.0),
y=gradient.center.y,
),
start_color: gradient.center_color,
end_color: gradient.edge_color,
}
}
}
///|
fn radial_brush_payload(
gradient : @core.RadialGradientSpec,
) -> HostRadialBrushPayload {
{
center: gradient.center,
radius: gradient.radius.max(1.0),
center_color: gradient.center_color,
edge_color: gradient.edge_color,
}
}
///|
fn rounded_brush_host_payload(
brush : @core.Brush,
frame : @core.Rect,
) -> RoundedBrushHostPayload {
match brush {
@core.Brush::Solid(color) => RoundedBrushHostPayload::SolidColor(color)
@core.Brush::LinearGradient(_) =>
RoundedBrushHostPayload::LinearGradientPayload(
brush_payload(brush, frame),
)
@core.Brush::RadialGradient(gradient) =>
RoundedBrushHostPayload::RadialGradientPayload(
radial_brush_payload(gradient),
)
}
}
///|
fn double_array_string(values : Array[Double]) -> String {
let parts : Array[String] = []
for value in values {
parts.push(value.to_string())
}
parts.join(",")
}
///|
fn submit_fill_rounded_rect_brush(
renderer : HostWebGpuRenderer,
rounded : @core.RoundedRect,
brush : @core.Brush,
) -> Unit raise WebGpuHostError {
match rounded_brush_host_payload(brush, rounded.rect) {
RoundedBrushHostPayload::SolidColor(color) =>
raise_for_host_status(
host_fill_rounded_rect(
renderer,
rounded.rect.origin.x,
rounded.rect.origin.y,
rounded.rect.size.width,
rounded.rect.size.height,
rounded.radius,
color.r,
color.g,
color.b,
color.a,
),
)
RoundedBrushHostPayload::LinearGradientPayload(payload) =>
raise_for_host_status(
host_fill_rounded_rect_gradient(
renderer,
rounded.rect.origin.x,
rounded.rect.origin.y,
rounded.rect.size.width,
rounded.rect.size.height,
rounded.radius,
payload.start.x,
payload.start.y,
payload.end.x,
payload.end.y,
payload.start_color.r,
payload.start_color.g,
payload.start_color.b,
payload.start_color.a,
payload.end_color.r,
payload.end_color.g,
payload.end_color.b,
payload.end_color.a,
),
)
RoundedBrushHostPayload::RadialGradientPayload(payload) =>
raise_for_host_status(
host_fill_rounded_rect_radial(
renderer,
rounded.rect.origin.x,
rounded.rect.origin.y,
rounded.rect.size.width,
rounded.rect.size.height,
rounded.radius,
payload.center.x,
payload.center.y,
payload.radius,
payload.center_color.r,
payload.center_color.g,
payload.center_color.b,
payload.center_color.a,
payload.edge_color.r,
payload.edge_color.g,
payload.edge_color.b,
payload.edge_color.a,
),
)
}
}
///|
fn submit_stroke_rounded_rect_brush(
renderer : HostWebGpuRenderer,
rounded : @core.RoundedRect,
brush : @core.Brush,
width : Double,
) -> Unit raise WebGpuHostError {
match rounded_brush_host_payload(brush, rounded.rect) {
RoundedBrushHostPayload::SolidColor(color) =>
raise_for_host_status(
host_stroke_rounded_rect(
renderer,
rounded.rect.origin.x,
rounded.rect.origin.y,
rounded.rect.size.width,
rounded.rect.size.height,
rounded.radius,
color.r,
color.g,
color.b,
color.a,
width,
),
)
RoundedBrushHostPayload::LinearGradientPayload(payload) =>
raise_for_host_status(
host_stroke_rounded_rect_gradient(
renderer,
rounded.rect.origin.x,
rounded.rect.origin.y,
rounded.rect.size.width,
rounded.rect.size.height,
rounded.radius,
width,
payload.start.x,
payload.start.y,
payload.end.x,
payload.end.y,
payload.start_color.r,
payload.start_color.g,
payload.start_color.b,
payload.start_color.a,
payload.end_color.r,
payload.end_color.g,
payload.end_color.b,
payload.end_color.a,
),
)
RoundedBrushHostPayload::RadialGradientPayload(payload) =>
raise_for_host_status(
host_stroke_rounded_rect_radial(
renderer,
rounded.rect.origin.x,
rounded.rect.origin.y,
rounded.rect.size.width,
rounded.rect.size.height,
rounded.radius,
width,
payload.center.x,
payload.center.y,
payload.radius,
payload.center_color.r,
payload.center_color.g,
payload.center_color.b,
payload.center_color.a,
payload.edge_color.r,
payload.edge_color.g,
payload.edge_color.b,
payload.edge_color.a,
),
)
}
}