129 lines
4.3 KiB
Odin
129 lines
4.3 KiB
Odin
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)
|
|
}
|