///|
#borrow(canvas)
extern "C" fn native_canvas_is_null(canvas : CanvasHandle) -> Bool = "moonbit_skia_canvas_is_null"
///|
#borrow(canvas)
extern "C" fn native_canvas_save(canvas : CanvasHandle) -> Int = "moonbit_skia_canvas_save"
///|
#borrow(canvas, color_filter, image_filter, mask_filter)
extern "C" fn native_canvas_save_layer(
canvas : CanvasHandle,
has_bounds : Bool,
left : Float,
top : Float,
right : Float,
bottom : Float,
color_argb : UInt,
anti_alias : Bool,
dither : Bool,
style : Int,
stroke_width : Float,
stroke_miter : Float,
stroke_cap : Int,
stroke_join : Int,
blend_mode : Int,
color_filter : ColorFilterHandle,
image_filter : ImageFilterHandle,
mask_filter : MaskFilterHandle,
) -> Int = "moonbit_skia_canvas_save_layer"
///|
#borrow(canvas)
extern "C" fn native_canvas_restore(canvas : CanvasHandle) -> Unit = "moonbit_skia_canvas_restore"
///|
#borrow(canvas)
extern "C" fn native_canvas_restore_to_count(
canvas : CanvasHandle,
count : Int,
) -> Unit = "moonbit_skia_canvas_restore_to_count"
///|
#borrow(canvas)
extern "C" fn native_canvas_save_count(canvas : CanvasHandle) -> Int = "moonbit_skia_canvas_save_count"
///|
#borrow(canvas)
extern "C" fn native_canvas_translate(
canvas : CanvasHandle,
dx : Float,
dy : Float,
) -> Unit = "moonbit_skia_canvas_translate"
///|
#borrow(canvas)
extern "C" fn native_canvas_scale(
canvas : CanvasHandle,
sx : Float,
sy : Float,
) -> Unit = "moonbit_skia_canvas_scale"
///|
#borrow(canvas)
extern "C" fn native_canvas_rotate(
canvas : CanvasHandle,
degrees : Float,
) -> Unit = "moonbit_skia_canvas_rotate"
///|
#borrow(canvas)
extern "C" fn native_canvas_skew(
canvas : CanvasHandle,
sx : Float,
sy : Float,
) -> Unit = "moonbit_skia_canvas_skew"
///|
#borrow(canvas)
extern "C" fn native_canvas_concat(
canvas : CanvasHandle,
scale_x : Float,
skew_x : Float,
trans_x : Float,
skew_y : Float,
scale_y : Float,
trans_y : Float,
persp_0 : Float,
persp_1 : Float,
persp_2 : Float,
) -> Unit = "moonbit_skia_canvas_concat"
///|
#borrow(canvas)
extern "C" fn native_canvas_reset_matrix(canvas : CanvasHandle) -> Unit = "moonbit_skia_canvas_reset_matrix"
///|
#borrow(canvas)
extern "C" fn native_canvas_discard(canvas : CanvasHandle) -> Unit = "moonbit_skia_canvas_discard"
///|
#borrow(canvas)
extern "C" fn native_canvas_clip_rect(
canvas : CanvasHandle,
left : Float,
top : Float,
right : Float,
bottom : Float,
op : Int,
anti_alias : Bool,
) -> Unit = "moonbit_skia_canvas_clip_rect"
///|
#borrow(canvas)
extern "C" fn native_canvas_clip_rrect(
canvas : CanvasHandle,
left : Float,
top : Float,
right : Float,
bottom : Float,
upper_left_width : Float,
upper_left_height : Float,
upper_right_width : Float,
upper_right_height : Float,
lower_right_width : Float,
lower_right_height : Float,
lower_left_width : Float,
lower_left_height : Float,
op : Int,
anti_alias : Bool,
) -> Unit = "moonbit_skia_canvas_clip_rrect"
///|
#borrow(canvas, path)
extern "C" fn native_canvas_clip_path(
canvas : CanvasHandle,
path : PathHandle,
op : Int,
anti_alias : Bool,
) -> Unit = "moonbit_skia_canvas_clip_path"
///|
#borrow(canvas)
extern "C" fn native_canvas_local_clip_bounds(canvas : CanvasHandle) -> Bool = "moonbit_skia_canvas_local_clip_bounds"
///|
#borrow(canvas)
extern "C" fn native_canvas_local_clip_bounds_left(
canvas : CanvasHandle,
) -> Float = "moonbit_skia_canvas_local_clip_bounds_left"
///|
#borrow(canvas)
extern "C" fn native_canvas_local_clip_bounds_top(
canvas : CanvasHandle,
) -> Float = "moonbit_skia_canvas_local_clip_bounds_top"
///|
#borrow(canvas)
extern "C" fn native_canvas_local_clip_bounds_right(
canvas : CanvasHandle,
) -> Float = "moonbit_skia_canvas_local_clip_bounds_right"
///|
#borrow(canvas)
extern "C" fn native_canvas_local_clip_bounds_bottom(
canvas : CanvasHandle,
) -> Float = "moonbit_skia_canvas_local_clip_bounds_bottom"
///|
#borrow(canvas)
extern "C" fn native_canvas_device_clip_bounds(canvas : CanvasHandle) -> Bool = "moonbit_skia_canvas_device_clip_bounds"
///|
#borrow(canvas)
extern "C" fn native_canvas_device_clip_bounds_left(
canvas : CanvasHandle,
) -> Int = "moonbit_skia_canvas_device_clip_bounds_left"
///|
#borrow(canvas)
extern "C" fn native_canvas_device_clip_bounds_top(
canvas : CanvasHandle,
) -> Int = "moonbit_skia_canvas_device_clip_bounds_top"
///|
#borrow(canvas)
extern "C" fn native_canvas_device_clip_bounds_right(
canvas : CanvasHandle,
) -> Int = "moonbit_skia_canvas_device_clip_bounds_right"
///|
#borrow(canvas)
extern "C" fn native_canvas_device_clip_bounds_bottom(
canvas : CanvasHandle,
) -> Int = "moonbit_skia_canvas_device_clip_bounds_bottom"
///|
#borrow(canvas)
extern "C" fn native_canvas_quick_reject_rect(
canvas : CanvasHandle,
left : Float,
top : Float,
right : Float,
bottom : Float,
) -> Bool = "moonbit_skia_canvas_quick_reject_rect"
///|
#borrow(canvas, path)
extern "C" fn native_canvas_quick_reject_path(
canvas : CanvasHandle,
path : PathHandle,
) -> Bool = "moonbit_skia_canvas_quick_reject_path"
///|
#borrow(canvas)
extern "C" fn native_canvas_draw_color(
canvas : CanvasHandle,
color_argb : UInt,
blend_mode : Int,
) -> Unit = "moonbit_skia_canvas_draw_color"
///|
#borrow(canvas, picture)
extern "C" fn native_canvas_draw_picture(
canvas : CanvasHandle,
picture : PictureHandle,
) -> Unit = "moonbit_skia_canvas_draw_picture"
///|
#borrow(canvas)
extern "C" fn native_canvas_draw_paint(
canvas : CanvasHandle,
color_argb : UInt,
anti_alias : Bool,
dither : Bool,
style : Int,
stroke_width : Float,
stroke_miter : Float,
stroke_cap : Int,
stroke_join : Int,
blend_mode : Int,
) -> Unit = "moonbit_skia_canvas_draw_paint"
///|
#borrow(canvas)
extern "C" fn native_canvas_draw_point(
canvas : CanvasHandle,
x : Float,
y : Float,
color_argb : UInt,
anti_alias : Bool,
dither : Bool,
style : Int,
stroke_width : Float,
stroke_miter : Float,
stroke_cap : Int,
stroke_join : Int,
blend_mode : Int,
) -> Unit = "moonbit_skia_canvas_draw_point"
///|
#borrow(canvas)
extern "C" fn native_canvas_draw_line(
canvas : CanvasHandle,
x0 : Float,
y0 : Float,
x1 : Float,
y1 : Float,
color_argb : UInt,
anti_alias : Bool,
dither : Bool,
style : Int,
stroke_width : Float,
stroke_miter : Float,
stroke_cap : Int,
stroke_join : Int,
blend_mode : Int,
) -> Unit = "moonbit_skia_canvas_draw_line"
///|
#borrow(canvas)
extern "C" fn native_canvas_draw_rect(
canvas : CanvasHandle,
left : Float,
top : Float,
right : Float,
bottom : Float,
color_argb : UInt,
anti_alias : Bool,
dither : Bool,
style : Int,
stroke_width : Float,
stroke_miter : Float,
stroke_cap : Int,
stroke_join : Int,
blend_mode : Int,
) -> Unit = "moonbit_skia_canvas_draw_rect"
///|
#borrow(canvas)
extern "C" fn native_canvas_draw_oval(
canvas : CanvasHandle,
left : Float,
top : Float,
right : Float,
bottom : Float,
color_argb : UInt,
anti_alias : Bool,
dither : Bool,
style : Int,
stroke_width : Float,
stroke_miter : Float,
stroke_cap : Int,
stroke_join : Int,
blend_mode : Int,
) -> Unit = "moonbit_skia_canvas_draw_oval"
///|
#borrow(canvas)
extern "C" fn native_canvas_draw_circle(
canvas : CanvasHandle,
x : Float,
y : Float,
radius : Float,
color_argb : UInt,
anti_alias : Bool,
dither : Bool,
style : Int,
stroke_width : Float,
stroke_miter : Float,
stroke_cap : Int,
stroke_join : Int,
blend_mode : Int,
) -> Unit = "moonbit_skia_canvas_draw_circle"
///|
#borrow(canvas)
extern "C" fn native_canvas_draw_arc(
canvas : CanvasHandle,
left : Float,
top : Float,
right : Float,
bottom : Float,
start_angle : Float,
sweep_angle : Float,
use_center : Bool,
color_argb : UInt,
anti_alias : Bool,
dither : Bool,
style : Int,
stroke_width : Float,
stroke_miter : Float,
stroke_cap : Int,
stroke_join : Int,
blend_mode : Int,
) -> Unit = "moonbit_skia_canvas_draw_arc"
///|
#borrow(canvas)
extern "C" fn native_canvas_draw_round_rect(
canvas : CanvasHandle,
left : Float,
top : Float,
right : Float,
bottom : Float,
rx : Float,
ry : Float,
color_argb : UInt,
anti_alias : Bool,
dither : Bool,
style : Int,
stroke_width : Float,
stroke_miter : Float,
stroke_cap : Int,
stroke_join : Int,
blend_mode : Int,
) -> Unit = "moonbit_skia_canvas_draw_round_rect"
///|
#borrow(canvas)
extern "C" fn native_canvas_draw_rrect(
canvas : CanvasHandle,
left : Float,
top : Float,
right : Float,
bottom : Float,
upper_left_width : Float,
upper_left_height : Float,
upper_right_width : Float,
upper_right_height : Float,
lower_right_width : Float,
lower_right_height : Float,
lower_left_width : Float,
lower_left_height : Float,
color_argb : UInt,
anti_alias : Bool,
dither : Bool,
style : Int,
stroke_width : Float,
stroke_miter : Float,
stroke_cap : Int,
stroke_join : Int,
blend_mode : Int,
) -> Unit = "moonbit_skia_canvas_draw_rrect"
///|
#borrow(canvas)
extern "C" fn native_canvas_draw_drrect(
canvas : CanvasHandle,
outer_left : Float,
outer_top : Float,
outer_right : Float,
outer_bottom : Float,
outer_upper_left_width : Float,
outer_upper_left_height : Float,
outer_upper_right_width : Float,
outer_upper_right_height : Float,
outer_lower_right_width : Float,
outer_lower_right_height : Float,
outer_lower_left_width : Float,
outer_lower_left_height : Float,
inner_left : Float,
inner_top : Float,
inner_right : Float,
inner_bottom : Float,
inner_upper_left_width : Float,
inner_upper_left_height : Float,
inner_upper_right_width : Float,
inner_upper_right_height : Float,
inner_lower_right_width : Float,
inner_lower_right_height : Float,
inner_lower_left_width : Float,
inner_lower_left_height : Float,
color_argb : UInt,
anti_alias : Bool,
dither : Bool,
style : Int,
stroke_width : Float,
stroke_miter : Float,
stroke_cap : Int,
stroke_join : Int,
blend_mode : Int,
) -> Unit = "moonbit_skia_canvas_draw_drrect"
///|
#borrow(canvas, path)
extern "C" fn native_canvas_draw_path(
canvas : CanvasHandle,
path : PathHandle,
color_argb : UInt,
anti_alias : Bool,
dither : Bool,
style : Int,
stroke_width : Float,
stroke_miter : Float,
stroke_cap : Int,
stroke_join : Int,
blend_mode : Int,
) -> Unit = "moonbit_skia_canvas_draw_path"
///|
#borrow(canvas, path, shader)
extern "C" fn native_canvas_draw_path_shader(
canvas : CanvasHandle,
path : PathHandle,
shader : ShaderHandle,
color_argb : UInt,
anti_alias : Bool,
dither : Bool,
style : Int,
stroke_width : Float,
stroke_miter : Float,
stroke_cap : Int,
stroke_join : Int,
blend_mode : Int,
) -> Unit = "moonbit_skia_canvas_draw_path_shader"
///|
#borrow(canvas, image)
extern "C" fn native_canvas_draw_image(
canvas : CanvasHandle,
image : ImageHandle,
x : Float,
y : Float,
) -> Unit = "moonbit_skia_canvas_draw_image"
///|
#borrow(canvas, image)
extern "C" fn native_canvas_draw_image_rect(
canvas : CanvasHandle,
image : ImageHandle,
src_left : Float,
src_top : Float,
src_right : Float,
src_bottom : Float,
dst_left : Float,
dst_top : Float,
dst_right : Float,
dst_bottom : Float,
color_argb : UInt,
anti_alias : Bool,
dither : Bool,
style : Int,
stroke_width : Float,
stroke_miter : Float,
stroke_cap : Int,
stroke_join : Int,
blend_mode : Int,
sampling_filter : Int,
sampling_mipmap : Int,
sampling_use_cubic : Bool,
sampling_cubic_b : Float,
sampling_cubic_c : Float,
) -> Unit = "moonbit_skia_canvas_draw_image_rect"
///|
#borrow(canvas, shader)
extern "C" fn native_canvas_draw_paint_shader(
canvas : CanvasHandle,
shader : ShaderHandle,
color_argb : UInt,
anti_alias : Bool,
dither : Bool,
style : Int,
stroke_width : Float,
stroke_miter : Float,
stroke_cap : Int,
stroke_join : Int,
blend_mode : Int,
) -> Unit = "moonbit_skia_canvas_draw_paint_shader"
///|
#borrow(canvas, shader)
extern "C" fn native_canvas_draw_rect_shader(
canvas : CanvasHandle,
shader : ShaderHandle,
left : Float,
top : Float,
right : Float,
bottom : Float,
color_argb : UInt,
anti_alias : Bool,
dither : Bool,
style : Int,
stroke_width : Float,
stroke_miter : Float,
stroke_cap : Int,
stroke_join : Int,
blend_mode : Int,
) -> Unit = "moonbit_skia_canvas_draw_rect_shader"
///|
#borrow(canvas, shader)
extern "C" fn native_canvas_draw_round_rect_shader(
canvas : CanvasHandle,
shader : ShaderHandle,
left : Float,
top : Float,
right : Float,
bottom : Float,
rx : Float,
ry : Float,
color_argb : UInt,
anti_alias : Bool,
dither : Bool,
style : Int,
stroke_width : Float,
stroke_miter : Float,
stroke_cap : Int,
stroke_join : Int,
blend_mode : Int,
) -> Unit = "moonbit_skia_canvas_draw_round_rect_shader"
///|
#borrow(canvas, text, font)
extern "C" fn native_canvas_draw_text_utf8(
canvas : CanvasHandle,
text : Bytes,
x : Float,
y : Float,
font : FontHandle,
color_argb : UInt,
anti_alias : Bool,
dither : Bool,
style : Int,
stroke_width : Float,
stroke_miter : Float,
stroke_cap : Int,
stroke_join : Int,
blend_mode : Int,
) -> Unit = "moonbit_skia_canvas_draw_text_utf8"
///|
#borrow(canvas, glyph_bytes, position_bytes, font)
extern "C" fn native_canvas_draw_glyphs(
canvas : CanvasHandle,
glyph_bytes : Bytes,
position_bytes : Bytes,
glyph_count : Int,
origin_x : Float,
origin_y : Float,
font : FontHandle,
color_argb : UInt,
anti_alias : Bool,
dither : Bool,
style : Int,
stroke_width : Float,
stroke_miter : Float,
stroke_cap : Int,
stroke_join : Int,
blend_mode : Int,
) -> Bool = "moonbit_skia_canvas_draw_glyphs"
///|
pub fn Canvas::is_available(self : Canvas) -> Bool {
ignore(self.owner)
!native_canvas_is_null(self.handle)
}
///|
pub fn Canvas::save(self : Canvas) -> Int {
native_canvas_save(self.handle)
}
///|
pub fn Canvas::save_layer(
self : Canvas,
bounds? : @skia.Rect? = None,
paint? : @skia.Paint = @skia.Paint::new(),
color_filter? : ColorFilter? = None,
image_filter? : ImageFilter? = None,
mask_filter? : MaskFilter? = None,
) -> Int {
let color_filter_handle = match color_filter {
Some(filter) => filter.handle
None => native_color_filter_null()
}
let image_filter_handle = match image_filter {
Some(filter) => filter.handle
None => native_image_filter_null()
}
let mask_filter_handle = match mask_filter {
Some(filter) => filter.handle
None => native_mask_filter_null()
}
let bounds = match bounds {
Some(rect) if rect.is_finite() => Some(rect)
_ => None
}
match bounds {
None =>
native_canvas_save_layer(
self.handle,
false,
0,
0,
0,
0,
paint.color_argb(),
paint.anti_alias,
paint.dither,
paint.style_ordinal(),
native_canvas_paint_stroke_width(paint),
native_canvas_paint_stroke_miter(paint),
paint.stroke_cap_ordinal(),
paint.stroke_join_ordinal(),
paint.blend_mode_ordinal(),
color_filter_handle,
image_filter_handle,
mask_filter_handle,
)
Some(rect) =>
native_canvas_save_layer(
self.handle,
true,
rect.left,
rect.top,
rect.right,
rect.bottom,
paint.color_argb(),
paint.anti_alias,
paint.dither,
paint.style_ordinal(),
native_canvas_paint_stroke_width(paint),
native_canvas_paint_stroke_miter(paint),
paint.stroke_cap_ordinal(),
paint.stroke_join_ordinal(),
paint.blend_mode_ordinal(),
color_filter_handle,
image_filter_handle,
mask_filter_handle,
)
}
}
///|
pub fn Canvas::restore(self : Canvas) -> Unit {
native_canvas_restore(self.handle)
}
///|
pub fn Canvas::restore_to_count(self : Canvas, count : Int) -> Unit {
native_canvas_restore_to_count(self.handle, count)
}
///|
pub fn Canvas::save_count(self : Canvas) -> Int {
native_canvas_save_count(self.handle)
}
///|
fn native_canvas_scalar_is_finite(value : Float) -> Bool {
value == value && value - value == 0.0
}
///|
fn native_canvas_paint_stroke_width(paint : @skia.Paint) -> Float {
if native_canvas_scalar_is_finite(paint.stroke_width) {
paint.stroke_width
} else {
0.0
}
}
///|
fn native_canvas_paint_stroke_miter(paint : @skia.Paint) -> Float {
if native_canvas_scalar_is_finite(paint.stroke_miter) {
paint.stroke_miter
} else {
4.0
}
}
///|
fn native_canvas_sampling_uses_cubic(sampling : @skia.SamplingOptions) -> Bool {
sampling.uses_cubic() &&
native_canvas_scalar_is_finite(sampling.cubic_b()) &&
native_canvas_scalar_is_finite(sampling.cubic_c())
}
///|
fn native_canvas_sampling_cubic_b(sampling : @skia.SamplingOptions) -> Float {
if native_canvas_sampling_uses_cubic(sampling) {
sampling.cubic_b()
} else {
0.0
}
}
///|
fn native_canvas_sampling_cubic_c(sampling : @skia.SamplingOptions) -> Float {
if native_canvas_sampling_uses_cubic(sampling) {
sampling.cubic_c()
} else {
0.0
}
}
///|
fn native_canvas_rrect_is_finite(rrect : @skia.RRect) -> Bool {
rrect.rect.is_finite() &&
rrect.upper_left.is_finite() &&
rrect.upper_right.is_finite() &&
rrect.lower_right.is_finite() &&
rrect.lower_left.is_finite()
}
///|
fn native_canvas_points_are_finite(points : Array[@skia.Point]) -> Bool {
let mut finite = true
for i = 0; i < points.length(); i = i + 1 {
if !points[i].is_finite() {
finite = false
}
}
finite
}
///|
pub fn Canvas::translate(self : Canvas, delta : @skia.Point) -> Unit {
if delta.is_finite() {
native_canvas_translate(self.handle, delta.x, delta.y)
}
}
///|
pub fn Canvas::scale(self : Canvas, scale : @skia.Size) -> Unit {
if scale.is_finite() {
native_canvas_scale(self.handle, scale.width, scale.height)
}
}
///|
pub fn Canvas::rotate(self : Canvas, degrees : Float) -> Unit {
if native_canvas_scalar_is_finite(degrees) {
native_canvas_rotate(self.handle, degrees)
}
}
///|
pub fn Canvas::skew(self : Canvas, skew : @skia.Point) -> Unit {
if skew.is_finite() {
native_canvas_skew(self.handle, skew.x, skew.y)
}
}
///|
pub fn Canvas::concat(self : Canvas, matrix : @skia.Matrix) -> Unit {
if matrix.is_finite() {
native_canvas_concat(
self.handle,
matrix.scale_x,
matrix.skew_x,
matrix.trans_x,
matrix.skew_y,
matrix.scale_y,
matrix.trans_y,
matrix.persp_0,
matrix.persp_1,
matrix.persp_2,
)
}
}
///|
pub fn Canvas::reset_matrix(self : Canvas) -> Unit {
native_canvas_reset_matrix(self.handle)
}
///|
pub fn Canvas::discard(self : Canvas) -> Unit {
native_canvas_discard(self.handle)
}
///|
pub fn Canvas::clip_rect(
self : Canvas,
rect : @skia.Rect,
op? : @skia.ClipOp = Intersect,
anti_alias? : Bool = false,
) -> Unit {
if rect.is_finite() {
native_canvas_clip_rect(
self.handle,
rect.left,
rect.top,
rect.right,
rect.bottom,
op.to_skia_ordinal(),
anti_alias,
)
}
}
///|
pub fn Canvas::clip_rrect(
self : Canvas,
rrect : @skia.RRect,
op? : @skia.ClipOp = Intersect,
anti_alias? : Bool = false,
) -> Unit {
if native_canvas_rrect_is_finite(rrect) {
native_canvas_clip_rrect(
self.handle,
rrect.rect.left,
rrect.rect.top,
rrect.rect.right,
rrect.rect.bottom,
rrect.upper_left.width,
rrect.upper_left.height,
rrect.upper_right.width,
rrect.upper_right.height,
rrect.lower_right.width,
rrect.lower_right.height,
rrect.lower_left.width,
rrect.lower_left.height,
op.to_skia_ordinal(),
anti_alias,
)
}
}
///|
pub fn Canvas::clip_path(
self : Canvas,
path : Path,
op? : @skia.ClipOp = Intersect,
anti_alias? : Bool = false,
) -> Unit {
native_canvas_clip_path(
self.handle,
path.handle,
op.to_skia_ordinal(),
anti_alias,
)
}
///|
pub fn Canvas::local_clip_bounds(self : Canvas) -> @skia.Rect? {
if native_canvas_local_clip_bounds(self.handle) {
Some(
@skia.Rect::new(
native_canvas_local_clip_bounds_left(self.handle),
native_canvas_local_clip_bounds_top(self.handle),
native_canvas_local_clip_bounds_right(self.handle),
native_canvas_local_clip_bounds_bottom(self.handle),
),
)
} else {
None
}
}
///|
pub fn Canvas::device_clip_bounds(self : Canvas) -> @skia.IRect? {
if native_canvas_device_clip_bounds(self.handle) {
Some(
@skia.IRect::new(
native_canvas_device_clip_bounds_left(self.handle),
native_canvas_device_clip_bounds_top(self.handle),
native_canvas_device_clip_bounds_right(self.handle),
native_canvas_device_clip_bounds_bottom(self.handle),
),
)
} else {
None
}
}
///|
pub fn Canvas::quick_reject_rect(self : Canvas, rect : @skia.Rect) -> Bool {
rect.is_finite() &&
native_canvas_quick_reject_rect(
self.handle,
rect.left,
rect.top,
rect.right,
rect.bottom,
)
}
///|
pub fn Canvas::quick_reject_path(self : Canvas, path : Path) -> Bool {
native_canvas_quick_reject_path(self.handle, path.handle)
}
///|
pub fn Canvas::draw_color(
self : Canvas,
color : @skia.Color,
blend_mode? : @skia.BlendMode = SrcOver,
) -> Unit {
native_canvas_draw_color(
self.handle,
color.argb(),
blend_mode.to_skia_ordinal(),
)
}
///|
pub fn Canvas::clear(self : Canvas, color : @skia.Color) -> Unit {
self.draw_color(color, blend_mode=Src)
}
///|
pub fn Canvas::draw_picture(self : Canvas, picture : Picture) -> Unit {
native_canvas_draw_picture(self.handle, picture.handle)
}
///|
pub fn Canvas::draw_paint(self : Canvas, paint : @skia.Paint) -> Unit {
native_canvas_draw_paint(
self.handle,
paint.color_argb(),
paint.anti_alias,
paint.dither,
paint.style_ordinal(),
native_canvas_paint_stroke_width(paint),
native_canvas_paint_stroke_miter(paint),
paint.stroke_cap_ordinal(),
paint.stroke_join_ordinal(),
paint.blend_mode_ordinal(),
)
}
///|
pub fn Canvas::draw_point(
self : Canvas,
point : @skia.Point,
paint : @skia.Paint,
) -> Unit {
if point.is_finite() {
native_canvas_draw_point(
self.handle,
point.x,
point.y,
paint.color_argb(),
paint.anti_alias,
paint.dither,
paint.style_ordinal(),
native_canvas_paint_stroke_width(paint),
native_canvas_paint_stroke_miter(paint),
paint.stroke_cap_ordinal(),
paint.stroke_join_ordinal(),
paint.blend_mode_ordinal(),
)
}
}
///|
pub fn Canvas::draw_line(
self : Canvas,
start : @skia.Point,
end : @skia.Point,
paint : @skia.Paint,
) -> Unit {
if start.is_finite() && end.is_finite() {
native_canvas_draw_line(
self.handle,
start.x,
start.y,
end.x,
end.y,
paint.color_argb(),
paint.anti_alias,
paint.dither,
paint.style_ordinal(),
native_canvas_paint_stroke_width(paint),
native_canvas_paint_stroke_miter(paint),
paint.stroke_cap_ordinal(),
paint.stroke_join_ordinal(),
paint.blend_mode_ordinal(),
)
}
}
///|
pub fn Canvas::draw_points(
self : Canvas,
points : Array[@skia.Point],
paint : @skia.Paint,
mode? : @skia.PointMode = Points,
) -> Unit {
match mode {
Points =>
for point in points {
self.draw_point(point, paint)
}
Lines =>
for i = 0; i + 1 < points.length(); i = i + 2 {
self.draw_line(points[i], points[i + 1], paint)
}
Polygon =>
for i = 0; i + 1 < points.length(); i = i + 1 {
self.draw_line(points[i], points[i + 1], paint)
}
}
}
///|
pub fn Canvas::draw_rect(
self : Canvas,
rect : @skia.Rect,
paint : @skia.Paint,
) -> Unit {
if rect.is_finite() {
native_canvas_draw_rect(
self.handle,
rect.left,
rect.top,
rect.right,
rect.bottom,
paint.color_argb(),
paint.anti_alias,
paint.dither,
paint.style_ordinal(),
native_canvas_paint_stroke_width(paint),
native_canvas_paint_stroke_miter(paint),
paint.stroke_cap_ordinal(),
paint.stroke_join_ordinal(),
paint.blend_mode_ordinal(),
)
}
}
///|
pub fn Canvas::draw_oval(
self : Canvas,
oval : @skia.Rect,
paint : @skia.Paint,
) -> Unit {
if oval.is_finite() {
native_canvas_draw_oval(
self.handle,
oval.left,
oval.top,
oval.right,
oval.bottom,
paint.color_argb(),
paint.anti_alias,
paint.dither,
paint.style_ordinal(),
native_canvas_paint_stroke_width(paint),
native_canvas_paint_stroke_miter(paint),
paint.stroke_cap_ordinal(),
paint.stroke_join_ordinal(),
paint.blend_mode_ordinal(),
)
}
}
///|
pub fn Canvas::draw_circle(
self : Canvas,
center : @skia.Point,
radius : Float,
paint : @skia.Paint,
) -> Unit {
if center.is_finite() &&
native_canvas_scalar_is_finite(radius) &&
radius > 0.0 {
native_canvas_draw_circle(
self.handle,
center.x,
center.y,
radius,
paint.color_argb(),
paint.anti_alias,
paint.dither,
paint.style_ordinal(),
native_canvas_paint_stroke_width(paint),
native_canvas_paint_stroke_miter(paint),
paint.stroke_cap_ordinal(),
paint.stroke_join_ordinal(),
paint.blend_mode_ordinal(),
)
}
}
///|
pub fn Canvas::draw_arc(
self : Canvas,
oval : @skia.Rect,
start_angle : Float,
sweep_angle : Float,
use_center : Bool,
paint : @skia.Paint,
) -> Unit {
if oval.is_finite() &&
native_canvas_scalar_is_finite(start_angle) &&
native_canvas_scalar_is_finite(sweep_angle) {
native_canvas_draw_arc(
self.handle,
oval.left,
oval.top,
oval.right,
oval.bottom,
start_angle,
sweep_angle,
use_center,
paint.color_argb(),
paint.anti_alias,
paint.dither,
paint.style_ordinal(),
native_canvas_paint_stroke_width(paint),
native_canvas_paint_stroke_miter(paint),
paint.stroke_cap_ordinal(),
paint.stroke_join_ordinal(),
paint.blend_mode_ordinal(),
)
}
}
///|
pub fn Canvas::draw_round_rect(
self : Canvas,
rect : @skia.Rect,
rx : Float,
ry : Float,
paint : @skia.Paint,
) -> Unit {
if rect.is_finite() &&
native_canvas_scalar_is_finite(rx) &&
native_canvas_scalar_is_finite(ry) {
native_canvas_draw_round_rect(
self.handle,
rect.left,
rect.top,
rect.right,
rect.bottom,
rx,
ry,
paint.color_argb(),
paint.anti_alias,
paint.dither,
paint.style_ordinal(),
native_canvas_paint_stroke_width(paint),
native_canvas_paint_stroke_miter(paint),
paint.stroke_cap_ordinal(),
paint.stroke_join_ordinal(),
paint.blend_mode_ordinal(),
)
}
}
///|
pub fn Canvas::draw_rrect(
self : Canvas,
rrect : @skia.RRect,
paint : @skia.Paint,
) -> Unit {
if native_canvas_rrect_is_finite(rrect) {
native_canvas_draw_rrect(
self.handle,
rrect.rect.left,
rrect.rect.top,
rrect.rect.right,
rrect.rect.bottom,
rrect.upper_left.width,
rrect.upper_left.height,
rrect.upper_right.width,
rrect.upper_right.height,
rrect.lower_right.width,
rrect.lower_right.height,
rrect.lower_left.width,
rrect.lower_left.height,
paint.color_argb(),
paint.anti_alias,
paint.dither,
paint.style_ordinal(),
native_canvas_paint_stroke_width(paint),
native_canvas_paint_stroke_miter(paint),
paint.stroke_cap_ordinal(),
paint.stroke_join_ordinal(),
paint.blend_mode_ordinal(),
)
}
}
///|
pub fn Canvas::draw_drrect(
self : Canvas,
outer : @skia.RRect,
inner : @skia.RRect,
paint : @skia.Paint,
) -> Unit {
if native_canvas_rrect_is_finite(outer) &&
native_canvas_rrect_is_finite(inner) {
native_canvas_draw_drrect(
self.handle,
outer.rect.left,
outer.rect.top,
outer.rect.right,
outer.rect.bottom,
outer.upper_left.width,
outer.upper_left.height,
outer.upper_right.width,
outer.upper_right.height,
outer.lower_right.width,
outer.lower_right.height,
outer.lower_left.width,
outer.lower_left.height,
inner.rect.left,
inner.rect.top,
inner.rect.right,
inner.rect.bottom,
inner.upper_left.width,
inner.upper_left.height,
inner.upper_right.width,
inner.upper_right.height,
inner.lower_right.width,
inner.lower_right.height,
inner.lower_left.width,
inner.lower_left.height,
paint.color_argb(),
paint.anti_alias,
paint.dither,
paint.style_ordinal(),
native_canvas_paint_stroke_width(paint),
native_canvas_paint_stroke_miter(paint),
paint.stroke_cap_ordinal(),
paint.stroke_join_ordinal(),
paint.blend_mode_ordinal(),
)
}
}
///|
pub fn Canvas::draw_path(
self : Canvas,
path : Path,
paint : @skia.Paint,
) -> Unit {
native_canvas_draw_path(
self.handle,
path.handle,
paint.color_argb(),
paint.anti_alias,
paint.dither,
paint.style_ordinal(),
native_canvas_paint_stroke_width(paint),
native_canvas_paint_stroke_miter(paint),
paint.stroke_cap_ordinal(),
paint.stroke_join_ordinal(),
paint.blend_mode_ordinal(),
)
}
///|
pub fn Canvas::draw_path_shader(
self : Canvas,
path : Path,
shader : Shader,
paint : @skia.Paint,
) -> Unit {
native_canvas_draw_path_shader(
self.handle,
path.handle,
shader.handle,
paint.color_argb(),
paint.anti_alias,
paint.dither,
paint.style_ordinal(),
native_canvas_paint_stroke_width(paint),
native_canvas_paint_stroke_miter(paint),
paint.stroke_cap_ordinal(),
paint.stroke_join_ordinal(),
paint.blend_mode_ordinal(),
)
}
///|
pub fn Canvas::draw_path_value(
self : Canvas,
path : @skia.Path,
paint : @skia.Paint,
) -> Unit {
match Path::from_value(path) {
None => ()
Some(native_path) => self.draw_path(native_path, paint)
}
}
///|
pub fn Canvas::draw_image(
self : Canvas,
image : Image,
top_left : @skia.Point,
) -> Unit {
if top_left.is_finite() {
native_canvas_draw_image(self.handle, image.handle, top_left.x, top_left.y)
}
}
///|
pub fn Canvas::draw_image_rect(
self : Canvas,
image : Image,
src : @skia.Rect,
dst : @skia.Rect,
paint : @skia.Paint,
sampling? : @skia.SamplingOptions = @skia.SamplingOptions::new(),
) -> Unit {
if src.is_finite() && dst.is_finite() {
native_canvas_draw_image_rect(
self.handle,
image.handle,
src.left,
src.top,
src.right,
src.bottom,
dst.left,
dst.top,
dst.right,
dst.bottom,
paint.color_argb(),
paint.anti_alias,
paint.dither,
paint.style_ordinal(),
native_canvas_paint_stroke_width(paint),
native_canvas_paint_stroke_miter(paint),
paint.stroke_cap_ordinal(),
paint.stroke_join_ordinal(),
paint.blend_mode_ordinal(),
sampling.filter_ordinal(),
sampling.mipmap_ordinal(),
native_canvas_sampling_uses_cubic(sampling),
native_canvas_sampling_cubic_b(sampling),
native_canvas_sampling_cubic_c(sampling),
)
}
}
///|
pub fn Canvas::draw_paint_shader(
self : Canvas,
shader : Shader,
paint : @skia.Paint,
) -> Unit {
native_canvas_draw_paint_shader(
self.handle,
shader.handle,
paint.color_argb(),
paint.anti_alias,
paint.dither,
paint.style_ordinal(),
native_canvas_paint_stroke_width(paint),
native_canvas_paint_stroke_miter(paint),
paint.stroke_cap_ordinal(),
paint.stroke_join_ordinal(),
paint.blend_mode_ordinal(),
)
}
///|
pub fn Canvas::draw_rect_shader(
self : Canvas,
rect : @skia.Rect,
shader : Shader,
paint : @skia.Paint,
) -> Unit {
if rect.is_finite() {
native_canvas_draw_rect_shader(
self.handle,
shader.handle,
rect.left,
rect.top,
rect.right,
rect.bottom,
paint.color_argb(),
paint.anti_alias,
paint.dither,
paint.style_ordinal(),
native_canvas_paint_stroke_width(paint),
native_canvas_paint_stroke_miter(paint),
paint.stroke_cap_ordinal(),
paint.stroke_join_ordinal(),
paint.blend_mode_ordinal(),
)
}
}
///|
pub fn Canvas::draw_round_rect_shader(
self : Canvas,
rect : @skia.Rect,
rx : Float,
ry : Float,
shader : Shader,
paint : @skia.Paint,
) -> Unit {
if rect.is_finite() &&
native_canvas_scalar_is_finite(rx) &&
native_canvas_scalar_is_finite(ry) {
native_canvas_draw_round_rect_shader(
self.handle,
shader.handle,
rect.left,
rect.top,
rect.right,
rect.bottom,
rx,
ry,
paint.color_argb(),
paint.anti_alias,
paint.dither,
paint.style_ordinal(),
native_canvas_paint_stroke_width(paint),
native_canvas_paint_stroke_miter(paint),
paint.stroke_cap_ordinal(),
paint.stroke_join_ordinal(),
paint.blend_mode_ordinal(),
)
}
}
///|
pub fn Canvas::draw_text_utf8(
self : Canvas,
text : Bytes,
origin : @skia.Point,
font : Font,
paint : @skia.Paint,
) -> Unit {
if !text.is_empty() && origin.is_finite() {
native_canvas_draw_text_utf8(
self.handle,
text,
origin.x,
origin.y,
font.handle,
paint.color_argb(),
paint.anti_alias,
paint.dither,
paint.style_ordinal(),
native_canvas_paint_stroke_width(paint),
native_canvas_paint_stroke_miter(paint),
paint.stroke_cap_ordinal(),
paint.stroke_join_ordinal(),
paint.blend_mode_ordinal(),
)
}
}
///|
fn native_canvas_glyph_id_bytes(glyphs : Array[GlyphId]) -> Bytes {
let bytes : Array[Byte] = Array::new(capacity=glyphs.length() * 2)
for glyph in glyphs {
let value = glyph.to_uint16()
bytes.push(value.shr(8).to_byte())
bytes.push(value.to_byte())
}
Bytes::from_array(bytes)
}
///|
fn native_canvas_glyph_position_bytes(positions : Array[@skia.Point]) -> Bytes {
let bytes : Array[Byte] = Array::new(capacity=positions.length() * 8)
for position in positions {
for byte in position.x.to_be_bytes() {
bytes.push(byte)
}
for byte in position.y.to_be_bytes() {
bytes.push(byte)
}
}
Bytes::from_array(bytes)
}
///|
fn native_canvas_glyphs_have_visible_payload(glyphs : Array[GlyphId]) -> Bool {
for glyph in glyphs {
if glyph.to_int() != 0 {
return true
}
}
false
}
///|
pub fn Canvas::draw_glyphs_checked(
self : Canvas,
glyphs : Array[GlyphId],
positions : Array[@skia.Point],
font : Font,
paint : @skia.Paint,
origin? : @skia.Point = @skia.Point::zero(),
) -> Bool {
if glyphs.is_empty() ||
glyphs.length() != positions.length() ||
!native_canvas_glyphs_have_visible_payload(glyphs) ||
!origin.is_finite() ||
!native_canvas_points_are_finite(positions) {
return false
}
let glyph_bytes = native_canvas_glyph_id_bytes(glyphs)
let position_bytes = native_canvas_glyph_position_bytes(positions)
native_canvas_draw_glyphs(
self.handle,
glyph_bytes,
position_bytes,
glyphs.length(),
origin.x,
origin.y,
font.handle,
paint.color_argb(),
paint.anti_alias,
paint.dither,
paint.style_ordinal(),
native_canvas_paint_stroke_width(paint),
native_canvas_paint_stroke_miter(paint),
paint.stroke_cap_ordinal(),
paint.stroke_join_ordinal(),
paint.blend_mode_ordinal(),
)
}
///|
pub fn Canvas::draw_glyphs(
self : Canvas,
glyphs : Array[GlyphId],
positions : Array[@skia.Point],
font : Font,
paint : @skia.Paint,
origin? : @skia.Point = @skia.Point::zero(),
) -> Unit {
ignore(self.draw_glyphs_checked(glyphs, positions, font, paint, origin~))
}
///|
fn Canvas::replay_text_utf8(
self : Canvas,
text : Bytes,
origin : @skia.Point,
paint : @skia.Paint,
font : Font?,
) -> Bool {
let font = match font {
Some(font) => Some(font)
None => Font::default()
}
match font {
None => false
Some(font) => {
self.draw_text_utf8(text, origin, font, paint)
true
}
}
}
///|
fn native_replay_font(font : Font?) -> Font? {
match font {
Some(font) => Some(font)
None => Font::default()
}
}
///|
fn native_replay_font_from_resources(
font_key : @skia.RendererResourceKey,
font : Font?,
resources : NativeReplayResources?,
) -> Font? {
if font_key.kind != FontResource || font_key.is_empty() {
native_replay_font(font)
} else {
match resources {
None => native_replay_font(font)
Some(resources) =>
match resources.font_cache.get(font_key) {
Some(font) => Some(font)
None =>
match native_replay_font(font) {
None => None
Some(font) => {
ignore(resources.font_cache.insert(font_key, font))
Some(font)
}
}
}
}
}
}
///|
fn native_replay_typeface_from_resources(
request : @skia.FontFallbackRequest,
resources : NativeReplayResources?,
) -> Typeface? {
let key = request.resource_key()
if request.is_empty() || key.kind != TypefaceResource || key.is_empty() {
None
} else {
match resources {
None =>
match FontMgr::default() {
None => None
Some(font_mgr) => font_mgr.match_fallback_request(request)
}
Some(resources) =>
match resources.typeface_cache.get(key) {
Some(typeface) => Some(typeface)
None =>
match FontMgr::default() {
None => None
Some(font_mgr) =>
match font_mgr.match_fallback_request(request) {
None => None
Some(typeface) => {
ignore(
resources.typeface_cache.insert(
key,
typeface,
byte_size=request.resource_descriptor().byte_size,
),
)
Some(typeface)
}
}
}
}
}
}
}
///|
fn shaped_glyph_run_native_glyph_ids(
glyph_run : @skia.ShapedGlyphRunDescriptor,
) -> Array[GlyphId] {
let glyphs : Array[GlyphId] = Array::new(
capacity=glyph_run.glyph_ids.length(),
)
for glyph_id in glyph_run.glyph_ids {
glyphs.push(GlyphId::new(glyph_id.clamp(min=0, max=65535).to_uint16()))
}
glyphs
}
///|
fn native_text_run_from_resources(
text : Bytes,
descriptor : @skia.TextRunDescriptor,
font_key : @skia.RendererResourceKey,
font : Font,
resources : NativeReplayResources?,
) -> NativeReplayTextRun {
let key = descriptor.resource_key(text, font_key~)
let shaping = @skia.TextShapingDescriptor::new(run=descriptor, font_key~)
match resources {
None =>
match font.shape_text_run_utf8(text, shaping) {
None => DirectTextRun(descriptor)
Some(glyph_run) => ShapedTextRun(glyph_run)
}
Some(resources) =>
match resources.text_run_cache.get(key) {
Some(replay_text_run) => replay_text_run
None => {
let replay_text_run = match font.shape_text_run_utf8(text, shaping) {
None => DirectTextRun(descriptor)
Some(glyph_run) => ShapedTextRun(glyph_run)
}
ignore(
resources.text_run_cache.insert(
key,
replay_text_run,
byte_size=descriptor.resource_descriptor(text, font_key~).byte_size,
),
)
replay_text_run
}
}
}
}
///|
fn Canvas::replay_text_run_utf8(
self : Canvas,
text : Bytes,
descriptor : @skia.TextRunDescriptor,
font_key : @skia.RendererResourceKey,
origin : @skia.Point,
paint : @skia.Paint,
font : Font?,
resources : NativeReplayResources?,
) -> Bool {
let run_text = text_run_bytes_for_shaping(text, descriptor)
if run_text.is_empty() || descriptor.is_empty() {
false
} else {
ignore(
native_replay_typeface_from_resources(descriptor.fallback, resources),
)
match native_replay_font_from_resources(font_key, font, resources) {
None => false
Some(font) =>
match
native_text_run_from_resources(
text, descriptor, font_key, font, resources,
) {
DirectTextRun(_) => {
self.draw_text_utf8(run_text, origin, font, paint)
true
}
ShapedTextRun(glyph_run) =>
if self.replay_shaped_glyph_run_utf8(
glyph_run,
origin,
paint,
Some(font),
) {
true
} else {
self.draw_text_utf8(run_text, origin, font, paint)
true
}
}
}
}
}
///|
fn Canvas::replay_shaped_glyph_run_utf8(
self : Canvas,
glyph_run : @skia.ShapedGlyphRunDescriptor,
origin : @skia.Point,
paint : @skia.Paint,
font : Font?,
) -> Bool {
let font = match font {
Some(font) => Some(font)
None => Font::default()
}
match font {
None => false
Some(font) =>
if !glyph_run.is_valid() {
false
} else {
self.draw_glyphs_checked(
shaped_glyph_run_native_glyph_ids(glyph_run),
glyph_run.positions,
font,
paint,
origin~,
)
}
}
}
///|
fn native_path_from_value(
path : @skia.Path,
resources : NativeReplayResources?,
) -> Path? {
if !path.is_finite() {
None
} else {
match resources {
None => Path::from_value(path)
Some(resources) => {
let descriptor = path.resource_descriptor()
if !descriptor.is_cacheable() {
Path::from_value(path)
} else {
match resources.path_cache.get(descriptor.key) {
Some(native_path) => Some(native_path)
None =>
match Path::from_value(path) {
None => None
Some(native_path) => {
ignore(
resources.path_cache.insert(
descriptor.key,
native_path,
byte_size=descriptor.byte_size,
),
)
Some(native_path)
}
}
}
}
}
}
}
}
///|
fn Canvas::replay_path_value(
self : Canvas,
path : @skia.Path,
paint : @skia.Paint,
resources : NativeReplayResources?,
) -> Bool {
match native_path_from_value(path, resources) {
None => false
Some(native_path) => {
self.draw_path(native_path, paint)
true
}
}
}
///|
fn Canvas::replay_clip_path(
self : Canvas,
path : @skia.Path,
op : @skia.ClipOp,
resources : NativeReplayResources?,
) -> Bool {
match native_path_from_value(path, resources) {
None => false
Some(native_path) => {
self.clip_path(native_path, op~)
true
}
}
}
///|
fn native_shader_from_descriptor(
descriptor : @skia.ShaderDescriptor,
) -> Shader? {
match descriptor {
ColorShader(color) => Shader::color(color)
LinearGradientShader(start, end, start_color, end_color, tile_mode) =>
Shader::linear_gradient(start, end, start_color, end_color, tile_mode~)
RadialGradientShader(center, radius, inner_color, outer_color, tile_mode) =>
Shader::radial_gradient(
center,
radius,
inner_color,
outer_color,
tile_mode~,
)
}
}
///|
fn native_shader_from_resources(
descriptor : @skia.ShaderDescriptor,
resources : NativeReplayResources?,
) -> Shader? {
let key = descriptor.resource_key()
if key.is_empty() || !descriptor.is_valid() {
native_shader_from_descriptor(descriptor)
} else {
match resources {
None => native_shader_from_descriptor(descriptor)
Some(resources) =>
match resources.shader_cache.get(key) {
Some(shader) => Some(shader)
None =>
match native_shader_from_descriptor(descriptor) {
None => None
Some(shader) => {
ignore(
resources.shader_cache.insert(
key,
shader,
byte_size=descriptor.resource_descriptor().byte_size,
),
)
Some(shader)
}
}
}
}
}
}
///|
fn Canvas::replay_paint_shader(
self : Canvas,
shader_descriptor : @skia.ShaderDescriptor,
paint : @skia.Paint,
resources : NativeReplayResources?,
) -> Bool {
match native_shader_from_resources(shader_descriptor, resources) {
None => false
Some(shader) => {
self.draw_paint_shader(shader, paint)
true
}
}
}
///|
fn Canvas::replay_rect_shader(
self : Canvas,
rect : @skia.Rect,
shader_descriptor : @skia.ShaderDescriptor,
paint : @skia.Paint,
resources : NativeReplayResources?,
) -> Bool {
match native_shader_from_resources(shader_descriptor, resources) {
None => false
Some(shader) => {
self.draw_rect_shader(rect, shader, paint)
true
}
}
}
///|
fn Canvas::replay_round_rect_shader(
self : Canvas,
rect : @skia.Rect,
rx : Float,
ry : Float,
shader_descriptor : @skia.ShaderDescriptor,
paint : @skia.Paint,
resources : NativeReplayResources?,
) -> Bool {
match native_shader_from_resources(shader_descriptor, resources) {
None => false
Some(shader) => {
self.draw_round_rect_shader(rect, rx, ry, shader, paint)
true
}
}
}
///|
fn Canvas::replay_path_shader(
self : Canvas,
path : @skia.Path,
shader_descriptor : @skia.ShaderDescriptor,
paint : @skia.Paint,
resources : NativeReplayResources?,
) -> Bool {
match native_path_from_value(path, resources) {
None => false
Some(native_path) =>
match native_shader_from_resources(shader_descriptor, resources) {
None => false
Some(shader) => {
self.draw_path_shader(native_path, shader, paint)
true
}
}
}
}
///|
fn native_image_decode_descriptor(descriptor : @skia.ImageDescriptor) -> Image? {
match descriptor {
EncodedImage(bytes, _, _) => Image::from_encoded_bytes(bytes)
}
}
///|
fn native_image_from_descriptor(
descriptor : @skia.ImageDescriptor,
resources : NativeReplayResources?,
) -> Image? {
let key = descriptor.resource_key()
if key.is_empty() {
native_image_decode_descriptor(descriptor)
} else {
match resources {
None => native_image_decode_descriptor(descriptor)
Some(resources) =>
match resources.image_cache.get(key) {
Some(image) => Some(image)
None =>
match native_image_decode_descriptor(descriptor) {
None => None
Some(image) => {
ignore(
resources.image_cache.insert(
key,
image,
byte_size=descriptor.byte_size(),
),
)
Some(image)
}
}
}
}
}
}
///|
fn Canvas::replay_image(
self : Canvas,
descriptor : @skia.ImageDescriptor,
top_left : @skia.Point,
resources : NativeReplayResources?,
) -> Bool {
match native_image_from_descriptor(descriptor, resources) {
None => false
Some(image) => {
self.draw_image(image, top_left)
true
}
}
}
///|
fn Canvas::replay_image_rect(
self : Canvas,
descriptor : @skia.ImageDescriptor,
src : @skia.Rect,
dst : @skia.Rect,
paint : @skia.Paint,
sampling : @skia.SamplingOptions,
resources : NativeReplayResources?,
) -> Bool {
match native_image_from_descriptor(descriptor, resources) {
None => false
Some(image) => {
self.draw_image_rect(image, src, dst, paint, sampling~)
true
}
}
}
///|
fn native_color_filter_from_descriptor(
descriptor : @skia.ColorFilterDescriptor,
) -> ColorFilter? {
match descriptor {
ColorMatrixFilter(values) => ColorFilter::matrix(values)
SaturationFilter(amount) => ColorFilter::saturation(amount)
BrightnessFilter(amount) => ColorFilter::brightness(amount)
ContrastFilter(amount) => ColorFilter::contrast(amount)
}
}
///|
fn native_color_filter_from_resources(
descriptor : @skia.ColorFilterDescriptor,
resources : NativeReplayResources?,
) -> ColorFilter? {
let key = descriptor.resource_key()
if key.is_empty() || !descriptor.is_valid() {
native_color_filter_from_descriptor(descriptor)
} else {
match resources {
None => native_color_filter_from_descriptor(descriptor)
Some(resources) =>
match resources.color_filter_cache.get(key) {
Some(filter) => Some(filter)
None =>
match native_color_filter_from_descriptor(descriptor) {
None => None
Some(filter) => {
ignore(
resources.color_filter_cache.insert(
key,
filter,
byte_size=descriptor.resource_descriptor().byte_size,
),
)
Some(filter)
}
}
}
}
}
}
///|
fn native_image_filter_from_descriptor(
descriptor : @skia.ImageFilterDescriptor,
) -> ImageFilter? {
match descriptor {
BlurImageFilter(sigma_x, sigma_y) => ImageFilter::blur(sigma_x, sigma_y)
}
}
///|
fn native_image_filter_from_resources(
descriptor : @skia.ImageFilterDescriptor,
resources : NativeReplayResources?,
) -> ImageFilter? {
let key = descriptor.resource_key()
if key.is_empty() || !descriptor.is_valid() {
native_image_filter_from_descriptor(descriptor)
} else {
match resources {
None => native_image_filter_from_descriptor(descriptor)
Some(resources) =>
match resources.image_filter_cache.get(key) {
Some(filter) => Some(filter)
None =>
match native_image_filter_from_descriptor(descriptor) {
None => None
Some(filter) => {
ignore(
resources.image_filter_cache.insert(
key,
filter,
byte_size=descriptor.resource_descriptor().byte_size,
),
)
Some(filter)
}
}
}
}
}
}
///|
fn native_mask_filter_from_descriptor(
descriptor : @skia.MaskFilterDescriptor,
) -> MaskFilter? {
match descriptor {
BlurMaskFilter(sigma) => MaskFilter::blur(sigma)
}
}
///|
fn native_mask_filter_from_resources(
descriptor : @skia.MaskFilterDescriptor,
resources : NativeReplayResources?,
) -> MaskFilter? {
let key = descriptor.resource_key()
if key.is_empty() || !descriptor.is_valid() {
native_mask_filter_from_descriptor(descriptor)
} else {
match resources {
None => native_mask_filter_from_descriptor(descriptor)
Some(resources) =>
match resources.mask_filter_cache.get(key) {
Some(filter) => Some(filter)
None =>
match native_mask_filter_from_descriptor(descriptor) {
None => None
Some(filter) => {
ignore(
resources.mask_filter_cache.insert(
key,
filter,
byte_size=descriptor.resource_descriptor().byte_size,
),
)
Some(filter)
}
}
}
}
}
}
///|
fn Canvas::replay_save_layer(
self : Canvas,
bounds : @skia.Rect?,
paint : @skia.Paint,
color_filter : @skia.ColorFilterDescriptor?,
image_filter : @skia.ImageFilterDescriptor?,
mask_filter : @skia.MaskFilterDescriptor?,
resources : NativeReplayResources?,
) -> Bool {
let mut failed = false
let mut color_filter_handle : ColorFilter? = None
match color_filter {
None => ()
Some(descriptor) =>
match native_color_filter_from_resources(descriptor, resources) {
None => failed = true
Some(filter) => color_filter_handle = Some(filter)
}
}
let mut image_filter_handle : ImageFilter? = None
match image_filter {
None => ()
Some(descriptor) =>
match native_image_filter_from_resources(descriptor, resources) {
None => failed = true
Some(filter) => image_filter_handle = Some(filter)
}
}
let mut mask_filter_handle : MaskFilter? = None
match mask_filter {
None => ()
Some(descriptor) =>
match native_mask_filter_from_resources(descriptor, resources) {
None => failed = true
Some(filter) => mask_filter_handle = Some(filter)
}
}
if failed {
false
} else {
self.save_layer(
bounds~,
paint~,
color_filter=color_filter_handle,
image_filter=image_filter_handle,
mask_filter=mask_filter_handle,
) >
0
}
}
///|
fn Canvas::replay_command(
self : Canvas,
command : @skia.RenderCommand,
font : Font?,
resources : NativeReplayResources?,
) -> Bool {
match command {
SaveCanvas => {
ignore(self.save())
true
}
RestoreCanvas => {
self.restore()
true
}
SaveCanvasLayer(bounds, paint, color_filter, image_filter, mask_filter) =>
self.replay_save_layer(
bounds, paint, color_filter, image_filter, mask_filter, resources,
)
TranslateCanvas(delta) => {
self.translate(delta)
true
}
ScaleCanvas(scale) => {
self.scale(scale)
true
}
RotateCanvas(degrees) => {
self.rotate(degrees)
true
}
SkewCanvas(skew) => {
self.skew(skew)
true
}
ConcatCanvas(matrix) => {
self.concat(matrix)
true
}
ResetCanvasMatrix => {
self.reset_matrix()
true
}
ClearCanvas(color) => {
self.clear(color)
true
}
DrawCanvasColor(color, blend_mode) => {
self.draw_color(color, blend_mode~)
true
}
DrawCanvasPaint(paint) => {
self.draw_paint(paint)
true
}
DrawCanvasPaintShader(shader_descriptor, paint) =>
self.replay_paint_shader(shader_descriptor, paint, resources)
ClipCanvasRect(rect, op) => {
self.clip_rect(rect, op~)
true
}
ClipCanvasRRect(rrect, op) => {
self.clip_rrect(rrect, op~)
true
}
ClipCanvasPath(path, op) => self.replay_clip_path(path, op, resources)
DrawCanvasPoint(point, paint) => {
self.draw_point(point, paint)
true
}
DrawCanvasLine(start, end, paint) => {
self.draw_line(start, end, paint)
true
}
DrawCanvasPoints(points, mode, paint) => {
self.draw_points(points, paint, mode~)
true
}
DrawCanvasRect(rect, paint) => {
self.draw_rect(rect, paint)
true
}
DrawCanvasOval(oval, paint) => {
self.draw_oval(oval, paint)
true
}
DrawCanvasCircle(center, radius, paint) => {
self.draw_circle(center, radius, paint)
true
}
DrawCanvasArc(oval, start_angle, sweep_angle, use_center, paint) => {
self.draw_arc(oval, start_angle, sweep_angle, use_center, paint)
true
}
DrawCanvasRoundRect(rect, rx, ry, paint) => {
self.draw_round_rect(rect, rx, ry, paint)
true
}
DrawCanvasRRect(rrect, paint) => {
self.draw_rrect(rrect, paint)
true
}
DrawCanvasDRRect(outer, inner, paint) => {
self.draw_drrect(outer, inner, paint)
true
}
DrawCanvasRectShader(rect, shader_descriptor, paint) =>
self.replay_rect_shader(rect, shader_descriptor, paint, resources)
DrawCanvasRoundRectShader(rect, rx, ry, shader_descriptor, paint) =>
self.replay_round_rect_shader(
rect, rx, ry, shader_descriptor, paint, resources,
)
DrawCanvasPath(path, paint) =>
self.replay_path_value(path, paint, resources)
DrawCanvasPathShader(path, shader_descriptor, paint) =>
self.replay_path_shader(path, shader_descriptor, paint, resources)
DrawCanvasImage(image_descriptor, top_left) =>
self.replay_image(image_descriptor, top_left, resources)
DrawCanvasImageRect(image_descriptor, src, dst, paint, sampling) =>
self.replay_image_rect(
image_descriptor, src, dst, paint, sampling, resources,
)
DrawCanvasTextUtf8(text, origin, paint) =>
self.replay_text_utf8(text, origin, paint, font)
DrawCanvasTextRunUtf8(text, descriptor, font_key, origin, paint) =>
self.replay_text_run_utf8(
text, descriptor, font_key, origin, paint, font, resources,
)
DrawCanvasShapedGlyphRunUtf8(_, glyph_run, origin, paint) =>
self.replay_shaped_glyph_run_utf8(glyph_run, origin, paint, font)
DeclareRenderResource(_) => true
PresentSurface => false
}
}
///|
fn Canvas::replay_internal(
self : Canvas,
commands : @skia.RenderCommandList,
font : Font?,
resources : NativeReplayResources?,
) -> CanvasReplayStats {
let mut command_count = 0
let mut replayed_count = 0
let mut skipped_count = 0
let mut draw_count = 0
let mut state_count = 0
let mut transform_count = 0
let mut clip_count = 0
let mut clear_count = 0
let mut text_count = 0
let mut present_count = 0
let mut resource_declaration_count = 0
let mut image_resource_count = 0
let mut shader_resource_count = 0
let mut filter_resource_count = 0
let mut path_resource_count = 0
let mut text_resource_count = 0
for command in commands.commands {
command_count += 1
if command.is_draw() {
draw_count += 1
}
if command.is_state() {
state_count += 1
}
if command.is_transform() {
transform_count += 1
}
if command.is_clip() {
clip_count += 1
}
if command.is_clear() {
clear_count += 1
}
if command.is_text() {
text_count += 1
}
if command.is_resource_declaration() {
resource_declaration_count += 1
}
let resource_counts = canvas_replay_command_resource_counts(command)
image_resource_count += resource_counts.image_resource_count
shader_resource_count += resource_counts.shader_resource_count
filter_resource_count += resource_counts.filter_resource_count
path_resource_count += resource_counts.path_resource_count
text_resource_count += resource_counts.text_resource_count
if command.is_present() {
present_count += 1
}
if self.replay_command(command, font, resources) {
replayed_count += 1
} else if !command.is_present() {
skipped_count += 1
}
}
{
command_count,
replayed_count,
skipped_count,
draw_count,
state_count,
transform_count,
clip_count,
clear_count,
text_count,
present_count,
resource_declaration_count,
image_resource_count,
shader_resource_count,
filter_resource_count,
path_resource_count,
text_resource_count,
}
}
///|
fn Canvas::replay_frame_internal(
self : Canvas,
frame : @skia.RenderFrameDescriptor,
font : Font?,
resources : NativeReplayResources?,
) -> CanvasReplayStats {
if frame.is_ready() {
self.replay_internal(frame.command_list, font, resources)
} else {
canvas_replay_skipped_stats(frame.command_list)
}
}
///|
/// Replay the CPU Canvas subset of a value-layer render command list.
pub fn Canvas::replay(
self : Canvas,
commands : @skia.RenderCommandList,
font? : Font? = None,
) -> CanvasReplayStats {
self.replay_internal(commands, font, None)
}
///|
/// Replay a ready render frame, preserving frame validation as the native boundary.
pub fn Canvas::replay_frame(
self : Canvas,
frame : @skia.RenderFrameDescriptor,
font? : Font? = None,
) -> CanvasReplayStats {
self.replay_frame_internal(frame, font, None)
}
///|
/// Replay render commands while reusing decoded native resources by key.
pub fn Canvas::replay_with_resources(
self : Canvas,
commands : @skia.RenderCommandList,
resources : NativeReplayResources,
font? : Font? = None,
) -> CanvasReplayStats {
self.replay_internal(commands, font, Some(resources))
}
///|
/// Replay a ready render frame while reusing native resources by key.
pub fn Canvas::replay_frame_with_resources(
self : Canvas,
frame : @skia.RenderFrameDescriptor,
resources : NativeReplayResources,
font? : Font? = None,
) -> CanvasReplayStats {
self.replay_frame_internal(frame, font, Some(resources))
}
///|
/// Replay render commands while reusing decoded native images by resource key.
pub fn Canvas::replay_with_image_cache(
self : Canvas,
commands : @skia.RenderCommandList,
image_cache : @skia.ResourceCache[@skia.RendererResourceKey, Image],
font? : Font? = None,
) -> CanvasReplayStats {
self.replay_with_resources(
commands,
{
image_cache,
shader_cache: @skia.ResourceCache::new(),
path_cache: @skia.ResourceCache::new(),
text_run_cache: @skia.ResourceCache::new(),
font_cache: @skia.ResourceCache::new(),
typeface_cache: @skia.ResourceCache::new(),
color_filter_cache: @skia.ResourceCache::new(),
image_filter_cache: @skia.ResourceCache::new(),
mask_filter_cache: @skia.ResourceCache::new(),
},
font~,
)
}