use pdf_writer::Content;
use zenith_core::{AssetProvider, FontProvider};
use zenith_scene::{Scene, SceneCommand};
use super::content::{IMAGE_PREFIX, PageResources, emit_command, name};
use super::font::FontPlan;
use super::image::decoded_image_from_straight_rgba;
pub(super) fn embed_rasterized_region(
content: &mut Content,
res: &mut PageResources,
sub_commands: &[SceneCommand],
page: (f64, f64),
fonts: &dyn FontProvider,
assets: &dyn AssetProvider,
font_plan: &FontPlan,
) {
let (pw, ph) = page;
let mut sub_scene = Scene::new(pw, ph);
sub_scene.commands = sub_commands.to_vec();
let img = match crate::render::render_image(&sub_scene, fonts, assets) {
Ok(i) => i,
Err(_) => {
for c in sub_commands {
emit_command(content, res, c, page, fonts, assets, font_plan);
}
return;
}
};
crop_and_embed(content, res, &img.rgba, img.width, img.height);
}
fn crop_and_embed(content: &mut Content, res: &mut PageResources, rgba: &[u8], iw: u32, ih: u32) {
let expected = match (iw as usize)
.checked_mul(ih as usize)
.and_then(|n| n.checked_mul(4))
{
Some(n) => n,
None => return,
};
if iw == 0 || ih == 0 || rgba.len() != expected {
return;
}
let stride = iw as usize * 4;
let mut min_x = iw;
let mut min_y = ih;
let mut max_x = 0u32;
let mut max_y = 0u32;
let mut found = false;
for (y, row) in rgba.chunks_exact(stride).enumerate() {
for (x, px) in row.chunks_exact(4).enumerate() {
if px[3] > 0 {
found = true;
let (xu, yu) = (x as u32, y as u32);
if xu < min_x {
min_x = xu;
}
if yu < min_y {
min_y = yu;
}
if xu > max_x {
max_x = xu;
}
if yu > max_y {
max_y = yu;
}
}
}
}
if !found {
return;
}
let ox = min_x;
let oy = min_y;
let cw = max_x - min_x + 1;
let ch = max_y - min_y + 1;
let crop_stride = cw as usize * 4;
let mut cropped = Vec::with_capacity(crop_stride * ch as usize);
for y in oy..=max_y {
let row_start = y as usize * stride + ox as usize * 4;
let row_end = row_start + crop_stride;
match rgba.get(row_start..row_end) {
Some(slice) => cropped.extend_from_slice(slice),
None => return, }
}
let Some(decoded) = decoded_image_from_straight_rgba(&cropped, cw, ch) else {
return;
};
let id = res.images.len();
res.images.push(decoded);
content.save_state();
content.transform([
cw as f32,
0.0,
0.0,
-(ch as f32),
ox as f32,
oy as f32 + ch as f32,
]);
content.x_object(name(IMAGE_PREFIX, id).as_name());
content.restore_state();
}