package pdf import "core:testing" @(test) test_blend_mode_names :: proc(t: ^testing.T) { testing.expect_value(t, blend_mode_from_name("Multiply"), Blend_Mode.Multiply) testing.expect_value(t, blend_mode_from_name("Compatible"), Blend_Mode.Normal) testing.expect_value(t, blend_mode_from_name("Luminosity"), Blend_Mode.Luminosity) // An unrecognised /BM is Normal, not an error (ISO 32000-2, 11.3.5.2). testing.expect_value(t, blend_mode_from_name("NotAMode"), Blend_Mode.Normal) testing.expect_value(t, blend_mode_from_name(""), Blend_Mode.Normal) testing.expect(t, blend_mode_is_separable(.Difference), "Difference is separable") testing.expect(t, !blend_mode_is_separable(.Hue), "Hue is not separable") testing.expect(t, !blend_mode_is_separable(.Luminosity), "Luminosity is not separable") } // An all-zero dash array must read as "solid": a dasher fed a pattern that // never advances loops forever. @(test) test_stroke_dash_guard :: proc(t: ^testing.T) { s := STROKE_STATE_DEFAULT testing.expect(t, !stroke_has_dash(&s), "no dash by default") s.dash_count = 2 s.dash[0] = 0 s.dash[1] = 0 testing.expect(t, !stroke_has_dash(&s), "all-zero dash is solid") s.dash[1] = 3 testing.expect(t, stroke_has_dash(&s), "a non-zero entry dashes") s.dash[0] = -1 testing.expect(t, !stroke_has_dash(&s), "a negative entry is invalid, treat as solid") } @(test) test_text_render_mode_predicates :: proc(t: ^testing.T) { testing.expect(t, text_render_mode_fills(.Fill), "") testing.expect(t, text_render_mode_fills(.Fill_Stroke_Clip), "") testing.expect(t, !text_render_mode_fills(.Stroke), "") testing.expect(t, !text_render_mode_fills(.Invisible), "") testing.expect(t, text_render_mode_strokes(.Stroke_Clip), "") testing.expect(t, !text_render_mode_strokes(.Fill_Clip), "") testing.expect(t, text_render_mode_clips(.Clip), "") testing.expect(t, text_render_mode_clips(.Fill_Clip), "") testing.expect(t, !text_render_mode_clips(.Invisible), "") } @(test) test_gstate_defaults :: proc(t: ^testing.T) { gs := gstate_default(MATRIX_IDENTITY) testing.expect_value(t, gs.fill_alpha, 1) testing.expect_value(t, gs.stroke_alpha, 1) testing.expect_value(t, gs.stroke_state.line_width, 1) testing.expect_value(t, gs.stroke_state.miter_limit, 10) testing.expect_value(t, gs.blend, Blend_Mode.Normal) // Tz is a percentage in the file but a fraction here, so the default is 1. testing.expect_value(t, gs.text.horiz_scale, 1) } @(test) test_gstate_stack :: proc(t: ^testing.T) { s := gstate_stack_make() defer gstate_stack_destroy(&s) _, ok := gstate_pop(&s) testing.expect(t, !ok, "popping an empty stack must fail, not underflow") gs := gstate_default(MATRIX_IDENTITY) gs.fill_alpha = 0.5 testing.expect(t, gstate_push(&s, gs), "push should succeed") testing.expect_value(t, gstate_depth(&s), 1) got, ok2 := gstate_pop(&s) testing.expect(t, ok2, "pop should succeed") testing.expect_value(t, got.fill_alpha, 0.5) testing.expect_value(t, gstate_depth(&s), 0) } // A content stream that only ever pushes must hit the cap and be told so, or // the matching pops later underflow and the rest of the page draws wrong. @(test) test_gstate_stack_depth_cap :: proc(t: ^testing.T) { s := gstate_stack_make() defer gstate_stack_destroy(&s) gs := gstate_default(MATRIX_IDENTITY) for _ in 0 ..< MAX_GSTATE_DEPTH { testing.expect(t, gstate_push(&s, gs), "should accept up to the cap") } testing.expect(t, !gstate_push(&s, gs), "must refuse past the cap") testing.expect_value(t, gstate_depth(&s), MAX_GSTATE_DEPTH) } @(test) test_color_make_clamps_count :: proc(t: ^testing.T) { c := color_make(0.1, 0.2, 0.3) testing.expect_value(t, c.n, 3) testing.expect_value(t, c.v[1], 0.2) big: [MAX_COLOR_COMPONENTS + 8]f64 huge := color_make(..big[:]) testing.expect_value(t, huge.n, MAX_COLOR_COMPONENTS) }