//! This example introduces the concept of a `StreamBuilder`, which allows you to //! define graphics content on a separate context than the main page surface. This is necessary //! when defining patterns or mask. use std::path; use krilla::color::rgb; use krilla::geom::{Path, PathBuilder, Rect, Transform}; use krilla::page::PageSettings; use krilla::paint::{Fill, Pattern, Stroke}; use krilla::Document; fn main() { let mut document = Document::new(); let mut page = document.start_page_with(PageSettings::from_wh(200.0, 200.0).unwrap()); let mut surface = page.surface(); // We want to define a pattern with a red rectangle on the top-left and a // blue rectangle on the bottom-right. Then we want to apply this pattern to // a rectangle that is rotated by 45 degrees in the center. // First, let's define the pattern by creating a new stream builder. let mut stream_builder = surface.stream_builder(); let mut pattern_surface = stream_builder.surface(); pattern_surface.set_fill(Some(Fill { paint: rgb::Color::new(255, 0, 0).into(), ..Default::default() })); // Draw the top-left rectangle. pattern_surface.draw_path(&rect_to_path(0.0, 0.0, 10.0, 10.0)); pattern_surface.set_fill(Some(Fill { paint: rgb::Color::new(0, 0, 255).into(), ..Default::default() })); // Draw the bottom-right rectangle. pattern_surface.draw_path(&rect_to_path(10.0, 10.0, 20.0, 20.0)); pattern_surface.finish(); // Get the pattern stream let pattern_stream = stream_builder.finish(); // Define the actual pattern let pattern = Pattern { stream: pattern_stream, transform: Default::default(), width: 20.0, height: 20.0, }; // Now we draw the actual transformed rectangle. // First, push a transform so that the rectangle will be rotated. surface.push_transform(&Transform::from_rotate_at(45.0, 100.0, 100.0)); let rect_path = rect_to_path(30.0, 30.0, 170.0, 170.0); surface.set_fill(Some(Fill { paint: pattern.into(), ..Default::default() })); // Draw the rectangle. surface.draw_path(&rect_path); surface.set_fill(None); surface.set_stroke(Some(Stroke { paint: rgb::Color::black().into(), ..Default::default() })); // Let's also add a stroke, makes it look a bit nicer. surface.draw_path(&rect_path); // Don't forget to pop! Each `push_` method must have a corresponding pop. surface.pop(); surface.finish(); page.finish(); let pdf = document.finish().unwrap(); let path = path::absolute("stream_builder.pdf").unwrap(); eprintln!("Saved PDF to '{}'", path.display()); // Write the PDF to a file. std::fs::write(path, &pdf).unwrap(); } // A simple convenience function that allow us to generate rectangle paths. pub fn rect_to_path(x1: f32, y1: f32, x2: f32, y2: f32) -> Path { let mut builder = PathBuilder::new(); builder.push_rect(Rect::from_ltrb(x1, y1, x2, y2).unwrap()); builder.finish().unwrap() }