91 lines
3.5 KiB
Odin
91 lines
3.5 KiB
Odin
package pdf
|
|||
|
|
|
||
|
|
import "core:testing"
|
||
|
|
|
||
|
|
// Every Device hook is optional: the text device leaves all the path and image
|
||
|
|
// hooks nil, the display-list device leaves the mask hooks nil. The interpreter
|
||
|
|
// goes through the dev_* wrappers precisely so that costs one predictable
|
||
|
|
// branch instead of a crash, so an all-nil device is the case to pin.
|
||
|
|
@(test)
|
||
|
|
test_device_wrappers_tolerate_nil_hooks :: proc(t: ^testing.T) {
|
||
|
|
p := path_make()
|
||
|
|
defer path_destroy(&p)
|
||
|
|
path_rect(&p, 0, 0, 10, 10)
|
||
|
|
|
||
|
|
txt := text_make()
|
||
|
|
defer text_destroy(&txt)
|
||
|
|
|
||
|
|
stroke := STROKE_STATE_DEFAULT
|
||
|
|
paint: Paint
|
||
|
|
|
||
|
|
call_everything :: proc(dev: ^Device, p: ^Path, txt: ^Text, stroke: ^Stroke_State, paint: Paint) {
|
||
|
|
dev_fill_path(dev, p, false, MATRIX_IDENTITY, paint)
|
||
|
|
dev_stroke_path(dev, p, stroke, MATRIX_IDENTITY, paint)
|
||
|
|
dev_clip_path(dev, p, true, MATRIX_IDENTITY)
|
||
|
|
dev_clip_stroke_path(dev, p, stroke, MATRIX_IDENTITY)
|
||
|
|
dev_clip_text(dev, txt, MATRIX_IDENTITY)
|
||
|
|
dev_clip_image_mask(dev, nil, MATRIX_IDENTITY)
|
||
|
|
dev_pop_clip(dev)
|
||
|
|
dev_fill_text(dev, txt, MATRIX_IDENTITY, paint)
|
||
|
|
dev_stroke_text(dev, txt, stroke, MATRIX_IDENTITY, paint)
|
||
|
|
dev_ignore_text(dev, txt, MATRIX_IDENTITY)
|
||
|
|
dev_fill_image(dev, nil, MATRIX_IDENTITY, paint)
|
||
|
|
dev_fill_image_mask(dev, nil, MATRIX_IDENTITY, paint)
|
||
|
|
dev_fill_shade(dev, nil, MATRIX_IDENTITY, paint)
|
||
|
|
dev_begin_mask(dev, RECT_EMPTY, true, paint)
|
||
|
|
dev_end_mask(dev, nil, nil)
|
||
|
|
dev_begin_group(dev, RECT_EMPTY, false, false, .Normal, 1, nil)
|
||
|
|
dev_end_group(dev)
|
||
|
|
_ = dev_begin_tile(dev, RECT_EMPTY, RECT_EMPTY, 1, 1, MATRIX_IDENTITY)
|
||
|
|
dev_end_tile(dev)
|
||
|
|
dev_begin_layer(dev, "layer")
|
||
|
|
dev_end_layer(dev)
|
||
|
|
dev_close(dev)
|
||
|
|
}
|
||
|
|
|
||
|
|
// A device with no hooks at all.
|
||
|
|
empty: Device
|
||
|
|
call_everything(&empty, &p, &txt, &stroke, paint)
|
||
|
|
|
||
|
|
// And no device at all, which is what an interpreter run with a nil sink
|
||
|
|
// must survive.
|
||
|
|
call_everything(nil, &p, &txt, &stroke, paint)
|
||
|
|
|
||
|
|
// begin_tile must report "run the content once" when unimplemented, not a
|
||
|
|
// negative or unbounded count.
|
||
|
|
testing.expect_value(t, dev_begin_tile(&empty, RECT_EMPTY, RECT_EMPTY, 1, 1, MATRIX_IDENTITY), 0)
|
||
|
|
testing.expect_value(t, dev_begin_tile(nil, RECT_EMPTY, RECT_EMPTY, 1, 1, MATRIX_IDENTITY), 0)
|
||
|
|
}
|
||
|
|
|
||
|
|
// The hints let a device tell the interpreter what it can skip -- decoding a
|
||
|
|
// 4000x4000 JPEG to extract text off the page it sits on is pure waste.
|
||
|
|
@(test)
|
||
|
|
test_device_hints :: proc(t: ^testing.T) {
|
||
|
|
dev: Device
|
||
|
|
testing.expect(t, dev_wants_images(&dev), "a device with no hints wants everything")
|
||
|
|
testing.expect(t, dev_wants_shades(&dev), "")
|
||
|
|
|
||
|
|
dev.hints = {.Ignore_Image}
|
||
|
|
testing.expect(t, !dev_wants_images(&dev), "")
|
||
|
|
testing.expect(t, dev_wants_shades(&dev), "one hint must not imply another")
|
||
|
|
|
||
|
|
dev.hints = {.Ignore_Image, .Ignore_Shade}
|
||
|
|
testing.expect(t, !dev_wants_images(&dev), "")
|
||
|
|
testing.expect(t, !dev_wants_shades(&dev), "")
|
||
|
|
|
||
|
|
// A nil device wants nothing, so the interpreter skips the work entirely.
|
||
|
|
testing.expect(t, !dev_wants_images(nil), "")
|
||
|
|
testing.expect(t, !dev_wants_shades(nil), "")
|
||
|
|
}
|
||
|
|
|
||
|
|
@(test)
|
||
|
|
test_text_make_and_destroy :: proc(t: ^testing.T) {
|
||
|
|
txt := text_make()
|
||
|
|
append(&txt.items, Text_Item{gid = 5, unicode = 'A', advance = 500})
|
||
|
|
testing.expect_value(t, len(txt.items), 1)
|
||
|
|
text_destroy(&txt)
|
||
|
|
testing.expect_value(t, len(txt.items), 0)
|
||
|
|
text_destroy(&txt) // idempotent
|
||
|
|
text_destroy(nil)
|
||
|
|
}
|