mod common;
use common::*;
use zenith_core::default_provider;
use zenith_scene::compile;
use zenith_scene::ir::{Paint, SceneCommand};
#[test]
fn span_without_highlight_emits_no_fill_rect() {
let src = r##"zenith version=1 {
project id="proj.hl0" name="HL0"
tokens format="zenith-token-v1" {
token id="color.ink" type="color" value="#111827"
token id="font.body" type="fontFamily" value="Noto Sans"
token id="size.body" type="dimension" value=(px)24
}
styles {}
document id="doc.hl0" title="HL0" {
page id="page.hl0" w=(px)400 h=(px)200 {
text id="t.hl0" x=(px)10 y=(px)20 w=(px)380 h=(px)60 fill=(token)"color.ink" font-family=(token)"font.body" font-size=(token)"size.body" {
span "Hello"
}
}
}
}
"##;
let doc = parse(src);
let result = compile(&doc, &default_provider());
assert!(
result
.diagnostics
.iter()
.all(|d| d.code != "scene.text_unshaped"),
"no text_unshaped diagnostics expected; got: {:?}",
result.diagnostics
);
let rects: Vec<_> = result
.scene
.commands
.iter()
.filter(|c| matches!(c, SceneCommand::FillRect { .. }))
.collect();
assert!(
rects.is_empty(),
"span without highlight must emit no FillRect; got {} rect(s)",
rects.len()
);
let runs: Vec<_> = result
.scene
.commands
.iter()
.filter(|c| matches!(c, SceneCommand::DrawGlyphRun { .. }))
.collect();
assert_eq!(
runs.len(),
1,
"expected exactly one DrawGlyphRun; got {}",
runs.len()
);
}
#[test]
fn span_with_highlight_emits_fill_rect_before_glyph_run() {
let src = r##"zenith version=1 {
project id="proj.hl1" name="HL1"
tokens format="zenith-token-v1" {
token id="color.ink" type="color" value="#111827"
token id="color.mark" type="color" value="#FFFF00"
token id="font.body" type="fontFamily" value="Noto Sans"
token id="size.body" type="dimension" value=(px)24
}
styles {}
document id="doc.hl1" title="HL1" {
page id="page.hl1" w=(px)400 h=(px)200 {
text id="t.hl1" x=(px)10 y=(px)20 w=(px)380 h=(px)60 fill=(token)"color.ink" font-family=(token)"font.body" font-size=(token)"size.body" {
span "Hello" highlight=(token)"color.mark"
}
}
}
}
"##;
let doc = parse(src);
let result = compile(&doc, &default_provider());
assert!(
result
.diagnostics
.iter()
.all(|d| d.code != "scene.text_unshaped"),
"no text_unshaped diagnostics expected; got: {:?}",
result.diagnostics
);
let significant: Vec<&SceneCommand> = result
.scene
.commands
.iter()
.filter(|c| {
matches!(
c,
SceneCommand::FillRect { .. } | SceneCommand::DrawGlyphRun { .. }
)
})
.collect();
assert_eq!(
significant.len(),
2,
"expected exactly 1 FillRect + 1 DrawGlyphRun; got: {:?}",
significant
);
match significant[0] {
SceneCommand::FillRect {
paint: Paint::Solid { color },
x,
w,
h,
..
} => {
assert_eq!(color.r, 0xFF, "highlight rect r must be 0xFF (yellow)");
assert_eq!(color.g, 0xFF, "highlight rect g must be 0xFF (yellow)");
assert_eq!(color.b, 0x00, "highlight rect b must be 0x00 (yellow)");
assert_eq!(*x, 10.0, "highlight rect x must be text-box origin (10px)");
assert!(*w > 0.0, "highlight rect width must be > 0; got {w}");
assert!(*h > 0.0, "highlight rect height must be > 0; got {h}");
}
other => panic!("expected FillRect (highlight), got {other:?}"),
}
match significant[1] {
SceneCommand::DrawGlyphRun { color, x, .. } => {
assert_eq!(color.r, 0x11, "glyph color.r must be 0x11 (ink)");
assert_eq!(color.g, 0x18, "glyph color.g must be 0x18 (ink)");
assert_eq!(color.b, 0x27, "glyph color.b must be 0x27 (ink)");
assert_eq!(*x, 10.0, "glyph run x must match text-box origin (10px)");
}
other => panic!("expected DrawGlyphRun after highlight FillRect; got {other:?}"),
}
}
#[test]
fn only_highlighted_span_gets_fill_rect() {
let src = r##"zenith version=1 {
project id="proj.hl2" name="HL2"
tokens format="zenith-token-v1" {
token id="color.ink" type="color" value="#111827"
token id="color.hi" type="color" value="#00FF00"
token id="font.body" type="fontFamily" value="Noto Sans"
token id="size.body" type="dimension" value=(px)24
}
styles {}
document id="doc.hl2" title="HL2" {
page id="page.hl2" w=(px)800 h=(px)200 {
text id="t.hl2" x=(px)10 y=(px)20 w=(px)780 h=(px)60 fill=(token)"color.ink" font-family=(token)"font.body" font-size=(token)"size.body" {
span "plain "
span "highlighted" highlight=(token)"color.hi"
}
}
}
}
"##;
let doc = parse(src);
let result = compile(&doc, &default_provider());
assert!(
result
.diagnostics
.iter()
.all(|d| d.code != "scene.text_unshaped"),
"no text_unshaped diagnostics; got: {:?}",
result.diagnostics
);
let significant: Vec<&SceneCommand> = result
.scene
.commands
.iter()
.filter(|c| {
matches!(
c,
SceneCommand::FillRect { .. } | SceneCommand::DrawGlyphRun { .. }
)
})
.collect();
assert_eq!(
significant.len(),
3,
"expected 2 DrawGlyphRun + 1 FillRect; got: {:?}",
significant
);
assert!(
matches!(significant[0], SceneCommand::DrawGlyphRun { .. }),
"first significant command must be DrawGlyphRun (plain span); got {:?}",
significant[0]
);
match significant[1] {
SceneCommand::FillRect {
paint: Paint::Solid { color },
x,
..
} => {
assert_eq!(color.r, 0x00, "highlight r must be 0x00 (green)");
assert_eq!(color.g, 0xFF, "highlight g must be 0xFF (green)");
assert_eq!(color.b, 0x00, "highlight b must be 0x00 (green)");
assert!(
*x > 10.0,
"highlight rect x must be > 10 (after plain span advance); got {x}"
);
}
other => panic!("expected FillRect (highlight) at index 1; got {other:?}"),
}
assert!(
matches!(significant[2], SceneCommand::DrawGlyphRun { .. }),
"third significant command must be DrawGlyphRun (highlighted span); got {:?}",
significant[2]
);
}