Compare commits

..
6 changed files with 32 additions and 18 deletions
+2 -2
View File
File diff suppressed because one or more lines are too long
+1 -3
View File
@@ -104,9 +104,7 @@ pub(super) fn table(toks: &[Tok], spec: &str, depth: usize) -> FTable {
for r in rows {
let mut cells = Vec::new();
let mut g = 0usize;
// A document row keeps MAX_COLS cells; the rest would only widen `covering`, which is
// walked once per row.
for cell_toks in r.into_iter().take(wordcraft_doc::table::MAX_COLS) {
for cell_toks in r {
let mut cell = Cell::default();
let mut content = trim_cell(cell_toks);
// `\multicolumn{n}{spec}{content}`, `\multirow{n}{width}{content}`. Each wrapper
-11
View File
@@ -460,14 +460,3 @@ fn ligature_characters_split_across_runs_stay_apart() {
let back = import(tex.as_bytes());
assert_eq!(back.plain_text(Default::default()).trim(), "a--b ''x", "{tex}");
}
#[test]
fn a_tabular_row_keeps_the_cells_a_table_row_holds() {
// A 5,000-cell row with spans widened the multirow tracking every later row walks; the
// document keeps MAX_COLS cells a row, so the rest are left out while parsing.
let wide = vec!["\\multicolumn{63}{c}{x}"; 5000].join("&");
let toks = tokenize(&format!("{wide}\\\\ a & b \\\\"));
let t = table::table(&toks, "", 0);
assert_eq!(t.rows.first().map(Vec::len), Some(wordcraft_doc::table::MAX_COLS));
assert_eq!(t.rows.get(1).map(Vec::len), Some(2));
}
+13 -1
View File
@@ -836,10 +836,22 @@ fn draw_image(ctx: &mut RenderContext, fr: &Frame, it: &Draw) {
}
}
/// Widest path drawn, in device pixels a side: 64 times the largest canvas. The rasteriser
/// flattens a curve into as many points as its size asks for, before clipping, so a path with
/// coordinates of 1e15 (file data in a native document) would take it forever or run out of
/// memory; one this far past every canvas shows nothing a real drawing would.
const MAX_PATH_PIXELS: f64 = 1_048_576.0;
/// Whether `path` under `view` is small enough to draw ([`MAX_PATH_PIXELS`]) and finite.
fn path_extent_ok(view: Affine, path: &kurbo::BezPath) -> bool {
let b = view.transform_rect_bbox(path.bounding_box());
path.is_finite() && [b.x0, b.y0, b.x1, b.y1].iter().all(|v| v.is_finite() && v.abs() <= MAX_PATH_PIXELS)
}
fn draw_path(ctx: &mut RenderContext, fr: &Frame, it: &Draw) {
let Draw::Path { segs, fill, stroke, stroke_width, dash, cap } = it else { return };
let path = wordcraft_layout::display::seg_path(segs);
if path.elements().is_empty() {
if path.elements().is_empty() || !path_extent_ok(fr.view, &path) {
return;
}
ctx.set_transform(fr.view);
+15
View File
@@ -1318,3 +1318,18 @@ fn a_line_runs_from_top_left_to_bottom_right() {
let p = shape_path(ShapeKind::Line, kurbo::Rect::new(10.0, 20.0, 30.0, 60.0), None);
assert_eq!(p.elements(), &[kurbo::PathEl::MoveTo((10.0, 20.0).into()), kurbo::PathEl::LineTo((30.0, 60.0).into())]);
}
#[test]
fn paths_far_past_every_canvas_are_not_flattened() {
let line = |x: f64| {
let mut p = kurbo::BezPath::new();
p.move_to((0.0, 0.0));
p.curve_to((x, 0.0), (x, x), (0.0, x));
p
};
assert!(path_extent_ok(Affine::IDENTITY, &line(500.0)));
assert!(path_extent_ok(Affine::scale(4.0), &line(200_000.0)), "a large page at a high zoom");
assert!(!path_extent_ok(Affine::IDENTITY, &line(1e15)));
assert!(!path_extent_ok(Affine::scale(1e12), &line(10.0)));
assert!(!path_extent_ok(Affine::IDENTITY, &line(f64::NAN)));
}
+1 -1
View File
File diff suppressed because one or more lines are too long