package pdf import "core:testing" @(test) test_bitmap_make_and_bounds :: proc(t: ^testing.T) { bmp, err := bitmap_make(4, 3, 4) testing.expect_value(t, err, Error.None) defer bitmap_destroy(&bmp) testing.expect_value(t, bmp.stride, 16) testing.expect_value(t, len(bmp.pixels), 48) testing.expect_value(t, len(bitmap_row(&bmp, 0)), 16) testing.expect_value(t, len(bitmap_row(&bmp, 2)), 16) testing.expect_value(t, len(bitmap_row(&bmp, 3)), 0) // out of range testing.expect_value(t, len(bitmap_row(&bmp, -1)), 0) off, ok := bitmap_pixel_offset(&bmp, 3, 2) testing.expect(t, ok, "in-range pixel") testing.expect_value(t, off, 2 * 16 + 3 * 4) _, ok2 := bitmap_pixel_offset(&bmp, 4, 0) testing.expect(t, !ok2, "x == width is out of range") } @(test) test_bitmap_rejects_bad_sizes :: proc(t: ^testing.T) { _, e1 := bitmap_make(0, 10, 4) testing.expect_value(t, e1, Error.Invalid_Argument) _, e2 := bitmap_make(10, 10, 5) testing.expect_value(t, e2, Error.Invalid_Argument) _, e3 := bitmap_make(-1, 10, 4) testing.expect_value(t, e3, Error.Invalid_Argument) // A size whose product overflows must be refused, not wrapped. _, e4 := bitmap_make(1 << 20, 1 << 20, 4) testing.expect_value(t, e4, Error.Bitmap_Too_Large) } @(test) test_bitmap_fill_and_clear :: proc(t: ^testing.T) { bmp, _ := bitmap_make(2, 2, 4) defer bitmap_destroy(&bmp) bitmap_fill(&bmp, {1, 2, 3, 4}) testing.expect_value(t, bmp.pixels[0], 1) testing.expect_value(t, bmp.pixels[3], 4) testing.expect_value(t, bmp.pixels[len(bmp.pixels) - 1], 4) bitmap_clear(&bmp, 9) for b in bmp.pixels { testing.expect_value(t, b, 9) } } // Premultiply then unpremultiply must return the original colour for every // alpha where the information survives the round trip. @(test) test_bitmap_premultiply_round_trip :: proc(t: ^testing.T) { bmp, _ := bitmap_make(1, 1, 4) defer bitmap_destroy(&bmp) for a in ([]u8{255, 200, 128, 64, 1}) { bmp.pixels[0] = 200 bmp.pixels[1] = 100 bmp.pixels[2] = 50 bmp.pixels[3] = a bmp.premultiplied = false bitmap_premultiply(&bmp) testing.expect(t, bmp.premultiplied, "should be marked premultiplied") testing.expect(t, bmp.pixels[0] <= 200, "premultiplied value cannot exceed the original") bitmap_unpremultiply(&bmp) testing.expect(t, !bmp.premultiplied, "should be marked straight") // Rounding through 8 bits at low alpha is lossy; the tolerance scales // with 255/alpha, which is the quantisation step of the round trip. tol := int(255 / max(int(a), 1)) + 1 testing.expect(t, abs(int(bmp.pixels[0]) - 200) <= tol, "red survives the round trip") testing.expect(t, abs(int(bmp.pixels[1]) - 100) <= tol, "green survives the round trip") testing.expect_value(t, bmp.pixels[3], a) } } // Fully transparent pixels lose their colour, deliberately: leaving the // multiplied zeros in place makes bilinear filtering drag black into edges. @(test) test_bitmap_unpremultiply_zero_alpha :: proc(t: ^testing.T) { bmp, _ := bitmap_make(1, 1, 4) defer bitmap_destroy(&bmp) bmp.pixels[0] = 77 bmp.pixels[1] = 88 bmp.pixels[2] = 99 bmp.pixels[3] = 0 bmp.premultiplied = true bitmap_unpremultiply(&bmp) testing.expect_value(t, bmp.pixels[0], 0) testing.expect_value(t, bmp.pixels[1], 0) testing.expect_value(t, bmp.pixels[2], 0) testing.expect_value(t, bmp.pixels[3], 0) } @(test) test_bitmap_to_rgba_expands :: proc(t: ^testing.T) { grey, _ := bitmap_make(2, 1, 1) defer bitmap_destroy(&grey) grey.pixels[0] = 10 grey.pixels[1] = 20 rgba, err := bitmap_to_rgba(&grey) testing.expect_value(t, err, Error.None) defer bitmap_destroy(&rgba) testing.expect_value(t, rgba.n, 4) testing.expect_value(t, rgba.pixels[0], 10) testing.expect_value(t, rgba.pixels[1], 10) testing.expect_value(t, rgba.pixels[2], 10) testing.expect_value(t, rgba.pixels[3], 255) testing.expect_value(t, rgba.pixels[4], 20) testing.expect_value(t, rgba.pixels[7], 255) } @(test) test_bitmap_destroy_is_idempotent :: proc(t: ^testing.T) { bmp, _ := bitmap_make(2, 2, 3) bitmap_destroy(&bmp) bitmap_destroy(&bmp) testing.expect_value(t, len(bmp.pixels), 0) }