paavohtl Claude Opus 4.6 (1M context) commited on
Commit
96b8a07
·
1 Parent(s): 0212bb3

feat: line-drawing snapshot test infrastructure

Browse files

Add PixelGrid (pure-Rust test grid) and PixelWriter trait for unit
testing line algorithms without WA runtime. Add snapshot capture in
DLL (OPENWA_CAPTURE_LINE_SNAPSHOTS=1, triggered at frame 10) that
draws test lines on a BitGrid using WA's native functions and saves
pixel data for comparison.

Also fix headful test crash: remove --minimized flag which became
incompatible with WA's DirectDraw initialization.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

crates/openwa-core/src/display/line_draw.rs ADDED
@@ -0,0 +1,289 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //! Line-drawing algorithms for 8bpp BitGrid surfaces.
2
+ //!
3
+ //! Pure Rust ports of WA's thick-line drawing system (0x4F7500 / 0x4F7A60).
4
+ //! The original draws 2-pixel-wide Bresenham-style lines with Fixed-point
5
+ //! Cohen-Sutherland clipping.
6
+ //!
7
+ //! ## Architecture
8
+ //!
9
+ //! ```text
10
+ //! draw_line_clipped / draw_line_two_color (outer dispatch)
11
+ //! ├── Determine dominant axis (|dx| vs |dy|)
12
+ //! ├── Sort endpoints in positive direction
13
+ //! ├── clip_line() — Cohen-Sutherland, Fixed-point
14
+ //! ├── Rasterizer (horizontal-major or vertical-major)
15
+ //! │ └── put_pixel_clipped × 8 per step (outline)
16
+ //! └── Fill rasterizer — 4 pixels per step (body color)
17
+ //! ```
18
+
19
+ use crate::fixed::Fixed;
20
+
21
+ /// Trait for pixel-addressable surfaces used by line-drawing algorithms.
22
+ ///
23
+ /// Implemented for `PixelGrid` (test-only, pure Rust) and can be implemented
24
+ /// for `DisplayBitGrid` (runtime, via vtable dispatch).
25
+ pub trait PixelWriter {
26
+ fn put_pixel_clipped(&mut self, x: i32, y: i32, color: u8);
27
+ fn clip_left(&self) -> i32;
28
+ fn clip_top(&self) -> i32;
29
+ fn clip_right(&self) -> i32;
30
+ fn clip_bottom(&self) -> i32;
31
+ }
32
+
33
+ /// Pure-Rust 8bpp pixel grid for unit testing. No vtable, no WA heap.
34
+ ///
35
+ /// Row-major layout: `data[y * row_stride + x]`.
36
+ /// Row stride is 4-byte aligned (matching WA's BitGrid allocation).
37
+ pub struct PixelGrid {
38
+ pub data: Vec<u8>,
39
+ pub width: u32,
40
+ pub height: u32,
41
+ pub row_stride: u32,
42
+ pub clip_left: u32,
43
+ pub clip_top: u32,
44
+ pub clip_right: u32,
45
+ pub clip_bottom: u32,
46
+ }
47
+
48
+ impl PixelGrid {
49
+ /// Create a new zeroed pixel grid with default clip rect covering the full surface.
50
+ pub fn new(width: u32, height: u32) -> Self {
51
+ let row_stride = (width + 3) & !3; // 4-byte aligned
52
+ let size = (row_stride * height) as usize;
53
+ Self {
54
+ data: vec![0u8; size],
55
+ width,
56
+ height,
57
+ row_stride,
58
+ clip_left: 0,
59
+ clip_top: 0,
60
+ clip_right: width,
61
+ clip_bottom: height,
62
+ }
63
+ }
64
+
65
+ /// Clear all pixels to zero.
66
+ pub fn clear(&mut self) {
67
+ self.data.fill(0);
68
+ }
69
+ }
70
+
71
+ impl PixelWriter for PixelGrid {
72
+ #[inline]
73
+ fn put_pixel_clipped(&mut self, x: i32, y: i32, color: u8) {
74
+ if x >= self.clip_left as i32
75
+ && x < self.clip_right as i32
76
+ && y >= self.clip_top as i32
77
+ && y < self.clip_bottom as i32
78
+ {
79
+ self.data[(y as u32 * self.row_stride + x as u32) as usize] = color;
80
+ }
81
+ }
82
+
83
+ #[inline]
84
+ fn clip_left(&self) -> i32 {
85
+ self.clip_left as i32
86
+ }
87
+ #[inline]
88
+ fn clip_top(&self) -> i32 {
89
+ self.clip_top as i32
90
+ }
91
+ #[inline]
92
+ fn clip_right(&self) -> i32 {
93
+ self.clip_right as i32
94
+ }
95
+ #[inline]
96
+ fn clip_bottom(&self) -> i32 {
97
+ self.clip_bottom as i32
98
+ }
99
+ }
100
+
101
+ // =========================================================================
102
+ // Fixed-point line clipping (port of 0x4F7150)
103
+ // =========================================================================
104
+
105
+ /// Cohen-Sutherland outcode bits for line clipping.
106
+ const LEFT: u8 = 1;
107
+ const RIGHT: u8 = 2;
108
+ const TOP: u8 = 4;
109
+ const BOTTOM: u8 = 8;
110
+
111
+ /// Compute Cohen-Sutherland outcode for a Fixed-point coordinate.
112
+ fn outcode(x: Fixed, y: Fixed, clip: &ClipRect) -> u8 {
113
+ let mut code = 0u8;
114
+ if x.to_raw() < clip.left.to_raw() {
115
+ code |= LEFT;
116
+ }
117
+ if x.to_raw() > clip.right.to_raw() {
118
+ code |= RIGHT;
119
+ }
120
+ if y.to_raw() < clip.top.to_raw() {
121
+ code |= TOP;
122
+ }
123
+ if y.to_raw() > clip.bottom.to_raw() {
124
+ code |= BOTTOM;
125
+ }
126
+ code
127
+ }
128
+
129
+ /// Clip rectangle in Fixed-point coordinates.
130
+ struct ClipRect {
131
+ left: Fixed,
132
+ top: Fixed,
133
+ right: Fixed,
134
+ bottom: Fixed,
135
+ }
136
+
137
+ /// Fixed-point multiply then shift: `(a * b) >> 16`.
138
+ ///
139
+ /// Port of the pattern used throughout the WA line clipper.
140
+ #[inline]
141
+ fn fixed_mul_shift(a: i32, b: i32) -> i32 {
142
+ ((a as i64 * b as i64) >> 16) as i32
143
+ }
144
+
145
+ /// Clip a line segment to the clip rectangle.
146
+ ///
147
+ /// Port of 0x4F7150. Returns true if the clipped line is visible.
148
+ /// Modifies coordinates in-place.
149
+ ///
150
+ /// The clip rectangle is read from the PixelWriter's bounds, scaled to Fixed.
151
+ fn clip_line(
152
+ x1: &mut Fixed,
153
+ y1: &mut Fixed,
154
+ x2: &mut Fixed,
155
+ y2: &mut Fixed,
156
+ writer: &dyn PixelWriter,
157
+ ) -> bool {
158
+ let clip = ClipRect {
159
+ left: Fixed::from_int(writer.clip_left()),
160
+ top: Fixed::from_int(writer.clip_top()),
161
+ right: Fixed::from_int(writer.clip_right()),
162
+ bottom: Fixed::from_int(writer.clip_bottom()),
163
+ };
164
+
165
+ let code1 = outcode(*x1, *y1, &clip);
166
+ let code2 = outcode(*x2, *y2, &clip);
167
+
168
+ // Trivial reject: both endpoints on same side
169
+ if code1 & code2 != 0 {
170
+ return false;
171
+ }
172
+
173
+ // Clip x1 against left/right bounds
174
+ if x1.to_raw() < clip.left.to_raw() {
175
+ let ratio = fixed_div(clip.left.to_raw() - x1.to_raw(), x2.to_raw() - x1.to_raw());
176
+ y1.0 += fixed_mul_shift(y2.to_raw() - y1.to_raw(), ratio);
177
+ *x1 = clip.left;
178
+ } else if x1.to_raw() > clip.right.to_raw() {
179
+ let ratio = fixed_div(clip.right.to_raw() - x1.to_raw(), x2.to_raw() - x1.to_raw());
180
+ y1.0 += fixed_mul_shift(y2.to_raw() - y1.to_raw(), ratio);
181
+ *x1 = clip.right;
182
+ }
183
+
184
+ // Clip x2 against left/right bounds
185
+ if x2.to_raw() < clip.left.to_raw() {
186
+ let ratio = fixed_div(clip.left.to_raw() - x2.to_raw(), x1.to_raw() - x2.to_raw());
187
+ y2.0 += fixed_mul_shift(y1.to_raw() - y2.to_raw(), ratio);
188
+ *x2 = clip.left;
189
+ } else if x2.to_raw() > clip.right.to_raw() {
190
+ let ratio = fixed_div(clip.right.to_raw() - x2.to_raw(), x1.to_raw() - x2.to_raw());
191
+ y2.0 += fixed_mul_shift(y1.to_raw() - y2.to_raw(), ratio);
192
+ *x2 = clip.right;
193
+ }
194
+
195
+ // Check y bounds after x clipping
196
+ if y1.to_raw() > clip.bottom.to_raw() || y2.to_raw() > clip.bottom.to_raw() {
197
+ return false;
198
+ }
199
+ if y1.to_raw() < clip.top.to_raw() && y2.to_raw() < clip.top.to_raw() {
200
+ return false;
201
+ }
202
+
203
+ // Clip y1 against top/bottom bounds
204
+ if y1.to_raw() < clip.top.to_raw() {
205
+ let ratio = fixed_div(clip.top.to_raw() - y1.to_raw(), y2.to_raw() - y1.to_raw());
206
+ x1.0 += fixed_mul_shift(x2.to_raw() - x1.to_raw(), ratio);
207
+ *y1 = clip.top;
208
+ } else if y1.to_raw() > clip.bottom.to_raw() {
209
+ let ratio = fixed_div(
210
+ clip.bottom.to_raw() - y1.to_raw(),
211
+ y2.to_raw() - y1.to_raw(),
212
+ );
213
+ x1.0 += fixed_mul_shift(x2.to_raw() - x1.to_raw(), ratio);
214
+ *y1 = clip.bottom;
215
+ }
216
+
217
+ // Clip y2 against top/bottom bounds
218
+ if y2.to_raw() < clip.top.to_raw() {
219
+ let ratio = fixed_div(clip.top.to_raw() - y2.to_raw(), y1.to_raw() - y2.to_raw());
220
+ x2.0 += fixed_mul_shift(x1.to_raw() - x2.to_raw(), ratio);
221
+ *y2 = clip.top;
222
+ } else if y2.to_raw() > clip.bottom.to_raw() {
223
+ let ratio = fixed_div(
224
+ clip.bottom.to_raw() - y2.to_raw(),
225
+ y1.to_raw() - y2.to_raw(),
226
+ );
227
+ x2.0 += fixed_mul_shift(x1.to_raw() - x2.to_raw(), ratio);
228
+ *y2 = clip.bottom;
229
+ }
230
+
231
+ // Final check: both endpoints must be within bounds
232
+ if (x1.to_raw() < clip.left.to_raw() || x1.to_raw() > clip.right.to_raw())
233
+ && (x2.to_raw() < clip.left.to_raw() || x2.to_raw() > clip.right.to_raw())
234
+ {
235
+ return false;
236
+ }
237
+
238
+ true
239
+ }
240
+
241
+ /// Fixed-point divide used by the line clipper.
242
+ ///
243
+ /// Port of FUN_005b3501: computes `(numerator << 16) / denominator`.
244
+ #[inline]
245
+ fn fixed_div(numerator: i32, denominator: i32) -> i32 {
246
+ if denominator == 0 {
247
+ return 0;
248
+ }
249
+ (((numerator as i64) << 16) / denominator as i64) as i32
250
+ }
251
+
252
+ #[cfg(test)]
253
+ mod tests {
254
+ use super::*;
255
+
256
+ #[test]
257
+ fn pixel_grid_basic() {
258
+ let mut grid = PixelGrid::new(16, 16);
259
+ grid.put_pixel_clipped(5, 5, 0xFF);
260
+ assert_eq!(grid.data[5 * grid.row_stride as usize + 5], 0xFF);
261
+
262
+ // Out of bounds — should be no-op
263
+ grid.put_pixel_clipped(-1, 5, 0xAA);
264
+ grid.put_pixel_clipped(16, 5, 0xAA);
265
+ grid.put_pixel_clipped(5, -1, 0xAA);
266
+ grid.put_pixel_clipped(5, 16, 0xAA);
267
+ }
268
+
269
+ #[test]
270
+ fn pixel_grid_clipping() {
271
+ let mut grid = PixelGrid::new(16, 16);
272
+ grid.clip_left = 4;
273
+ grid.clip_top = 4;
274
+ grid.clip_right = 12;
275
+ grid.clip_bottom = 12;
276
+
277
+ // Inside clip rect — should write
278
+ grid.put_pixel_clipped(4, 4, 1);
279
+ assert_eq!(grid.data[4 * grid.row_stride as usize + 4], 1);
280
+
281
+ // At clip boundary (exclusive) — should NOT write
282
+ grid.put_pixel_clipped(12, 4, 2);
283
+ assert_eq!(grid.data[4 * grid.row_stride as usize + 12], 0);
284
+
285
+ // Outside clip rect — should NOT write
286
+ grid.put_pixel_clipped(3, 4, 3);
287
+ assert_eq!(grid.data[4 * grid.row_stride as usize + 3], 0);
288
+ }
289
+ }
crates/openwa-core/src/display/mod.rs CHANGED
@@ -5,6 +5,7 @@ pub mod dd_display;
5
  pub mod display_wrapper;
6
  pub mod gfx;
7
  pub mod gradient;
 
8
  pub mod opengl;
9
  pub mod palette;
10
 
 
5
  pub mod display_wrapper;
6
  pub mod gfx;
7
  pub mod gradient;
8
+ pub mod line_draw;
9
  pub mod opengl;
10
  pub mod palette;
11
 
crates/openwa-dll/src/replacements/display.rs CHANGED
@@ -48,6 +48,134 @@ unsafe extern "thiscall" fn headless_destructor(
48
  this
49
  }
50
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  pub fn install() -> Result<(), String> {
52
  let _ = log_line("[Display] Patching DisplayBase vtables");
53
 
 
48
  this
49
  }
50
 
51
+ /// Capture line-drawing snapshots from WA's native BitGrid line functions.
52
+ ///
53
+ /// Creates a test BitGrid, calls WA line functions with known inputs,
54
+ /// saves pixel data to `testdata/snapshots/`. Activated by
55
+ /// `OPENWA_CAPTURE_LINE_SNAPSHOTS=1`.
56
+ pub unsafe fn capture_line_snapshots() {
57
+ use openwa_core::display::bitgrid::DisplayBitGrid;
58
+ use std::fs;
59
+ use std::io::Write;
60
+
61
+ let grid_w: u32 = 128;
62
+ let grid_h: u32 = 128;
63
+ let grid = DisplayBitGrid::alloc(8, grid_w, grid_h);
64
+ if grid.is_null() {
65
+ let _ = log_line("[Display] SNAPSHOT: Failed to allocate test BitGrid");
66
+ return;
67
+ }
68
+
69
+ let row_stride = (*grid).row_stride;
70
+ let data_ptr = (*grid).data;
71
+ let data_size = (row_stride * grid_h) as usize;
72
+
73
+ // WA line functions (stdcall)
74
+ let draw_clipped: unsafe extern "stdcall" fn(*mut DisplayBitGrid, i32, i32, i32, i32, u32) =
75
+ core::mem::transmute(rb(va::DRAW_LINE_CLIPPED) as usize);
76
+
77
+ let draw_two: unsafe extern "stdcall" fn(*mut DisplayBitGrid, i32, i32, i32, i32, u32, u32) =
78
+ core::mem::transmute(rb(va::DRAW_LINE_TWO_COLOR) as usize);
79
+
80
+ let dir = "testdata/snapshots";
81
+ let _ = fs::create_dir_all(dir);
82
+
83
+ // Macro: clear grid, reset clip, run drawing code, save to file.
84
+ macro_rules! snap {
85
+ ($name:expr, $body:expr) => {{
86
+ core::ptr::write_bytes(data_ptr, 0, data_size);
87
+ (*grid).clip_left = 0;
88
+ (*grid).clip_top = 0;
89
+ (*grid).clip_right = grid_w;
90
+ (*grid).clip_bottom = grid_h;
91
+ $body;
92
+ let path = format!("{}/{}.bin", dir, $name);
93
+ if let Ok(mut file) = fs::File::create(&path) {
94
+ let _ = file.write_all(&grid_w.to_le_bytes());
95
+ let _ = file.write_all(&grid_h.to_le_bytes());
96
+ let _ = file.write_all(&row_stride.to_le_bytes());
97
+ let _ = file.write_all(core::slice::from_raw_parts(data_ptr, data_size));
98
+ }
99
+ }};
100
+ }
101
+
102
+ let f = |x: i32| x << 16; // int to Fixed raw
103
+ let mut count = 0u32;
104
+
105
+ // Single-color line tests
106
+ for &(name, x1, y1, x2, y2, color) in &[
107
+ ("clipped_horizontal", f(10), f(64), f(118), f(64), 1u32),
108
+ ("clipped_vertical", f(64), f(10), f(64), f(118), 2),
109
+ ("clipped_diagonal_45", f(10), f(10), f(118), f(118), 3),
110
+ ("clipped_diagonal_steep", f(60), f(10), f(68), f(118), 4),
111
+ ("clipped_diagonal_shallow", f(10), f(60), f(118), f(68), 5),
112
+ ("clipped_negative_slope", f(118), f(10), f(10), f(118), 6),
113
+ (
114
+ "clipped_subpixel",
115
+ f(10) + 0x8000,
116
+ f(20) + 0x4000,
117
+ f(100) + 0xC000,
118
+ f(80) + 0x2000,
119
+ 7,
120
+ ),
121
+ ("clipped_zero_length", f(64), f(64), f(64), f(64), 8),
122
+ ("clipped_partially_outside", f(-20), f(64), f(148), f(64), 9),
123
+ ("clipped_fully_outside", f(-50), f(-50), f(-10), f(-10), 10),
124
+ ] {
125
+ snap!(name, draw_clipped(grid, x1, y1, x2, y2, color));
126
+ count += 1;
127
+ }
128
+
129
+ // Two-color line tests
130
+ for &(name, x1, y1, x2, y2, c1, c2) in &[
131
+ ("twocol_horizontal", f(10), f(64), f(118), f(64), 1u32, 2u32),
132
+ ("twocol_vertical", f(64), f(10), f(64), f(118), 1, 2),
133
+ ("twocol_diagonal_45", f(10), f(10), f(118), f(118), 1, 2),
134
+ ("twocol_steep", f(60), f(10), f(68), f(118), 3, 4),
135
+ ("twocol_shallow", f(10), f(60), f(118), f(68), 3, 4),
136
+ ("twocol_negative", f(118), f(10), f(10), f(118), 5, 6),
137
+ (
138
+ "twocol_subpixel",
139
+ f(10) + 0x8000,
140
+ f(20) + 0x4000,
141
+ f(100) + 0xC000,
142
+ f(80) + 0x2000,
143
+ 7,
144
+ 8,
145
+ ),
146
+ ] {
147
+ snap!(name, draw_two(grid, x1, y1, x2, y2, c1, c2));
148
+ count += 1;
149
+ }
150
+
151
+ // Restricted clip rect tests
152
+ snap!("clipped_restricted_clip", {
153
+ (*grid).clip_left = 30;
154
+ (*grid).clip_top = 30;
155
+ (*grid).clip_right = 98;
156
+ (*grid).clip_bottom = 98;
157
+ draw_clipped(grid, f(10), f(10), f(118), f(118), 11)
158
+ });
159
+ count += 1;
160
+
161
+ snap!("twocol_restricted_clip", {
162
+ (*grid).clip_left = 30;
163
+ (*grid).clip_top = 30;
164
+ (*grid).clip_right = 98;
165
+ (*grid).clip_bottom = 98;
166
+ draw_two(grid, f(10), f(10), f(118), f(118), 9, 10)
167
+ });
168
+ count += 1;
169
+
170
+ let _ = log_line(&format!(
171
+ "[Display] SNAPSHOT: Saved {count} line snapshots to {dir}/"
172
+ ));
173
+
174
+ // Free the grid
175
+ let destructor = (*(*grid).vtable).destructor;
176
+ destructor(grid, 1);
177
+ }
178
+
179
  pub fn install() -> Result<(), String> {
180
  let _ = log_line("[Display] Patching DisplayBase vtables");
181
 
crates/openwa-dll/src/replacements/frame_hook.rs CHANGED
@@ -63,6 +63,13 @@ unsafe extern "stdcall" fn hook_turn_manager(turngame: u32) {
63
 
64
  let frame = FRAMES_PROCESSED.fetch_add(1, Ordering::Relaxed) + 1;
65
 
 
 
 
 
 
 
 
66
  // Replay test: fast-forward + milestone tracking (no-op if not in replay test mode)
67
  super::replay_test::on_frame(frame);
68
  }
 
63
 
64
  let frame = FRAMES_PROCESSED.fetch_add(1, Ordering::Relaxed) + 1;
65
 
66
+ // Line snapshot capture: run once at frame 10 when env var is set
67
+ if frame == 10 {
68
+ if std::env::var("OPENWA_CAPTURE_LINE_SNAPSHOTS").is_ok() {
69
+ super::display::capture_line_snapshots();
70
+ }
71
+ }
72
+
73
  // Replay test: fast-forward + milestone tracking (no-op if not in replay test mode)
74
  super::replay_test::on_frame(frame);
75
  }
crates/openwa-test-runner/src/main.rs CHANGED
@@ -816,7 +816,6 @@ fn run_headful_test(
816
  let errorlog_path = run_dir.join(format!("{}.errorlog.txt", test.name));
817
 
818
  let result = Command::new(launcher)
819
- .arg("--minimized")
820
  .arg(wa_exe)
821
  .arg(&test.replay_path)
822
  .env("OPENWA_REPLAY_TEST", "1")
 
816
  let errorlog_path = run_dir.join(format!("{}.errorlog.txt", test.name));
817
 
818
  let result = Command::new(launcher)
 
819
  .arg(wa_exe)
820
  .arg(&test.replay_path)
821
  .env("OPENWA_REPLAY_TEST", "1")
testdata/snapshots/clipped_diagonal_45.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a6d578b7421ee45ef7d10700614024892972c3ab255705fc7ec750dc4b70852b
3
+ size 16396
testdata/snapshots/clipped_diagonal_shallow.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d4154d14e49950ce44801998957d4d316287a574d2006db21e262c5b7459521e
3
+ size 16396
testdata/snapshots/clipped_diagonal_steep.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b4f9440349534e65a92869a779075877c14fd169bf58ff1074c438b80919e72c
3
+ size 16396
testdata/snapshots/clipped_fully_outside.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:60d2f81832d645fd3abf309ea419b7c75bfa3516cd69f8105fa35c89a0c58c1d
3
+ size 16396
testdata/snapshots/clipped_horizontal.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:dd0f3f8abfa05ba3d0483c8c2b974d9a1efbbc7558d32d8d32666c723cba9801
3
+ size 16396
testdata/snapshots/clipped_negative_slope.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:7ceedb4d2c03ad3b6ebf3f1be84a8b13580d7500b991b496d0077004cbeb8e79
3
+ size 16396
testdata/snapshots/clipped_partially_outside.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e6e4be906d80defb36b321eff3f64be21c13ac43f5f24749be5119dbf97b010e
3
+ size 16396
testdata/snapshots/clipped_restricted_clip.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:cd3afc44b242bbc7c03109e564660e8ca8aa3af2d6558730025044601ae5bdb6
3
+ size 16396
testdata/snapshots/clipped_subpixel.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:dc55020f352f34210d0e0ca685979f3a5a94552fbda4303b55d2b6206a20c665
3
+ size 16396
testdata/snapshots/clipped_vertical.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d858f5c4aafd68f2fa4ae6cbeea4ea8443889db40a7c70817734b1edd80c7bd9
3
+ size 16396
testdata/snapshots/clipped_zero_length.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:60d2f81832d645fd3abf309ea419b7c75bfa3516cd69f8105fa35c89a0c58c1d
3
+ size 16396
testdata/snapshots/twocol_diagonal_45.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2dd5a7b9994e85f003fe1c19ca8fdb34e94894ebe9e710124d1fc6b6b31aa1ea
3
+ size 16396
testdata/snapshots/twocol_horizontal.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:afb48702dc248c6fc3a0e6a6dcd603420997b2b894034114e641bfddec57170b
3
+ size 16396
testdata/snapshots/twocol_negative.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f2cb64e70b3dfc6ff185ff08494ffd0f799d872492470611fcea89c53b51518d
3
+ size 16396
testdata/snapshots/twocol_restricted_clip.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:cef5d61f71bc09964371eed8157c000bd0f404678d9bd6b5e78cff68f8379845
3
+ size 16396
testdata/snapshots/twocol_shallow.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:5b1ea09b4e78cd1f0fa1ad38665f3225cc016ff957c680c1a1fe42b656e3ffe6
3
+ size 16396
testdata/snapshots/twocol_steep.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d545b902251a860bd4f6753b0e8b6d8181cd21fc512dddf6fd4d93abf4b9ac94
3
+ size 16396
testdata/snapshots/twocol_subpixel.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1e47b85680ab580348b4abf968d1c4b9dd3b0491f84fd2f95bf919f237b98d1f
3
+ size 16396
testdata/snapshots/twocol_vertical.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f98dec117c9422729adf2ce21d479d8513e3b1a62ef6de8b17a50c27244f4a50
3
+ size 16396