Skip to content

Commit 21611ff

Browse files
committed
First attempt at checking ref images
1 parent ca0229b commit 21611ff

File tree

18 files changed

+695
-3
lines changed

18 files changed

+695
-3
lines changed

Cargo.lock

Lines changed: 588 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ tiny-skia-path = {git = "https://github.com/RazrFalcon/tiny-skia", rev="eec0a47"
2525

2626
[dev-dependencies]
2727
difference = "2.0.0"
28+
image = "0.25.1"
2829
paste = "1.0.15"
2930
sitro = {git = "https://github.com/LaurenzV/sitro", rev = "666b4ee"}
3031

850 Bytes
Loading

tests/refs/linear_gradient/mupdf.png

2.45 KB
Loading

tests/refs/linear_gradient/pdfbox.png

1.13 KB
Loading

tests/refs/linear_gradient/pdfium.png

1.73 KB
Loading

tests/refs/linear_gradient/pdfjs.png

849 Bytes
Loading
584 Bytes
Loading

tests/refs/linear_gradient/quartz.png

21.4 KB
Loading

tests/refs/linear_gradient/xpdf.png

763 Bytes
Loading
3.63 KB
Loading

tests/refs/text_rendering/mupdf.png

5.57 KB
Loading

tests/refs/text_rendering/pdfbox.png

5.9 KB
Loading

tests/refs/text_rendering/pdfium.png

13.3 KB
Loading

tests/refs/text_rendering/pdfjs.png

3.49 KB
Loading

tests/refs/text_rendering/poppler.png

6.54 KB
Loading

tests/refs/text_rendering/quartz.png

8.43 KB
Loading

tests/visreg.rs

Lines changed: 106 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,19 @@
1+
use cosmic_text::{Attrs, Buffer, FontSystem, Metrics, Shaping};
2+
use fontdb::Source;
3+
use image::{load_from_memory, Rgba};
14
use krilla::document::Document;
25
use krilla::rgb::Rgb;
36
use krilla::serialize::SerializeSettings;
7+
use krilla::stream::TestGlyph;
48
use krilla::{rgb, Fill, LinearGradient, Paint, SpreadMethod, Stop};
5-
use sitro::{render_mupdf, render_pdfbox, render_pdfium, render_pdfjs, render_quartz, RenderOptions, RenderedDocument, Renderer, render_poppler, render_ghostscript};
9+
use sitro::{
10+
render_ghostscript, render_mupdf, render_pdfbox, render_pdfium, render_pdfjs, render_poppler,
11+
render_quartz, RenderOptions, RenderedDocument, Renderer,
12+
};
13+
use skrifa::GlyphId;
14+
use std::cmp::max;
615
use std::path::PathBuf;
16+
use std::sync::Arc;
717
use tiny_skia_path::{PathBuilder, Rect, Size, Transform};
818
use usvg::NormalizedF32;
919

@@ -17,7 +27,7 @@ pub fn render_doc(doc: &[u8], renderer: &Renderer) -> RenderedDocument {
1727
Renderer::Quartz => render_quartz(doc, &options).unwrap(),
1828
Renderer::Pdfjs => render_pdfjs(doc, &options).unwrap(),
1929
Renderer::Pdfbox => render_pdfbox(doc, &options).unwrap(),
20-
Renderer::Ghostscript => render_ghostscript(doc, &options).unwrap()
30+
Renderer::Ghostscript => render_ghostscript(doc, &options).unwrap(),
2131
}
2232
}
2333

@@ -32,6 +42,42 @@ pub fn save_refs(name: &str, renderer: &Renderer, document: RenderedDocument) {
3242
panic!("empty document");
3343
} else if document.len() == 1 {
3444
let ref_path = refs_path.join(format!("{}.png", renderer.name()));
45+
46+
let reference = load_from_memory(&std::fs::read(&ref_path).unwrap()).unwrap().into_rgba8();
47+
let actual = load_from_memory(&document[0]).unwrap().into_rgba8();
48+
49+
let width = max(reference.width(), actual.width());
50+
let height = max(reference.height(), actual.height());
51+
52+
let mut pixel_diff = 0;
53+
54+
for x in 0..width {
55+
for y in 0..height {
56+
let actual_pixel = actual.get_pixel_checked(x, y);
57+
let expected_pixel = reference.get_pixel_checked(x, y);
58+
59+
60+
61+
match (actual_pixel, expected_pixel) {
62+
(Some(actual), Some(expected)) => {
63+
if is_pix_diff(expected, actual) {
64+
pixel_diff += 1;
65+
}
66+
}
67+
(Some(actual), None) => {
68+
pixel_diff += 1;
69+
}
70+
(None, Some(expected)) => {
71+
pixel_diff += 1;
72+
}
73+
_ => unreachable!(),
74+
}
75+
}
76+
}
77+
78+
assert_eq!(pixel_diff, 0);
79+
80+
3581
std::fs::write(&ref_path, &document[0]).unwrap();
3682
} else {
3783
for (index, page) in document.iter().enumerate() {
@@ -41,6 +87,17 @@ pub fn save_refs(name: &str, renderer: &Renderer, document: RenderedDocument) {
4187
}
4288
}
4389

90+
fn is_pix_diff(pixel1: &Rgba<u8>, pixel2: &Rgba<u8>) -> bool {
91+
if pixel1.0[3] == 0 && pixel2.0[3] == 0 {
92+
return false;
93+
}
94+
95+
pixel1.0[0] != pixel2.0[0]
96+
|| pixel1.0[1] != pixel2.0[1]
97+
|| pixel1.0[2] != pixel2.0[2]
98+
|| pixel1.0[3] != pixel2.0[3]
99+
}
100+
44101
macro_rules! generate_renderer_tests {
45102
($test_name:ident, $test_body:expr) => {
46103
paste::item! {
@@ -140,3 +197,50 @@ generate_renderer_tests!(linear_gradient, |renderer| {
140197
let rendered = render_doc(&pdf, &renderer);
141198
save_refs(stringify!(linear_gradient), &renderer, rendered);
142199
});
200+
201+
generate_renderer_tests!(cosmic_text, |renderer| {
202+
let mut font_system = FontSystem::new_with_fonts([Source::Binary(Arc::new(include_bytes!(
203+
"fonts/NotoSans-Regular.ttf"
204+
)))]);
205+
let metrics = Metrics::new(14.0, 20.0);
206+
let mut buffer = Buffer::new(&mut font_system, metrics);
207+
buffer.set_size(&mut font_system, Some(200.0), None);
208+
let attrs = Attrs::new();
209+
let text = "Some text here. Let's make it a bit longer so that line wrapping kicks in";
210+
buffer.set_text(&mut font_system, text, attrs, Shaping::Advanced);
211+
buffer.shape_until_scroll(&mut font_system, false);
212+
213+
let page_size = tiny_skia_path::Size::from_wh(200.0, 400.0).unwrap();
214+
let mut document_builder = Document::new(SerializeSettings::default());
215+
let mut builder = document_builder.start_page(page_size);
216+
let mut surface = builder.surface();
217+
218+
let font_map = surface.convert_fontdb(font_system.db_mut(), None);
219+
220+
// Inspect the output runs
221+
for run in buffer.layout_runs() {
222+
let y_offset = run.line_y;
223+
let iter = run
224+
.glyphs
225+
.iter()
226+
.map(|g| {
227+
TestGlyph::new(
228+
font_map.get(&g.font_id).unwrap().clone(),
229+
GlyphId::new(g.glyph_id as u32),
230+
g.w,
231+
g.x_offset,
232+
g.font_size,
233+
run.text[g.start..g.end].to_string(),
234+
)
235+
})
236+
.peekable();
237+
surface.fill_glyph_run(0.0, y_offset, Fill::<Rgb>::default(), iter);
238+
}
239+
240+
surface.finish();
241+
builder.finish();
242+
243+
let pdf = document_builder.finish();
244+
let rendered = render_doc(&pdf, &renderer);
245+
save_refs(stringify!(text_rendering), &renderer, rendered);
246+
});

0 commit comments

Comments
 (0)