//! This example shows how to use `simple_text` API to draw simple text in a single line. It //! also demonstrates how you can use non-default variation coordinates. //! //! Note that simple text in this case does not mean that complex scripts aren't supported //! (they are, including RTL text!), but the text itself must not contain mixed scripts. And //! the font must contain all necessary glyphs, otherwise the `.notdef` glyph will be emitted //! instead of font fallback. use std::path; use std::path::PathBuf; use std::sync::{Arc, LazyLock}; use krilla::color::rgb; use krilla::geom::Point; use krilla::num::NormalizedF32; use krilla::page::PageSettings; use krilla::paint::{Fill, LinearGradient, SpreadMethod, Stop, Stroke}; use krilla::text::{Font, TextDirection}; use krilla::Document; pub(crate) static WORKSPACE_PATH: LazyLock = LazyLock::new(|| PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../../")); pub(crate) static ASSETS_PATH: LazyLock = LazyLock::new(|| WORKSPACE_PATH.join("assets")); fn main() { // The usual page setup. let mut document = Document::new(); let mut page = document.start_page_with(PageSettings::from_wh(600.0, 280.0).unwrap()); let mut surface = page.surface(); let noto_font = Font::new( Arc::new(std::fs::read(ASSETS_PATH.join("fonts/NotoSans-Regular.ttf")).unwrap()).into(), 0, ) .unwrap(); let gradient = LinearGradient { x1: 30.0, y1: 0.0, x2: 50.0, y2: 0.0, transform: Default::default(), spread_method: SpreadMethod::Reflect, stops: vec![ Stop { offset: NormalizedF32::new(0.2).unwrap(), color: rgb::Color::new(255, 0, 0).into(), opacity: NormalizedF32::ONE, }, Stop { offset: NormalizedF32::new(0.8).unwrap(), color: rgb::Color::new(255, 255, 0).into(), opacity: NormalizedF32::ONE, }, ], anti_alias: true, }; surface.set_fill(Some(Fill { paint: gradient.into(), opacity: NormalizedF32::new(0.5).unwrap(), rule: Default::default(), })); // Let's first write some red-colored text with some English text. surface.draw_text( Point::from_xy(0.0, 25.0), noto_font.clone(), 25.0, "z͈̤̭͖̉͑́a̳ͫ́̇͑̽͒ͯlͨ͗̍̀̍̔̀ģ͔̫̫̄o̗̠͔͆̏̓͢", false, TextDirection::Auto, ); surface.set_fill(None); surface.set_stroke(Some(Stroke { paint: rgb::Color::new(0, 255, 0).into(), ..Default::default() })); // Instead of applying fills, we can also apply strokes! surface.draw_text( Point::from_xy(0.0, 50.0), noto_font.clone(), 25.0, "This text is stroked green!", false, TextDirection::Auto, ); let noto_arabic_font = Font::new( Arc::new(std::fs::read(ASSETS_PATH.join("fonts/NotoSansArabic-Regular.ttf")).unwrap()) .into(), 0, ) .unwrap(); surface.set_fill(None); // As mentioned above, complex scripts are supported, you just can't mix them in // one run. surface.draw_text( Point::from_xy(0.0, 75.0), noto_arabic_font.clone(), 25.0, "هذا هو السطر الثاني من النص.", false, TextDirection::Auto, ); surface.finish(); page.finish(); let pdf = document.finish().unwrap(); let path = path::absolute("simple_text.pdf").unwrap(); eprintln!("Saved PDF to '{}'", path.display()); // Write the PDF to a file. std::fs::write(path, &pdf).unwrap(); }