Packages

Elixir drawing API backed by a batched Rustler Skia renderer

Retired package: Release invalid - Package metadata includes development-only generator modules; use 0.3.2 or later

Current section

Files

Jump to
skia native skia_native src generated_text.rs
Raw

native/skia_native/src/generated_text.rs

// Generated by mix skia.codegen. Do not edit by hand.
fn draw_text_blob<'a>(canvas: &skia_safe::Canvas, command: Term<'a>) -> NifResult<()> {
let args = decode_args(command)?;
let opts = decode_opts(command)?;
let decoded_opts = generated_opts::decode_text_blob_opts(&opts)?;
draw_text_blob_impl(canvas, args, decoded_opts, &opts)
}
fn draw_text_blob_impl<'a>(
canvas: &skia_safe::Canvas,
args: Vec<Term<'a>>,
opts: generated_opts::TextBlobOpts<'a>,
raw_opts: &[(Atom, Term<'a>)],
) -> NifResult<()> {
let blob = text_blob_from_term(*args.first().ok_or(rustler::Error::BadArg)?)?;
let mut paint = match opts.fill {
Some(term) => decode_paint(term)?,
None => fill_paint(Color::BLACK),
};
apply_paint_effects(&mut paint, raw_opts)?;
canvas.draw_text_blob(blob, (opts.x, opts.y), &paint);
Ok(())
}
fn draw_text<'a>(canvas: &skia_safe::Canvas, command: Term<'a>) -> NifResult<()> {
let args = decode_args(command)?;
let opts = decode_opts(command)?;
let decoded_opts = generated_opts::decode_text_opts(&opts)?;
draw_text_impl(canvas, args, decoded_opts, &opts)
}
fn draw_text_impl<'a>(
canvas: &skia_safe::Canvas,
args: Vec<Term<'a>>,
opts: generated_opts::TextOpts<'a>,
_raw_opts: &[(Atom, Term<'a>)],
) -> NifResult<()> {
let text = args.first().ok_or(rustler::Error::BadArg)?.decode::<String>()?;
let size = opts.size.unwrap_or(16.0);
let mut font = match opts.font {
Some(term) => font_from_term(term, size)?,
None => Font::default(),
};
font.set_size(size);
let paint = match opts.fill {
Some(term) => fill_paint(decode_color(term)?),
None => fill_paint(Color::BLACK),
};
match opts.width {
Some(width) => {
draw_paragraph_text(
canvas,
&text,
opts.x,
opts.y,
width,
size,
&paint,
&opts,
)?;
}
None => {
canvas.draw_str(text, (opts.x, opts.y), &font, &paint);
}
};
Ok(())
}
fn draw_paragraph_text<'a>(
canvas: &skia_safe::Canvas,
text: &str,
x: f32,
y: f32,
width: f32,
size: f32,
paint: &Paint,
opts: &generated_opts::TextOpts<'a>,
) -> NifResult<()> {
let mut text_style = TextStyle::new();
text_style.set_font_size(size);
text_style.set_color(paint.color());
if let Some(family) = &opts.font_family {
text_style.set_font_families(&vec![family]);
}
if let Some(line_height) = opts.line_height {
text_style.set_height(line_height / size);
text_style.set_height_override(true);
}
let mut paragraph_style = ParagraphStyle::new();
paragraph_style.set_text_style(&text_style);
if let Some(align) = opts.align {
paragraph_style.set_text_align(decode_text_align(align)?);
}
if let Some(direction) = opts.direction {
paragraph_style.set_text_direction(decode_text_direction(direction)?);
}
let mut font_collection = FontCollection::new();
font_collection.set_default_font_manager(FontMgr::default(), None);
let mut paragraph_builder = ParagraphBuilder::new(&paragraph_style, font_collection);
match opts.spans {
Some(spans_term) => {
let spans = spans_term.decode::<Vec<(String, Vec<(Atom, Term<'a>)>)>>()?;
for (span_text, style_opts) in spans {
let span_style = text_style_from_opts(&text_style, &style_opts)?;
paragraph_builder.push_style(&span_style);
paragraph_builder.add_text(span_text);
paragraph_builder.pop();
}
}
None => {
paragraph_builder.push_style(&text_style);
paragraph_builder.add_text(text);
paragraph_builder.pop();
}
};
let mut paragraph = paragraph_builder.build();
paragraph.layout(width);
paragraph.paint(canvas, Point::new(x, y));
Ok(())
}
fn text_style_from_opts<'a>(
base: &TextStyle,
opts: &[(Atom, Term<'a>)],
) -> NifResult<TextStyle> {
let mut style = base.clone();
if let Some(size) = opt_f32_option(opts, atoms::size())? {
style.set_font_size(size);
}
if let Some(fill) = opt_term(opts, atoms::fill()) {
style.set_color(decode_color(fill)?);
}
if let Some(term) = opt_term(opts, atoms::font_family()) {
let family = term.decode::<String>()?;
style.set_font_families(&vec![family]);
}
if let Some(line_height) = opt_f32_option(opts, atoms::line_height())? {
let font_size = opt_f32_option(opts, atoms::size())?.unwrap_or(base.font_size());
style.set_height(line_height / font_size);
style.set_height_override(true);
}
Ok(style)
}
fn decode_text_align(value: Atom) -> NifResult<TextAlign> {
match value {
value if value == atoms::center() => Ok(TextAlign::Center),
value if value == atoms::right() => Ok(TextAlign::Right),
value if value == atoms::justify() => Ok(TextAlign::Justify),
value if value == atoms::left() => Ok(TextAlign::Left),
_ => Err(rustler::Error::BadArg),
}
}
fn decode_text_direction(value: Atom) -> NifResult<TextDirection> {
match value {
value if value == atoms::rtl() => Ok(TextDirection::RTL),
value if value == atoms::ltr() => Ok(TextDirection::LTR),
_ => Err(rustler::Error::BadArg),
}
}