Quellcode durchsuchen

Handle out-of-bounds correctly in olivec_copy

rexim vor 3 Jahren
Ursprung
Commit
0a3d5e352c
5 geänderte Dateien mit 34 neuen und 13 gelöschten Zeilen
  1. 3 3
      build.sh
  2. 2 1
      demos/squish.c
  3. 9 7
      olive.c
  4. 20 2
      test.c
  5. BIN
      test/copy_out_of_bounds_cut_expected.png

+ 3 - 3
build.sh

@@ -15,14 +15,14 @@ build_vc_demo() {
 
 mkdir -p ./build/
 
-# Build tests
-clang $COMMON_CFLAGS -fsanitize=memory -o ./build/test -Ithirdparty test.c -lm
-
 # Build asserts
 clang $COMMON_CFLAGS -o ./build/png2c -Ithirdparty png2c.c -lm
 mkdir -p ./build/assets/
 ./build/png2c ./assets/tsodinPog.png > ./build/assets/tsodinPog.c
 
+# Build tests
+clang $COMMON_CFLAGS -fsanitize=memory -o ./build/test -Ithirdparty test.c -lm
+
 # Build VC demos
 build_vc_demo triangle &
 build_vc_demo 3d &

+ 2 - 1
demos/squish.c

@@ -28,7 +28,8 @@ Olivec_Canvas render(float dt)
 
     olivec_copy(
         olivec_canvas(png, png_width, png_height, png_width),
-        olivec_subcanvas(dst_canvas, WIDTH/2 - w/2, HEIGHT - h, w, h));
+        dst_canvas,
+        WIDTH/2 - w/2, HEIGHT - h, w, h);
 
     return dst_canvas;
 }

+ 9 - 7
olive.c

@@ -699,15 +699,17 @@ OLIVECDEF void olivec_text(Olivec_Canvas oc, const char *text, int tx, int ty, O
     }
 }
 
-// TODO: olivec_copy does not work correctly with dst out of bounds
 // TODO: bilinear interpolation for olivec_copy
-void olivec_copy(Olivec_Canvas src, Olivec_Canvas dst)
+void olivec_copy(Olivec_Canvas src, Olivec_Canvas dst, int x, int y, int w, int h)
 {
-    for (size_t y = 0; y < dst.height; ++y) {
-        for (size_t x = 0; x < dst.width; ++x) {
-            size_t nx = x*src.width/dst.width;
-            size_t ny = y*src.height/dst.height;
-            olivec_blend_color(&OLIVEC_PIXEL(dst, x, y), OLIVEC_PIXEL(src, nx, ny));
+    int x1, x2, y1, y2;
+    if (olivec_normalize_rect(x, y, w, h, dst.width, dst.height, &x1, &x2, &y1, &y2)) {
+        for (int y = y1; y <= y2; ++y) {
+            for (int x = x1; x <= x2; ++x) {
+                size_t nx = (x - x1)*src.width/w;
+                size_t ny = (y - y1)*src.height/h;
+                olivec_blend_color(&OLIVEC_PIXEL(dst, x, y), OLIVEC_PIXEL(src, nx, ny));
+            }
         }
     }
 }

+ 20 - 2
test.c

@@ -1,9 +1,12 @@
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdint.h>
 #include <stdbool.h>
 #include <string.h>
 #include <errno.h>
 
+#include "./assets/tsodinPog.c"
+
 #define return_defer(value) do { result = (value); goto defer; } while (0)
 #define UNUSED(x) (void)(x)
 #define UNIMPLEMENTED(message) \
@@ -140,7 +143,7 @@ Replay_Result run_test_case(const char *program_path, const Test_Case *tc)
     if (!canvas_stbi_load(expected_file_path, &expected_canvas)) {
         fprintf(stderr, "%s: ERROR: could not read %s: %s\n", tc->id, expected_file_path, stbi_failure_reason());
         if (errno == ENOENT) {
-            fprintf(stderr, "%s: HINT: Consider running `$ %s update` to create it\n", tc->id, program_path);
+            fprintf(stderr, "%s: HINT: Consider running `$ %s update %s` to create it\n", tc->id, program_path, tc->id);
         }
         return(REPLAY_ERRORED);
     }
@@ -463,7 +466,21 @@ Olivec_Canvas test_blending_of_copy(void)
         }
     }
 
-    olivec_copy(src, dst);
+    olivec_copy(src, dst, 0, 0, width, height);
+
+    return dst;
+}
+
+Olivec_Canvas test_copy_out_of_bounds_cut(void)
+{
+    size_t width = 128;
+    size_t height = 128;
+    Olivec_Canvas dst = canvas_alloc(width, height);
+    olivec_fill(dst, 0xFF1818FF);
+    olivec_copy(
+        olivec_canvas(png, png_width, png_height, png_width),
+        dst,
+        width/2, height/2, width, height);
 
     return dst;
 }
@@ -482,6 +499,7 @@ Test_Case test_cases[] = {
     DEFINE_TEST_CASE(line_edge_cases),
     DEFINE_TEST_CASE(frame),
     DEFINE_TEST_CASE(blending_of_copy),
+    DEFINE_TEST_CASE(copy_out_of_bounds_cut),
 };
 #define TEST_CASES_COUNT (sizeof(test_cases)/sizeof(test_cases[0]))
 

BIN
test/copy_out_of_bounds_cut_expected.png