mirror of
https://github.com/storytold/wordcraft.git
synced 2026-11-04 17:30:18 -06:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b909e7d6b9 | ||
|
|
4f0fee6fc6 |
+2
-2
File diff suppressed because one or more lines are too long
@@ -58,23 +58,6 @@ mod tests {
|
||||
assert!(t.rows.iter().all(|r| r.len() <= 64), "a row grew past the column cap");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn insert_covered_skips_full_rows_without_walking_them() {
|
||||
// 50,000 spanning cells over a 50,000-cell row: each walked the row below to its grid
|
||||
// column before finding it full (billions of steps). A full row is now skipped at once.
|
||||
let n = 50_000;
|
||||
let mut t = FTable {
|
||||
rows: vec![vec![Cell { rowspan: 2, ..Default::default() }; n], vec![Cell::default(); n]],
|
||||
widths: Vec::new(),
|
||||
borderless: false,
|
||||
};
|
||||
let start = std::time::Instant::now();
|
||||
t.insert_covered();
|
||||
assert!(start.elapsed() < std::time::Duration::from_secs(10), "{:?}", start.elapsed());
|
||||
assert_eq!(t.rows[1].len(), n, "a full row takes no covered cell");
|
||||
assert!(t.rows[1].iter().all(|c| !c.covered));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn base64_round_trip() {
|
||||
for data in [&b""[..], b"f", b"fo", b"foo", b"foob", b"fooba", b"foobar", &[0, 255, 128, 7]] {
|
||||
|
||||
@@ -418,11 +418,6 @@ impl FTable {
|
||||
return;
|
||||
}
|
||||
let Some(row) = self.rows.get_mut(r + k) else { break };
|
||||
// A full row takes no covered cell: checked before it is walked, so a
|
||||
// wide row isn't scanned for every span above it.
|
||||
if row.len() >= 64 {
|
||||
continue;
|
||||
}
|
||||
// Find the index in that row at grid column `g`.
|
||||
let mut x = 0usize;
|
||||
let mut at = row.len();
|
||||
@@ -433,7 +428,9 @@ impl FTable {
|
||||
}
|
||||
x += cc.colspan.clamp(1, 63) as usize;
|
||||
}
|
||||
row.insert(at, Cell { colspan: span as u32, covered: true, ..Default::default() });
|
||||
if row.len() < 64 {
|
||||
row.insert(at, Cell { colspan: span as u32, covered: true, ..Default::default() });
|
||||
}
|
||||
}
|
||||
}
|
||||
g += span;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user