From 47cba64a43903ea328d635b7460bf70728382e12 Mon Sep 17 00:00:00 2001 From: jorisschellekens Date: Mon, 6 Sep 2021 00:25:22 +0200 Subject: [PATCH] release v2.0.9.1 --- LICENSE.md => LICENSE | 551 +++++++++--------- README.md | 2 +- borb/io/read/any_object_transformer.py | 98 ++++ ...rmer.py => font_dictionary_transformer.py} | 8 +- ....py => function_dictionary_transformer.py} | 4 +- ...rmer.py => ccitt_fax_image_transformer.py} | 4 +- ...y => compressed_jpeg_image_transformer.py} | 4 +- ...rmer.py => grayscale_image_transformer.py} | 4 +- ...nsformer.py => jbig2_image_transformer.py} | 4 +- ...rmer.py => jpeg_2000_image_transformer.py} | 4 +- ...ansformer.py => jpeg_image_transformer.py} | 4 +- ...sformer.py => xmp_metadata_transformer.py} | 8 +- ...ay_transformer.py => array_transformer.py} | 4 +- ...ansformer.py => dictionary_transformer.py} | 4 +- ...m_transformer.py => stream_transformer.py} | 4 +- ...rmer.py => page_dictionary_transformer.py} | 4 +- ...rmer.py => root_dictionary_transformer.py} | 8 +- ...r_transformer.py => number_transformer.py} | 4 +- ...g_transformer.py => string_transformer.py} | 4 +- borb/io/read/read_any_object_transformer.py | 116 ---- ...ransformer.py => reference_transformer.py} | 6 +- ...ref_transformer.py => xref_transformer.py} | 8 +- ...ead_base_transformer.py => transformer.py} | 10 +- borb/io/write/any_object_transformer.py | 85 +++ ...ransformer.py => ascii_art_transformer.py} | 6 +- borb/io/write/ascii_art/ascii_logo.txt | 2 +- borb/io/write/document/__init__.py | 43 ++ .../document_transformer.py} | 10 +- ...ge_transformer.py => image_transformer.py} | 6 +- ...ay_transformer.py => array_transformer.py} | 6 +- ...ansformer.py => dictionary_transformer.py} | 6 +- ...m_transformer.py => stream_transformer.py} | 6 +- ...age_transformer.py => page_transformer.py} | 8 +- ...es_transformer.py => pages_transformer.py} | 8 +- ..._transformer.py => boolean_transformer.py} | 6 +- ...ame_transformer.py => name_transformer.py} | 6 +- ...r_transformer.py => number_transformer.py} | 6 +- ...g_transformer.py => string_transformer.py} | 6 +- ...ransformer.py => reference_transformer.py} | 6 +- ...ref_transformer.py => xref_transformer.py} | 6 +- ...ite_base_transformer.py => transformer.py} | 12 +- borb/io/write/write_any_object_transformer.py | 85 --- ..._xmp_transformer.py => xmp_transformer.py} | 6 +- borb/pdf/canvas/font/glyph_line.py | 7 +- borb/pdf/pdf.py | 4 +- .../ocr/ocr_as_optional_content_group.py | 2 +- release_notes.md | 17 +- setup.py | 2 +- .../output.pdf | Bin 5147 -> 5147 bytes .../test_add_circle_annotation/output.pdf | Bin 1990 -> 1989 bytes .../output_001.pdf | Bin 2086 -> 2087 bytes .../output_002.pdf | Bin 2453 -> 2453 bytes .../output_001.pdf | Bin 2084 -> 2086 bytes .../output_002.pdf | Bin 2410 -> 2409 bytes .../test_add_line_annotation/output_001.pdf | Bin 2075 -> 2075 bytes .../test_add_line_annotation/output_002.pdf | Bin 2364 -> 2363 bytes tests/output/test_add_outline/output_001.pdf | Bin 2603 -> 2602 bytes tests/output/test_add_outline/output_002.pdf | Bin 3573 -> 3574 bytes .../output.pdf | Bin 22428 -> 22428 bytes .../output.png | Bin 15128 -> 15118 bytes .../output.pdf | Bin 22752 -> 22752 bytes .../test_add_redact_annotation/output_001.pdf | Bin 2084 -> 2083 bytes .../test_add_redact_annotation/output_002.pdf | Bin 2550 -> 2550 bytes .../test_add_redact_annotation/output_003.pdf | Bin 78585 -> 78585 bytes .../test_add_redact_annotation/output_004.pdf | Bin 13156 -> 13156 bytes .../test_add_redact_annotation/output_005.pdf | Bin 13666 -> 13666 bytes .../output_001.pdf | Bin 2108 -> 2107 bytes .../output_002.pdf | Bin 2169 -> 2169 bytes .../test_add_square_annotation/output.pdf | Bin 1990 -> 1989 bytes .../output_001.pdf | Bin 386215 -> 386215 bytes .../output_002.pdf | Bin 78005 -> 78005 bytes .../output_001.pdf | Bin 2086 -> 2086 bytes .../output_002.pdf | Bin 2655 -> 2655 bytes .../output_001.pdf | Bin 2086 -> 2086 bytes .../output_002.pdf | Bin 2585 -> 2585 bytes .../output.pdf | Bin 30583 -> 30583 bytes .../test_add_text_annotation/output_001.pdf | Bin 2074 -> 2074 bytes .../test_add_text_annotation/output_002.pdf | Bin 3049 -> 3049 bytes .../output_001.pdf | Bin 2087 -> 2086 bytes .../output_002.pdf | Bin 2504 -> 2505 bytes .../test_analogous_color_scheme/output.pdf | Bin 6843 -> 6843 bytes .../test_append_embedded_file/output_001.pdf | Bin 2071 -> 2071 bytes .../test_append_embedded_file/output_002.pdf | Bin 2847 -> 2847 bytes .../output_001.pdf | Bin 2122 -> 2121 bytes .../output_002.pdf | Bin 2604 -> 2605 bytes .../output_003.pdf | Bin 2927 -> 2927 bytes .../output_004.pdf | Bin 2063 -> 2063 bytes .../output_005.pdf | Bin 2545 -> 2546 bytes .../output_006.pdf | Bin 2776 -> 2776 bytes .../output_001.pdf | Bin 2129 -> 2128 bytes .../output_002.pdf | Bin 2127 -> 2128 bytes .../test_concat_documents/output_000.pdf | Bin 1739 -> 1739 bytes .../test_concat_documents/output_001.pdf | Bin 298819 -> 298819 bytes .../test_concat_documents/output_002.pdf | Bin 298819 -> 298819 bytes .../test_count_annotations/output_001.pdf | Bin 2121 -> 2121 bytes .../test_count_annotations/output_002.pdf | Bin 2587 -> 2587 bytes .../output_001.pdf | Bin 2619 -> 2619 bytes tests/output/test_detect_table/input_000.pdf | Bin 2182 -> 2181 bytes tests/output/test_detect_table/input_001.pdf | Bin 2269 -> 2266 bytes tests/output/test_detect_table/input_002.pdf | Bin 2247 -> 2247 bytes tests/output/test_detect_table/input_003.pdf | Bin 2238 -> 2238 bytes tests/output/test_detect_table/input_004.pdf | Bin 2308 -> 2308 bytes tests/output/test_detect_table/input_005.pdf | Bin 2336 -> 2336 bytes tests/output/test_detect_table/input_006.pdf | Bin 2483 -> 2482 bytes tests/output/test_detect_table/output_000.pdf | Bin 3574 -> 3573 bytes tests/output/test_detect_table/output_001.pdf | Bin 4612 -> 4612 bytes tests/output/test_detect_table/output_002.pdf | Bin 4399 -> 4399 bytes tests/output/test_detect_table/output_003.pdf | Bin 4391 -> 4390 bytes tests/output/test_detect_table/output_004.pdf | Bin 4846 -> 4845 bytes tests/output/test_detect_table/output_005.pdf | Bin 5067 -> 5067 bytes tests/output/test_detect_table/output_006.pdf | Bin 6184 -> 6183 bytes .../example_html_input_000.pdf | Bin 3232 -> 3232 bytes .../example_html_input_001.pdf | Bin 2168 -> 2168 bytes .../example_html_input_002.pdf | Bin 1959 -> 1959 bytes .../example_html_input_003.pdf | Bin 105858 -> 105858 bytes .../example_html_input_004.pdf | Bin 105639 -> 105639 bytes .../example_html_input_005.pdf | Bin 2906 -> 2906 bytes .../example_html_input_006.pdf | Bin 105820 -> 105820 bytes .../example_html_input_007.pdf | Bin 55770 -> 55770 bytes .../example_html_input_008.pdf | Bin 2645 -> 2645 bytes .../example_html_input_009.pdf | Bin 2979 -> 2979 bytes .../example_html_input_010.pdf | Bin 106883 -> 106883 bytes .../example_html_input_011.pdf | Bin 2300 -> 2300 bytes .../example_html_input_012.pdf | Bin 1809 -> 1809 bytes .../example_html_input_013.pdf | Bin 2108 -> 2108 bytes .../example_html_input_014.pdf | Bin 1748 -> 1748 bytes .../example-markdown-input-001.md.pdf | Bin 6022 -> 6022 bytes .../example-markdown-input-002.md.pdf | Bin 8421 -> 8421 bytes .../example-markdown-input-003.md.pdf | Bin 9883 -> 9883 bytes .../example-markdown-input-004.md.pdf | Bin 8086 -> 8086 bytes .../example-markdown-input-005.md.pdf | Bin 6487 -> 6487 bytes .../example-markdown-input-006.md.pdf | Bin 6903 -> 6903 bytes .../example-markdown-input-007.md.pdf | Bin 3412 -> 3412 bytes .../example-markdown-input-008.md.pdf | Bin 7076 -> 7076 bytes .../example-markdown-input-009.md.pdf | Bin 131858 -> 131858 bytes .../test_export_pdf_to_jpg/output_001.jpg | Bin 66894 -> 64207 bytes .../test_export_pdf_to_jpg/output_002.jpg | Bin 66894 -> 64207 bytes .../output/test_extract_colors/output_001.pdf | Bin 120034 -> 120034 bytes .../output/test_extract_colors/output_002.pdf | Bin 15508 -> 15508 bytes .../test_extract_courier_text/output_001.pdf | Bin 2247 -> 2247 bytes .../test_extract_font_names/output_001.pdf | Bin 2475 -> 2476 bytes .../test_extract_font_names/output_002.pdf | Bin 1928 -> 1927 bytes .../test_extract_keywords/output_001.pdf | Bin 2544 -> 2544 bytes .../test_extract_keywords/output_002.pdf | Bin 1987 -> 1987 bytes .../test_extract_keywords/output_003.pdf | Bin 1991 -> 1991 bytes .../test_extract_red_text/output_001.pdf | Bin 2112 -> 2111 bytes .../output/test_extract_regex/output_001.pdf | Bin 2106 -> 2105 bytes .../output/test_extract_regex/output_002.pdf | Bin 2353 -> 2352 bytes tests/output/test_extract_text/output_001.pdf | Bin 2093 -> 2093 bytes .../output.pdf | Bin 34170 -> 34494 bytes .../output.pdf | Bin 4666 -> 4665 bytes .../output_001.pdf | Bin 219337 -> 219337 bytes .../test_line_height_parameter/output_001.pdf | Bin 1919 -> 1918 bytes .../test_line_height_parameter/output_002.pdf | Bin 1916 -> 1916 bytes tests/output/test_modify_image/output_001.pdf | Bin 485774 -> 485773 bytes tests/output/test_modify_image/output_002.pdf | Bin 461153 -> 461153 bytes tests/output/test_open_document/output.pdf | Bin 12236 -> 12235 bytes .../test_optimize_images/output_001.pdf | Bin 63426 -> 63426 bytes .../output_001.pdf | Bin 2215 -> 2215 bytes .../output_002.pdf | Bin 2701 -> 2701 bytes .../output_003.pdf | Bin 2922 -> 2918 bytes .../test_remove_annotation/output_001.pdf | Bin 2181 -> 2180 bytes .../test_remove_annotation/output_002.pdf | Bin 2646 -> 2646 bytes .../test_remove_annotation/output_003.pdf | Bin 2180 -> 2180 bytes tests/output/test_remove_page/output_001.pdf | Bin 5187 -> 5186 bytes tests/output/test_remove_page/output_002.pdf | Bin 3878 -> 3878 bytes tests/output/test_remove_page/output_003.pdf | Bin 4459 -> 4459 bytes tests/output/test_remove_page/output_004.pdf | Bin 4459 -> 4459 bytes tests/output/test_rotate_page/output_001.pdf | Bin 2087 -> 2087 bytes tests/output/test_rotate_page/output_002.pdf | Bin 2098 -> 2098 bytes tests/output/test_rotate_page/output_003.pdf | Bin 2099 -> 2099 bytes .../output.pdf | Bin 6862 -> 6862 bytes .../output.pdf | Bin 8078 -> 8078 bytes .../output.pdf | Bin 8086 -> 8085 bytes .../test_triadic_color_scheme/output.pdf | Bin 6828 -> 6828 bytes .../test_write_2_scatter_plots/output.pdf | Bin 36977 -> 37078 bytes .../test_write_3d_density_chart/output.pdf | Bin 22528 -> 22678 bytes .../test_write_3d_surface_plot/output.pdf | Bin 25873 -> 25872 bytes .../test_write_all_types_barcode/output.pdf | Bin 243380 -> 243406 bytes tests/output/test_write_battleship/output.pdf | Bin 60398 -> 60398 bytes tests/output/test_write_blobs/output.pdf | Bin 267453 -> 262151 bytes .../test_write_check_box/output_001.pdf | Bin 1860 -> 1860 bytes .../test_write_check_box/output_002.pdf | Bin 5874 -> 5874 bytes .../test_write_chunk_of_text/output.pdf | Bin 1748 -> 1747 bytes .../output.pdf | Bin 1821 -> 1821 bytes .../output.pdf | Bin 1890 -> 1889 bytes .../test_write_chunks_of_text/output_001.pdf | Bin 2557 -> 2556 bytes .../test_write_chunks_of_text/output_002.pdf | Bin 2567 -> 2567 bytes .../test_write_chunks_of_text/output_003.pdf | Bin 2567 -> 2567 bytes .../test_write_chunks_of_text/output_004.pdf | Bin 2569 -> 2568 bytes .../test_write_chunks_of_text/output_005.pdf | Bin 2612 -> 2612 bytes .../output.pdf | Bin 3584 -> 3584 bytes .../test_write_code_128_barcode/output.pdf | Bin 16199 -> 16201 bytes .../output.pdf | Bin 15718 -> 15715 bytes tests/output/test_write_codeblock/output.pdf | Bin 3108 -> 3107 bytes .../output/test_write_dragon_curve/output.pdf | Bin 35945 -> 35944 bytes .../test_write_drop_down_list/output_001.pdf | Bin 1946 -> 1946 bytes .../test_write_drop_down_list/output_002.pdf | Bin 5162 -> 5162 bytes tests/output/test_write_emoji/output.pdf | Bin 6454 -> 6453 bytes .../test_write_empty_document/output.pdf | Bin 801 -> 801 bytes .../output_001.pdf | Bin 2203 -> 2203 bytes .../output_002.pdf | Bin 2107 -> 2107 bytes .../output_003.pdf | Bin 1982 -> 1982 bytes .../output_004.pdf | Bin 2163 -> 2162 bytes .../output_005.pdf | Bin 2289 -> 2288 bytes .../test_write_flexi_table/output_001.pdf | Bin 2197 -> 2197 bytes .../test_write_flexi_table/output_002.pdf | Bin 2107 -> 2107 bytes .../test_write_flexi_table/output_003.pdf | Bin 1972 -> 1971 bytes .../test_write_flexi_table/output_004.pdf | Bin 2158 -> 2158 bytes .../test_write_flexi_table/output_005.pdf | Bin 2288 -> 2288 bytes .../output.pdf | Bin 9571 -> 9570 bytes .../test_write_flowchart_line_art/output.pdf | Bin 30745 -> 30745 bytes .../test_write_grayscale_image/output.pdf | Bin 476279 -> 476279 bytes .../output.pdf | Bin 2228 -> 2227 bytes .../output/test_write_image_by_url/output.pdf | Bin 485807 -> 485806 bytes .../output.pdf | Bin 485814 -> 485814 bytes .../test_write_incomplete_table/output.pdf | Bin 2215 -> 2215 bytes .../output.pdf | Bin 2356 -> 2355 bytes .../output.pdf | Bin 2334 -> 2332 bytes .../output.pdf | Bin 2356 -> 2354 bytes .../test_write_lissajours_line_art/output.pdf | Bin 131512 -> 131512 bytes .../test_write_long_unordered_list/output.pdf | Bin 2143 -> 2143 bytes .../test_write_multiple_pages/output.pdf | Bin 2466 -> 2465 bytes .../test_write_nested_ordered_list/output.pdf | Bin 1895 -> 1894 bytes .../output.pdf | Bin 1983 -> 1982 bytes .../test_write_ordered_list/output_001.pdf | Bin 1827 -> 1827 bytes .../test_write_ordered_list/output_002.pdf | Bin 1828 -> 1828 bytes tests/output/test_write_paragraph/output.pdf | Bin 2343 -> 2343 bytes .../test_write_paragraph_alignment/output.pdf | Bin 40913 -> 40913 bytes .../output.pdf | Bin 1784 -> 1784 bytes .../output.pdf | Bin 2166 -> 2166 bytes .../output_001.pdf | Bin 2019 -> 2019 bytes .../output_002.pdf | Bin 2348 -> 2348 bytes .../output.pdf | Bin 2362 -> 2362 bytes .../output.pdf | Bin 2529 -> 2529 bytes .../output.pdf | Bin 2496 -> 2496 bytes .../output.pdf | Bin 2934 -> 2934 bytes .../output.pdf | Bin 2336 -> 2336 bytes .../output.pdf | Bin 1915 -> 1915 bytes .../output_001.pdf | Bin 2089 -> 2088 bytes .../output_002.pdf | Bin 2089 -> 2088 bytes .../output.pdf | Bin 1892 -> 1892 bytes .../output.pdf | Bin 5146 -> 5145 bytes .../output.png | Bin 93408 -> 93412 bytes .../output.pdf | Bin 4186 -> 4186 bytes .../output.pdf | Bin 18346 -> 15457 bytes tests/output/test_write_pil_image/output.pdf | Bin 485804 -> 485804 bytes .../test_write_png_image_by_url/output.pdf | Bin 9589 -> 9589 bytes tests/output/test_write_radar_plot/output.pdf | Bin 21242 -> 21242 bytes .../test_write_table_with_col_span/output.pdf | Bin 2371 -> 2372 bytes .../test_write_table_with_image/output.pdf | Bin 8314253 -> 8314252 bytes .../output.pdf | Bin 2466 -> 2466 bytes .../output.pdf | Bin 8554 -> 8552 bytes .../test_write_table_with_row_span/output.pdf | Bin 2307 -> 2306 bytes .../output.pdf | Bin 58693 -> 58693 bytes .../test_write_tents_and_trees/output.pdf | Bin 62585 -> 62585 bytes .../test_write_text_area/output_001.pdf | Bin 2335 -> 2334 bytes .../test_write_text_area/output_002.pdf | Bin 3249 -> 3249 bytes .../test_write_text_field/output_001.pdf | Bin 2328 -> 2327 bytes .../test_write_text_field/output_002.pdf | Bin 3228 -> 3227 bytes .../test_write_unordered_list/output.pdf | Bin 1947 -> 1947 bytes .../output.pdf | Bin 2274 -> 2274 bytes .../output_001.pdf | Bin 177435 -> 177435 bytes .../output_002.pdf | Bin 14789 -> 14789 bytes .../output_002.png | Bin 20052 -> 20044 bytes .../output_003.pdf | Bin 82476 -> 82476 bytes tests/output/test_write_xl_image/output.pdf | Bin 1760 -> 1759 bytes tests/toolkit/image/test_optimize_images.py | 2 +- ...est_extract_text_from_self_made_invoice.py | 2 +- 269 files changed, 633 insertions(+), 595 deletions(-) rename LICENSE.md => LICENSE (53%) create mode 100644 borb/io/read/any_object_transformer.py rename borb/io/read/font/{read_font_dictionary_transformer.py => font_dictionary_transformer.py} (93%) rename borb/io/read/function/{read_function_dictionary_transformer.py => function_dictionary_transformer.py} (95%) rename borb/io/read/image/{read_ccitt_fax_image_transformer.py => ccitt_fax_image_transformer.py} (94%) rename borb/io/read/image/{read_compressed_jpeg_image_transformer.py => compressed_jpeg_image_transformer.py} (95%) rename borb/io/read/image/{read_grayscale_image_transformer.py => grayscale_image_transformer.py} (95%) rename borb/io/read/image/{read_jbig2_image_transformer.py => jbig2_image_transformer.py} (94%) rename borb/io/read/image/{read_jpeg_2000_image_transformer.py => jpeg_2000_image_transformer.py} (94%) rename borb/io/read/image/{read_jpeg_image_transformer.py => jpeg_image_transformer.py} (94%) rename borb/io/read/metadata/{read_xmp_metadata_transformer.py => xmp_metadata_transformer.py} (93%) rename borb/io/read/object/{read_array_transformer.py => array_transformer.py} (92%) rename borb/io/read/object/{read_dictionary_transformer.py => dictionary_transformer.py} (92%) rename borb/io/read/object/{read_stream_transformer.py => stream_transformer.py} (94%) rename borb/io/read/page/{read_page_dictionary_transformer.py => page_dictionary_transformer.py} (96%) rename borb/io/read/page/{read_root_dictionary_transformer.py => root_dictionary_transformer.py} (91%) rename borb/io/read/primitive/{read_number_transformer.py => number_transformer.py} (89%) rename borb/io/read/primitive/{read_string_transformer.py => string_transformer.py} (90%) delete mode 100644 borb/io/read/read_any_object_transformer.py rename borb/io/read/reference/{read_reference_transformer.py => reference_transformer.py} (95%) rename borb/io/read/reference/{read_xref_transformer.py => xref_transformer.py} (97%) rename borb/io/read/{read_base_transformer.py => transformer.py} (92%) create mode 100644 borb/io/write/any_object_transformer.py rename borb/io/write/ascii_art/{write_ascii_art_transformer.py => ascii_art_transformer.py} (93%) create mode 100644 borb/io/write/document/__init__.py rename borb/io/write/{write_pdf_transformer.py => document/document_transformer.py} (94%) rename borb/io/write/image/{write_image_transformer.py => image_transformer.py} (97%) rename borb/io/write/object/{write_array_transformer.py => array_transformer.py} (96%) rename borb/io/write/object/{write_dictionary_transformer.py => dictionary_transformer.py} (96%) rename borb/io/write/object/{write_stream_transformer.py => stream_transformer.py} (96%) rename borb/io/write/page/{write_page_transformer.py => page_transformer.py} (85%) rename borb/io/write/page/{write_pages_transformer.py => pages_transformer.py} (85%) rename borb/io/write/primitive/{write_boolean_transformer.py => boolean_transformer.py} (89%) rename borb/io/write/primitive/{write_name_transformer.py => name_transformer.py} (88%) rename borb/io/write/primitive/{write_number_transformer.py => number_transformer.py} (90%) rename borb/io/write/primitive/{write_string_transformer.py => string_transformer.py} (92%) rename borb/io/write/reference/{write_reference_transformer.py => reference_transformer.py} (91%) rename borb/io/write/reference/{write_xref_transformer.py => xref_transformer.py} (97%) rename borb/io/write/{write_base_transformer.py => transformer.py} (95%) delete mode 100644 borb/io/write/write_any_object_transformer.py rename borb/io/write/xmp/{write_xmp_transformer.py => xmp_transformer.py} (94%) diff --git a/LICENSE.md b/LICENSE similarity index 53% rename from LICENSE.md rename to LICENSE index 6124431c9..f288702d2 100644 --- a/LICENSE.md +++ b/LICENSE @@ -1,127 +1,137 @@ -GNU Affero General Public License -================================= + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 -_Version 3, 19 November 2007_ -_Copyright © 2007 Free Software Foundation, Inc. <>_ + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. -Everyone is permitted to copy and distribute verbatim copies -of this license document, but changing it is not allowed. + Preamble -## Preamble + The GNU General Public License is a free, copyleft license for +software and other kinds of works. -The GNU Affero General Public License is a free, copyleft license for -software and other kinds of works, specifically designed to ensure -cooperation with the community in the case of network server software. - -The licenses for most software and other practical works are designed + The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, -our General Public Licenses are intended to guarantee your freedom to +the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free -software for all its users. +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. -When we speak of free software, we are referring to freedom, not + When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. -Developers that use our General Public Licenses protect your rights -with two steps: **(1)** assert copyright on the software, and **(2)** offer -you this License which gives you legal permission to copy, distribute -and/or modify the software. - -A secondary benefit of defending all users' freedom is that -improvements made in alternate versions of the program, if they -receive widespread use, become available for other developers to -incorporate. Many developers of free software are heartened and -encouraged by the resulting cooperation. However, in the case of -software used on network servers, this result may fail to come about. -The GNU General Public License permits making a modified version and -letting the public access it on a server without ever releasing its -source code to the public. - -The GNU Affero General Public License is designed specifically to -ensure that, in such cases, the modified source code becomes available -to the community. It requires the operator of a network server to -provide the source code of the modified version running there to the -users of that server. Therefore, public use of a modified version, on -a publicly accessible server, gives the public access to the source -code of the modified version. - -An older license, called the Affero General Public License and -published by Affero, was designed to accomplish similar goals. This is -a different license, not a version of the Affero GPL, but Affero has -released a new version of the Affero GPL which permits relicensing under -this license. - -The precise terms and conditions for copying, distribution and + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and modification follow. -## TERMS AND CONDITIONS + TERMS AND CONDITIONS -### 0. Definitions + 0. Definitions. -“This License” refers to version 3 of the GNU Affero General Public License. + "This License" refers to version 3 of the GNU General Public License. -“Copyright” also means copyright-like laws that apply to other kinds of + "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. -“The Program” refers to any copyrightable work licensed under this -License. Each licensee is addressed as “you”. “Licensees” and -“recipients” may be individuals or organizations. + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. -To “modify” a work means to copy from or adapt all or part of the work + To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a “modified version” of the -earlier work or a work “based on” the earlier work. +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. -A “covered work” means either the unmodified Program or a work based + A "covered work" means either the unmodified Program or a work based on the Program. -To “propagate” a work means to do anything with it that, without + To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. -To “convey” a work means any kind of propagation that enables other + To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. -An interactive user interface displays “Appropriate Legal Notices” + An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible -feature that **(1)** displays an appropriate copyright notice, and **(2)** +feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. -### 1. Source Code + 1. Source Code. -The “source code” for a work means the preferred form of the work -for making modifications to it. “Object code” means any non-source + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source form of a work. -A “Standard Interface” means an interface that either is an official + A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. -The “System Libraries” of an executable work include anything, other -than the work as a whole, that **(a)** is included in the normal form of + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major -Component, and **(b)** serves only to enable use of the work with that +Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A -“Major Component”, in this context, means a major essential component +"Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. -The “Corresponding Source” for a work in object code form means all + The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's @@ -134,16 +144,16 @@ linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. -The Corresponding Source need not include anything that users + The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. -The Corresponding Source for a work in source code form is that + The Corresponding Source for a work in source code form is that same work. -### 2. Basic Permissions + 2. Basic Permissions. -All rights granted under this License are granted for the term of + All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a @@ -151,7 +161,7 @@ covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. -You may make, run and propagate covered works that you do not + You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you @@ -162,19 +172,19 @@ for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. -Conveying under any other circumstances is permitted solely under + Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. -### 3. Protecting Users' Legal Rights From Anti-Circumvention Law + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. -No covered work shall be deemed part of an effective technological + No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. -When you convey a covered work, you waive any legal power to forbid + When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or @@ -182,9 +192,9 @@ modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. -### 4. Conveying Verbatim Copies + 4. Conveying Verbatim Copies. -You may convey verbatim copies of the Program's source code as you + You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any @@ -192,97 +202,104 @@ non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. -You may charge any price or no price for each copy that you convey, + You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. -### 5. Conveying Modified Source Versions + 5. Conveying Modified Source Versions. -You may convey a work based on the Program, or the modifications to + You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: -* **a)** The work must carry prominent notices stating that you modified -it, and giving a relevant date. -* **b)** The work must carry prominent notices stating that it is -released under this License and any conditions added under section 7. -This requirement modifies the requirement in section 4 to -“keep intact all notices”. -* **c)** You must license the entire work, as a whole, under this -License to anyone who comes into possession of a copy. This -License will therefore apply, along with any applicable section 7 -additional terms, to the whole of the work, and all its parts, -regardless of how they are packaged. This License gives no -permission to license the work in any other way, but it does not -invalidate such permission if you have separately received it. -* **d)** If the work has interactive user interfaces, each must display -Appropriate Legal Notices; however, if the Program has interactive -interfaces that do not display Appropriate Legal Notices, your -work need not make them do so. - -A compilation of a covered work with other separate and independent + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an -“aggregate” if the compilation and its resulting copyright are not +"aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. -### 6. Conveying Non-Source Forms + 6. Conveying Non-Source Forms. -You may convey a covered work in object code form under the terms + You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: -* **a)** Convey the object code in, or embodied in, a physical product -(including a physical distribution medium), accompanied by the -Corresponding Source fixed on a durable physical medium -customarily used for software interchange. -* **b)** Convey the object code in, or embodied in, a physical product -(including a physical distribution medium), accompanied by a -written offer, valid for at least three years and valid for as -long as you offer spare parts or customer support for that product -model, to give anyone who possesses the object code either **(1)** a -copy of the Corresponding Source for all the software in the -product that is covered by this License, on a durable physical -medium customarily used for software interchange, for a price no -more than your reasonable cost of physically performing this -conveying of source, or **(2)** access to copy the -Corresponding Source from a network server at no charge. -* **c)** Convey individual copies of the object code with a copy of the -written offer to provide the Corresponding Source. This -alternative is allowed only occasionally and noncommercially, and -only if you received the object code with such an offer, in accord -with subsection 6b. -* **d)** Convey the object code by offering access from a designated -place (gratis or for a charge), and offer equivalent access to the -Corresponding Source in the same way through the same place at no -further charge. You need not require recipients to copy the -Corresponding Source along with the object code. If the place to -copy the object code is a network server, the Corresponding Source -may be on a different server (operated by you or a third party) -that supports equivalent copying facilities, provided you maintain -clear directions next to the object code saying where to find the -Corresponding Source. Regardless of what server hosts the -Corresponding Source, you remain obligated to ensure that it is -available for as long as needed to satisfy these requirements. -* **e)** Convey the object code using peer-to-peer transmission, provided -you inform other peers where the object code and Corresponding -Source of the work are being offered to the general public at no -charge under subsection 6d. - -A separable portion of the object code, whose source code is excluded + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. -A “User Product” is either **(1)** a “consumer product”, which means any + A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, -or household purposes, or **(2)** anything designed or sold for incorporation +or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, “normally used” refers to a +product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product @@ -290,7 +307,7 @@ is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. -“Installation Information” for a User Product means any methods, + "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must @@ -298,7 +315,7 @@ suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. -If you convey an object code work under this section in, or with, or + If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a @@ -309,7 +326,7 @@ if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). -The requirement to provide Installation Information does not include a + The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a @@ -317,15 +334,15 @@ network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. -Corresponding Source conveyed, and Installation Information provided, + Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. -### 7. Additional Terms + 7. Additional Terms. -“Additional permissions” are terms that supplement the terms of this + "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent @@ -334,37 +351,42 @@ apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. -When you convey a copy of a covered work, you may at your option + When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. -Notwithstanding any other provision of this License, for material you + Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: -* **a)** Disclaiming warranty or limiting liability differently from the -terms of sections 15 and 16 of this License; or -* **b)** Requiring preservation of specified reasonable legal notices or -author attributions in that material or in the Appropriate Legal -Notices displayed by works containing it; or -* **c)** Prohibiting misrepresentation of the origin of that material, or -requiring that modified versions of such material be marked in -reasonable ways as different from the original version; or -* **d)** Limiting the use for publicity purposes of names of licensors or -authors of the material; or -* **e)** Declining to grant rights under trademark law for use of some -trade names, trademarks, or service marks; or -* **f)** Requiring indemnification of licensors and authors of that -material by anyone who conveys the material (or modified versions of -it) with contractual assumptions of liability to the recipient, for -any liability that these contractual assumptions directly impose on -those licensors and authors. - -All other non-permissive additional terms are considered “further -restrictions” within the meaning of section 10. If the Program as you + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains @@ -373,46 +395,46 @@ License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. -If you add terms to a covered work in accord with this section, you + If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. -Additional terms, permissive or non-permissive, may be stated in the + Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. -### 8. Termination + 8. Termination. -You may not propagate or modify a covered work except as expressly + You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). -However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated **(a)** + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and **(b)** permanently, if the copyright +finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. -Moreover, your license from a particular copyright holder is + Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. -Termination of your rights under this section does not terminate the + Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. -### 9. Acceptance Not Required for Having Copies + 9. Acceptance Not Required for Having Copies. -You are not required to accept this License in order to receive or + You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, @@ -421,14 +443,14 @@ modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. -### 10. Automatic Licensing of Downstream Recipients + 10. Automatic Licensing of Downstream Recipients. -Each time you convey a covered work, the recipient automatically + Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. -An “entity transaction” is a transaction transferring control of an + An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that @@ -438,7 +460,7 @@ give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. -You may not impose any further restrictions on the exercise of the + You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation @@ -446,49 +468,49 @@ rights granted under this License, and you may not initiate litigation any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. -### 11. Patents + 11. Patents. -A “contributor” is a copyright holder who authorizes use under this + A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's “contributor version”. +work thus licensed is called the contributor's "contributor version". -A contributor's “essential patent claims” are all patent claims + A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For -purposes of this definition, “control” includes the right to grant +purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. -Each contributor grants you a non-exclusive, worldwide, royalty-free + Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. -In the following three paragraphs, a “patent license” is any express + In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to -sue for patent infringement). To “grant” such a patent license to a +sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. -If you convey a covered work, knowingly relying on a patent license, + If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, -then you must either **(1)** cause the Corresponding Source to be so -available, or **(2)** arrange to deprive yourself of the benefit of the -patent license for this particular work, or **(3)** arrange, in a manner +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent -license to downstream recipients. “Knowingly relying” means you have +license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. -If, pursuant to or in connection with a single transaction or + If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify @@ -496,7 +518,7 @@ or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. -A patent license is “discriminatory” if it does not include within + A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered @@ -505,19 +527,19 @@ in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory -patent license **(a)** in connection with copies of the covered work -conveyed by you (or copies made from those copies), or **(b)** primarily +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. -Nothing in this License shall be construed as excluding or limiting + Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. -### 12. No Surrender of Others' Freedom + 12. No Surrender of Others' Freedom. -If conditions are imposed on you (whether by court order, agreement or + If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this @@ -527,67 +549,57 @@ to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. -### 13. Remote Network Interaction; Use with the GNU General Public License - -Notwithstanding any other provision of this License, if you modify the -Program, your modified version must prominently offer all users -interacting with it remotely through a computer network (if your version -supports such interaction) an opportunity to receive the Corresponding -Source of your version by providing access to the Corresponding Source -from a network server at no charge, through some standard or customary -means of facilitating copying of software. This Corresponding Source -shall include the Corresponding Source for any work covered by version 3 -of the GNU General Public License that is incorporated pursuant to the -following paragraph. + 13. Use with the GNU Affero General Public License. -Notwithstanding any other provision of this License, you have + Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed -under version 3 of the GNU General Public License into a single +under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, -but the work with which it is combined will remain governed by version -3 of the GNU General Public License. +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. -### 14. Revised Versions of this License + 14. Revised Versions of this License. -The Free Software Foundation may publish revised and/or new versions of -the GNU Affero General Public License from time to time. Such new versions -will be similar in spirit to the present version, but may differ in detail to + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to address new problems or concerns. -Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU Affero General -Public License “or any later version” applies to it, you have the + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the -GNU Affero General Public License, you may choose any version ever published +GNU General Public License, you may choose any version ever published by the Free Software Foundation. -If the Program specifies that a proxy can decide which future -versions of the GNU Affero General Public License can be used, that proxy's + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. -Later license versions may give you additional or different + Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. -### 15. Disclaimer of Warranty + 15. Disclaimer of Warranty. -THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. -### 16. Limitation of Liability + 16. Limitation of Liability. -IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE @@ -597,55 +609,66 @@ PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. -### 17. Interpretation of Sections 15 and 16 + 17. Interpretation of Sections 15 and 16. -If the disclaimer of warranty and limitation of liability provided + If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. -_END OF TERMS AND CONDITIONS_ + END OF TERMS AND CONDITIONS -## How to Apply These Terms to Your New Programs + How to Apply These Terms to Your New Programs -If you develop a new program, and you want it to be of the greatest + If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. -To do so, attach the following notices to the program. It is safest + To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least -the “copyright” line and a pointer to where the full notice is found. +the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by + it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. + GNU General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + You should have received a copy of the GNU General Public License + along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. -If your software can interact with users remotely through a computer -network, you should also make sure that it provides a way for users to -get its source. For example, if your program is a web application, its -interface could display a “Source” link that leads users to an archive -of the code. There are many ways you could offer source, and different -solutions will be better for different programs; see section 13 for the -specific requirements. - -You should also get your employer (if you work as a programmer) or school, -if any, to sign a “copyright disclaimer” for the program, if necessary. -For more information on this, and how to apply and follow the GNU AGPL, see -<>. \ No newline at end of file + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/README.md b/README.md index 6d81cf9b0..d844dd396 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -# ![borb logo](https://github.com/jorisschellekens/borb/raw/master/readme_img/logo/borb_64.png) borb +# ![borb logo](https://github.com/jorisschellekens/borb/raw/master/logo/borb_64.png) borb [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) diff --git a/borb/io/read/any_object_transformer.py b/borb/io/read/any_object_transformer.py new file mode 100644 index 000000000..3763b0140 --- /dev/null +++ b/borb/io/read/any_object_transformer.py @@ -0,0 +1,98 @@ +# !/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +This implementation of ReadBaseTransformer aggregates all +other implementations of ReadBaseTransformer +""" +import io +import typing +from typing import Any, Optional, Union + +from borb.io.read.font.font_dictionary_transformer import FontDictionaryTransformer +from borb.io.read.function.function_dictionary_transformer import FunctionDictionaryTransformer +from borb.io.read.image.ccitt_fax_image_transformer import CCITTFaxImageTransformer +from borb.io.read.image.compressed_jpeg_image_transformer import CompressedJPEGImageTransformer +from borb.io.read.image.grayscale_image_transformer import GrayscaleImageTransformer +from borb.io.read.image.jbig2_image_transformer import JBIG2ImageTransformer +from borb.io.read.image.jpeg_2000_image_transformer import JPEG2000ImageTransformer +from borb.io.read.image.jpeg_image_transformer import JPEGImageTransformer +from borb.io.read.metadata.xmp_metadata_transformer import XMPMetadataTransformer +from borb.io.read.object.array_transformer import ArrayTransformer +from borb.io.read.object.dictionary_transformer import DictionaryTransformer +from borb.io.read.object.stream_transformer import StreamTransformer +from borb.io.read.page.page_dictionary_transformer import PageDictionaryTransformer +from borb.io.read.page.root_dictionary_transformer import RootDictionaryTransformer +from borb.io.read.primitive.number_transformer import NumberTransformer +from borb.io.read.primitive.string_transformer import StringTransformer +from borb.io.read.transformer import Transformer, ReadTransformerState +from borb.io.read.reference.reference_transformer import ReferenceTransformer +from borb.io.read.reference.xref_transformer import XREFTransformer +from borb.io.read.types import AnyPDFType +from borb.pdf.canvas.event.event_listener import EventListener + + +class AnyObjectTransformer(Transformer): + """ + This implementation of ReadBaseTransformer aggregates all other implementations + of ReadBaseTransformer + """ + + def __init__(self): + super().__init__() + self.add_child_transformer(XREFTransformer()) + # XMP + self.add_child_transformer(XMPMetadataTransformer()) + # fonts + self.add_child_transformer(FontDictionaryTransformer()) + # images + self.add_child_transformer(CCITTFaxImageTransformer()) + self.add_child_transformer(GrayscaleImageTransformer()) + self.add_child_transformer(JBIG2ImageTransformer()) + self.add_child_transformer(JPEG2000ImageTransformer()) + self.add_child_transformer(JPEGImageTransformer()) + self.add_child_transformer(CompressedJPEGImageTransformer()) + # pages + self.add_child_transformer(RootDictionaryTransformer()) + self.add_child_transformer(PageDictionaryTransformer()) + # references + self.add_child_transformer(ReferenceTransformer()) + # primitives + self.add_child_transformer(FunctionDictionaryTransformer()) + self.add_child_transformer(StreamTransformer()) + self.add_child_transformer(StringTransformer()) + self.add_child_transformer(NumberTransformer()) + # objects + self.add_child_transformer(DictionaryTransformer()) + self.add_child_transformer(ArrayTransformer()) + + def can_be_transformed( + self, object: Union[io.BufferedIOBase, io.RawIOBase, io.BytesIO, AnyPDFType] + ) -> bool: + """ + This function returns True if the object to be transformed can be transformed by this ReadAnyObjectTransformer + """ + return isinstance(object, io.IOBase) + + def transform( + self, + object_to_transform: Union[io.BufferedIOBase, io.RawIOBase, AnyPDFType], + parent_object: Any, + context: Optional[ReadTransformerState] = None, + event_listeners: typing.List[EventListener] = [], + ) -> Any: + """ + This function reads an object from a byte stream. + The object being read depends on the implementation of ReadAnyObjectTransformer. + """ + if context is None: + return super().transform( + object_to_transform, + parent_object, + ReadTransformerState(), + event_listeners, + ) + else: + return super().transform( + object_to_transform, parent_object, context, event_listeners + ) diff --git a/borb/io/read/font/read_font_dictionary_transformer.py b/borb/io/read/font/font_dictionary_transformer.py similarity index 93% rename from borb/io/read/font/read_font_dictionary_transformer.py rename to borb/io/read/font/font_dictionary_transformer.py index 819848110..e0026726a 100644 --- a/borb/io/read/font/read_font_dictionary_transformer.py +++ b/borb/io/read/font/font_dictionary_transformer.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- """ -This implementation of ReadBaseTransformer is responsible for reading a Font object +This implementation of BaseTransformer is responsible for reading a Font object """ import io import typing from typing import Any, Optional, Union -from borb.io.read.read_base_transformer import ReadBaseTransformer, ReadTransformerState +from borb.io.read.transformer import Transformer, ReadTransformerState from borb.io.read.types import AnyPDFType, Dictionary, Stream from borb.pdf.canvas.event.event_listener import EventListener from borb.pdf.canvas.font.composite_font.cid_font_type_0 import CIDType0Font @@ -20,13 +20,13 @@ from borb.pdf.canvas.font.simple_font.true_type_font import TrueTypeFont -class ReadFontDictionaryTransformer(ReadBaseTransformer): +class FontDictionaryTransformer(Transformer): """ This implementation of ReadBaseTransformer is responsible for reading a Font object """ def __init__(self): - super(ReadFontDictionaryTransformer, self).__init__() + super(FontDictionaryTransformer, self).__init__() self._accept_true_type_standard_14_fonts: bool = True def can_be_transformed( diff --git a/borb/io/read/function/read_function_dictionary_transformer.py b/borb/io/read/function/function_dictionary_transformer.py similarity index 95% rename from borb/io/read/function/read_function_dictionary_transformer.py rename to borb/io/read/function/function_dictionary_transformer.py index da822f7a6..1156e6823 100644 --- a/borb/io/read/function/read_function_dictionary_transformer.py +++ b/borb/io/read/function/function_dictionary_transformer.py @@ -10,12 +10,12 @@ from typing import Any, Optional, Union from borb.io.filter.stream_decode_util import decode_stream -from borb.io.read.read_base_transformer import ReadBaseTransformer, ReadTransformerState +from borb.io.read.transformer import Transformer, ReadTransformerState from borb.io.read.types import AnyPDFType, Dictionary, Function, Name, Reference, Stream from borb.pdf.canvas.event.event_listener import EventListener -class FunctionDictionaryTransformer(ReadBaseTransformer): +class FunctionDictionaryTransformer(Transformer): """ This implementation of ReadBaseTransformer is responsible for reading a Function Dictionary """ diff --git a/borb/io/read/image/read_ccitt_fax_image_transformer.py b/borb/io/read/image/ccitt_fax_image_transformer.py similarity index 94% rename from borb/io/read/image/read_ccitt_fax_image_transformer.py rename to borb/io/read/image/ccitt_fax_image_transformer.py index 5984f3d9f..f511fd596 100644 --- a/borb/io/read/image/read_ccitt_fax_image_transformer.py +++ b/borb/io/read/image/ccitt_fax_image_transformer.py @@ -9,7 +9,7 @@ import typing from typing import Any, Optional, Union -from borb.io.read.read_base_transformer import ReadBaseTransformer, ReadTransformerState +from borb.io.read.transformer import Transformer, ReadTransformerState from borb.io.read.types import AnyPDFType, Stream, add_base_methods from borb.pdf.canvas.event.event_listener import EventListener from PIL import Image # type: ignore [import] @@ -17,7 +17,7 @@ logger = logging.getLogger(__name__) -class ReadCCITTFaxImageTransformer(ReadBaseTransformer): +class CCITTFaxImageTransformer(Transformer): """ This implementation of ReadBaseTransformer is responsible for reading CCITT fax images """ diff --git a/borb/io/read/image/read_compressed_jpeg_image_transformer.py b/borb/io/read/image/compressed_jpeg_image_transformer.py similarity index 95% rename from borb/io/read/image/read_compressed_jpeg_image_transformer.py rename to borb/io/read/image/compressed_jpeg_image_transformer.py index f0706432d..c1f7e7b2a 100644 --- a/borb/io/read/image/read_compressed_jpeg_image_transformer.py +++ b/borb/io/read/image/compressed_jpeg_image_transformer.py @@ -10,7 +10,7 @@ from typing import Any, Optional, Union from borb.io.filter.stream_decode_util import decode_stream -from borb.io.read.read_base_transformer import ReadBaseTransformer, ReadTransformerState +from borb.io.read.transformer import Transformer, ReadTransformerState from borb.io.read.types import AnyPDFType, Name, Stream, add_base_methods from borb.pdf.canvas.event.event_listener import EventListener from PIL import Image # type: ignore [import] @@ -18,7 +18,7 @@ logger = logging.getLogger(__name__) -class ReadCompressedJPEGImageTransformer(ReadBaseTransformer): +class CompressedJPEGImageTransformer(Transformer): """ This implementation of ReadBaseTransformer is responsible for reading a jpeg image object """ diff --git a/borb/io/read/image/read_grayscale_image_transformer.py b/borb/io/read/image/grayscale_image_transformer.py similarity index 95% rename from borb/io/read/image/read_grayscale_image_transformer.py rename to borb/io/read/image/grayscale_image_transformer.py index 62264b9ad..011b3b1fb 100644 --- a/borb/io/read/image/read_grayscale_image_transformer.py +++ b/borb/io/read/image/grayscale_image_transformer.py @@ -10,7 +10,7 @@ from typing import Any, Optional, Union from borb.io.filter.stream_decode_util import decode_stream -from borb.io.read.read_base_transformer import ReadBaseTransformer, ReadTransformerState +from borb.io.read.transformer import Transformer, ReadTransformerState from borb.io.read.types import AnyPDFType, Reference, Stream, add_base_methods from borb.pdf.canvas.event.event_listener import EventListener from PIL import Image # type: ignore [import] @@ -18,7 +18,7 @@ logger = logging.getLogger(__name__) -class ReadGrayscaleImageTransformer(ReadBaseTransformer): +class GrayscaleImageTransformer(Transformer): """ This implementation of ReadBaseTransformer is responsible for reading a grayscale image object """ diff --git a/borb/io/read/image/read_jbig2_image_transformer.py b/borb/io/read/image/jbig2_image_transformer.py similarity index 94% rename from borb/io/read/image/read_jbig2_image_transformer.py rename to borb/io/read/image/jbig2_image_transformer.py index 6cec6d02e..cec5fc702 100644 --- a/borb/io/read/image/read_jbig2_image_transformer.py +++ b/borb/io/read/image/jbig2_image_transformer.py @@ -9,7 +9,7 @@ import typing from typing import Any, Optional, Union -from borb.io.read.read_base_transformer import ReadBaseTransformer, ReadTransformerState +from borb.io.read.transformer import Transformer, ReadTransformerState from borb.io.read.types import AnyPDFType, Stream, add_base_methods from borb.pdf.canvas.event.event_listener import EventListener from PIL import Image # type: ignore [import] @@ -17,7 +17,7 @@ logger = logging.getLogger(__name__) -class ReadJBIG2ImageTransformer(ReadBaseTransformer): +class JBIG2ImageTransformer(Transformer): """ This implementation of ReadBaseTransformer is responsible for reading a jbig2 image object """ diff --git a/borb/io/read/image/read_jpeg_2000_image_transformer.py b/borb/io/read/image/jpeg_2000_image_transformer.py similarity index 94% rename from borb/io/read/image/read_jpeg_2000_image_transformer.py rename to borb/io/read/image/jpeg_2000_image_transformer.py index 695a3a2d9..6de0ab85c 100644 --- a/borb/io/read/image/read_jpeg_2000_image_transformer.py +++ b/borb/io/read/image/jpeg_2000_image_transformer.py @@ -9,7 +9,7 @@ import typing from typing import Any, Optional, Union -from borb.io.read.read_base_transformer import ReadBaseTransformer, ReadTransformerState +from borb.io.read.transformer import Transformer, ReadTransformerState from borb.io.read.types import AnyPDFType, Stream, add_base_methods from borb.pdf.canvas.event.event_listener import EventListener from PIL import Image # type: ignore [import] @@ -17,7 +17,7 @@ logger = logging.getLogger(__name__) -class ReadJPEG2000ImageTransformer(ReadBaseTransformer): +class JPEG2000ImageTransformer(Transformer): """ This implementation of ReadBaseTransformer is responsible for reading a jpeg2000 image object """ diff --git a/borb/io/read/image/read_jpeg_image_transformer.py b/borb/io/read/image/jpeg_image_transformer.py similarity index 94% rename from borb/io/read/image/read_jpeg_image_transformer.py rename to borb/io/read/image/jpeg_image_transformer.py index 1d34971a9..101a8b97e 100644 --- a/borb/io/read/image/read_jpeg_image_transformer.py +++ b/borb/io/read/image/jpeg_image_transformer.py @@ -9,7 +9,7 @@ import typing from typing import Any, Optional, Union -from borb.io.read.read_base_transformer import ReadBaseTransformer, ReadTransformerState +from borb.io.read.transformer import Transformer, ReadTransformerState from borb.io.read.types import AnyPDFType, Stream, add_base_methods from borb.pdf.canvas.event.event_listener import EventListener from PIL import Image # type: ignore [import] @@ -17,7 +17,7 @@ logger = logging.getLogger(__name__) -class ReadJPEGImageTransformer(ReadBaseTransformer): +class JPEGImageTransformer(Transformer): """ This implementation of ReadBaseTransformer is responsible for reading a jpeg image object """ diff --git a/borb/io/read/metadata/read_xmp_metadata_transformer.py b/borb/io/read/metadata/xmp_metadata_transformer.py similarity index 93% rename from borb/io/read/metadata/read_xmp_metadata_transformer.py rename to borb/io/read/metadata/xmp_metadata_transformer.py index 7546060d7..f62edf672 100644 --- a/borb/io/read/metadata/read_xmp_metadata_transformer.py +++ b/borb/io/read/metadata/xmp_metadata_transformer.py @@ -18,15 +18,15 @@ import xml.etree.ElementTree as ET from typing import Any, Optional, Union -from borb.io.read.object.read_stream_transformer import ReadStreamTransformer -from borb.io.read.read_base_transformer import ReadTransformerState +from borb.io.read.object.stream_transformer import StreamTransformer +from borb.io.read.transformer import ReadTransformerState from borb.io.read.types import AnyPDFType, Element, Stream from borb.pdf.canvas.event.event_listener import EventListener logger = logging.getLogger(__name__) -class ReadXMPMetadataTransformer(ReadStreamTransformer): +class XMPMetadataTransformer(StreamTransformer): """ A metadata stream may be attached to a document through the Metadata entry in the document catalogue (see 7.7.2, “Document Catalog”). The metadata framework provides a date stamp for metadata expressed in @@ -65,7 +65,7 @@ def transform( """ # delegate to super (ReadStreamTransformer) - out_value = super(ReadXMPMetadataTransformer, self).transform( + out_value = super(XMPMetadataTransformer, self).transform( object_to_transform=object_to_transform, parent_object=parent_object, context=context, diff --git a/borb/io/read/object/read_array_transformer.py b/borb/io/read/object/array_transformer.py similarity index 92% rename from borb/io/read/object/read_array_transformer.py rename to borb/io/read/object/array_transformer.py index 1de87c126..f6c3f369c 100644 --- a/borb/io/read/object/read_array_transformer.py +++ b/borb/io/read/object/array_transformer.py @@ -8,12 +8,12 @@ import typing from typing import Any, Optional, Union -from borb.io.read.read_base_transformer import ReadBaseTransformer, ReadTransformerState +from borb.io.read.transformer import Transformer, ReadTransformerState from borb.io.read.types import AnyPDFType, List from borb.pdf.canvas.event.event_listener import EventListener -class ReadArrayTransformer(ReadBaseTransformer): +class ArrayTransformer(Transformer): """ This implementation of BaseTransformer converts a PDFArray to a List """ diff --git a/borb/io/read/object/read_dictionary_transformer.py b/borb/io/read/object/dictionary_transformer.py similarity index 92% rename from borb/io/read/object/read_dictionary_transformer.py rename to borb/io/read/object/dictionary_transformer.py index 2ccbcc923..956f63b7e 100644 --- a/borb/io/read/object/read_dictionary_transformer.py +++ b/borb/io/read/object/dictionary_transformer.py @@ -8,12 +8,12 @@ import typing from typing import Any, Optional, Union -from borb.io.read.read_base_transformer import ReadBaseTransformer, ReadTransformerState +from borb.io.read.transformer import Transformer, ReadTransformerState from borb.io.read.types import AnyPDFType, Dictionary from borb.pdf.canvas.event.event_listener import EventListener -class ReadDictionaryTransformer(ReadBaseTransformer): +class DictionaryTransformer(Transformer): """ This implementation of ReadBaseTransformer is responsible for reading a Dictionary object """ diff --git a/borb/io/read/object/read_stream_transformer.py b/borb/io/read/object/stream_transformer.py similarity index 94% rename from borb/io/read/object/read_stream_transformer.py rename to borb/io/read/object/stream_transformer.py index 8f6af9a8d..d09fd8354 100644 --- a/borb/io/read/object/read_stream_transformer.py +++ b/borb/io/read/object/stream_transformer.py @@ -9,12 +9,12 @@ from typing import Any, Optional, Union from borb.io.filter.stream_decode_util import decode_stream -from borb.io.read.read_base_transformer import ReadBaseTransformer, ReadTransformerState +from borb.io.read.transformer import Transformer, ReadTransformerState from borb.io.read.types import AnyPDFType, Reference, Stream from borb.pdf.canvas.event.event_listener import EventListener -class ReadStreamTransformer(ReadBaseTransformer): +class StreamTransformer(Transformer): """ This implementation of ReadBaseTransformer is responsible for reading Stream objects """ diff --git a/borb/io/read/page/read_page_dictionary_transformer.py b/borb/io/read/page/page_dictionary_transformer.py similarity index 96% rename from borb/io/read/page/read_page_dictionary_transformer.py rename to borb/io/read/page/page_dictionary_transformer.py index a738e15da..b6f38c09f 100644 --- a/borb/io/read/page/read_page_dictionary_transformer.py +++ b/borb/io/read/page/page_dictionary_transformer.py @@ -9,7 +9,7 @@ import zlib from typing import Any, Dict, Optional, Union -from borb.io.read.read_base_transformer import ReadBaseTransformer, ReadTransformerState +from borb.io.read.transformer import Transformer, ReadTransformerState from borb.io.read.types import AnyPDFType from borb.io.read.types import Decimal as pDecimal from borb.io.read.types import Dictionary, List, Name, Stream @@ -21,7 +21,7 @@ from borb.pdf.page.page import Page -class ReadPageDictionaryTransformer(ReadBaseTransformer): +class PageDictionaryTransformer(Transformer): """ This implementation of ReadBaseTransformer is responsible for reading Page objects """ diff --git a/borb/io/read/page/read_root_dictionary_transformer.py b/borb/io/read/page/root_dictionary_transformer.py similarity index 91% rename from borb/io/read/page/read_root_dictionary_transformer.py rename to borb/io/read/page/root_dictionary_transformer.py index c89465c74..7e2fc29ba 100644 --- a/borb/io/read/page/read_root_dictionary_transformer.py +++ b/borb/io/read/page/root_dictionary_transformer.py @@ -8,8 +8,8 @@ import typing from typing import Any, Dict, List, Optional, Union -from borb.io.read.object.read_dictionary_transformer import ReadDictionaryTransformer -from borb.io.read.read_base_transformer import ReadBaseTransformer, ReadTransformerState +from borb.io.read.object.dictionary_transformer import DictionaryTransformer +from borb.io.read.transformer import Transformer, ReadTransformerState from borb.io.read.types import AnyPDFType, Decimal, Dictionary from borb.io.read.types import List as pList from borb.io.read.types import Name @@ -17,7 +17,7 @@ from borb.pdf.page.page import Page -class ReadRootDictionaryTransformer(ReadBaseTransformer): +class RootDictionaryTransformer(Transformer): """ This implementation of ReadBaseTransformer is responsible for reading the \Catalog object """ @@ -53,7 +53,7 @@ def transform( # convert using Dictionary transformer transformed_root_dictionary: Optional[Dictionary] = None for t in self.get_root_transformer().get_children(): - if isinstance(t, ReadDictionaryTransformer): + if isinstance(t, DictionaryTransformer): transformed_root_dictionary = t.transform( object_to_transform, parent_object, context, [] ) diff --git a/borb/io/read/primitive/read_number_transformer.py b/borb/io/read/primitive/number_transformer.py similarity index 89% rename from borb/io/read/primitive/read_number_transformer.py rename to borb/io/read/primitive/number_transformer.py index cb4533c23..7bc88eed8 100644 --- a/borb/io/read/primitive/read_number_transformer.py +++ b/borb/io/read/primitive/number_transformer.py @@ -8,12 +8,12 @@ import typing from typing import Any, Optional, Union -from borb.io.read.read_base_transformer import ReadBaseTransformer, ReadTransformerState +from borb.io.read.transformer import Transformer, ReadTransformerState from borb.io.read.types import AnyPDFType, Decimal from borb.pdf.canvas.event.event_listener import EventListener -class ReadNumberTransformer(ReadBaseTransformer): +class NumberTransformer(Transformer): """ This implementation of ReadBaseTransformer is responsible for reading Decimal objects """ diff --git a/borb/io/read/primitive/read_string_transformer.py b/borb/io/read/primitive/string_transformer.py similarity index 90% rename from borb/io/read/primitive/read_string_transformer.py rename to borb/io/read/primitive/string_transformer.py index db34b78ab..7cf73dee3 100644 --- a/borb/io/read/primitive/read_string_transformer.py +++ b/borb/io/read/primitive/string_transformer.py @@ -8,12 +8,12 @@ import typing from typing import Any, Optional, Union -from borb.io.read.read_base_transformer import ReadBaseTransformer, ReadTransformerState +from borb.io.read.transformer import Transformer, ReadTransformerState from borb.io.read.types import AnyPDFType, HexadecimalString, Name, String from borb.pdf.canvas.event.event_listener import EventListener -class ReadStringTransformer(ReadBaseTransformer): +class StringTransformer(Transformer): """ This implementation of ReadBaseTransformer is responsible for reading String objects """ diff --git a/borb/io/read/read_any_object_transformer.py b/borb/io/read/read_any_object_transformer.py deleted file mode 100644 index c8d5d5ad2..000000000 --- a/borb/io/read/read_any_object_transformer.py +++ /dev/null @@ -1,116 +0,0 @@ -# !/usr/bin/env python -# -*- coding: utf-8 -*- - -""" -This implementation of ReadBaseTransformer aggregates all -other implementations of ReadBaseTransformer -""" -import io -import typing -from typing import Any, Optional, Union - -from borb.io.read.font.read_font_dictionary_transformer import ( - ReadFontDictionaryTransformer, -) -from borb.io.read.function.read_function_dictionary_transformer import ( - FunctionDictionaryTransformer, -) -from borb.io.read.image.read_ccitt_fax_image_transformer import ( - ReadCCITTFaxImageTransformer, -) -from borb.io.read.image.read_compressed_jpeg_image_transformer import ( - ReadCompressedJPEGImageTransformer, -) -from borb.io.read.image.read_grayscale_image_transformer import ( - ReadGrayscaleImageTransformer, -) -from borb.io.read.image.read_jbig2_image_transformer import ReadJBIG2ImageTransformer -from borb.io.read.image.read_jpeg_2000_image_transformer import ( - ReadJPEG2000ImageTransformer, -) -from borb.io.read.image.read_jpeg_image_transformer import ReadJPEGImageTransformer -from borb.io.read.metadata.read_xmp_metadata_transformer import ( - ReadXMPMetadataTransformer, -) -from borb.io.read.object.read_array_transformer import ReadArrayTransformer -from borb.io.read.object.read_dictionary_transformer import ReadDictionaryTransformer -from borb.io.read.object.read_stream_transformer import ReadStreamTransformer -from borb.io.read.page.read_page_dictionary_transformer import ( - ReadPageDictionaryTransformer, -) -from borb.io.read.page.read_root_dictionary_transformer import ( - ReadRootDictionaryTransformer, -) -from borb.io.read.primitive.read_number_transformer import ReadNumberTransformer -from borb.io.read.primitive.read_string_transformer import ReadStringTransformer -from borb.io.read.read_base_transformer import ReadBaseTransformer, ReadTransformerState -from borb.io.read.reference.read_reference_transformer import ReadReferenceTransformer -from borb.io.read.reference.read_xref_transformer import ReadXREFTransformer -from borb.io.read.types import AnyPDFType -from borb.pdf.canvas.event.event_listener import EventListener - - -class ReadAnyObjectTransformer(ReadBaseTransformer): - """ - This implementation of ReadBaseTransformer aggregates all other implementations - of ReadBaseTransformer - """ - - def __init__(self): - super().__init__() - self.add_child_transformer(ReadXREFTransformer()) - # XMP - self.add_child_transformer(ReadXMPMetadataTransformer()) - # fonts - self.add_child_transformer(ReadFontDictionaryTransformer()) - # images - self.add_child_transformer(ReadCCITTFaxImageTransformer()) - self.add_child_transformer(ReadGrayscaleImageTransformer()) - self.add_child_transformer(ReadJBIG2ImageTransformer()) - self.add_child_transformer(ReadJPEG2000ImageTransformer()) - self.add_child_transformer(ReadJPEGImageTransformer()) - self.add_child_transformer(ReadCompressedJPEGImageTransformer()) - # pages - self.add_child_transformer(ReadRootDictionaryTransformer()) - self.add_child_transformer(ReadPageDictionaryTransformer()) - # references - self.add_child_transformer(ReadReferenceTransformer()) - # primitives - self.add_child_transformer(FunctionDictionaryTransformer()) - self.add_child_transformer(ReadStreamTransformer()) - self.add_child_transformer(ReadStringTransformer()) - self.add_child_transformer(ReadNumberTransformer()) - # objects - self.add_child_transformer(ReadDictionaryTransformer()) - self.add_child_transformer(ReadArrayTransformer()) - - def can_be_transformed( - self, object: Union[io.BufferedIOBase, io.RawIOBase, io.BytesIO, AnyPDFType] - ) -> bool: - """ - This function returns True if the object to be transformed can be transformed by this ReadAnyObjectTransformer - """ - return isinstance(object, io.IOBase) - - def transform( - self, - object_to_transform: Union[io.BufferedIOBase, io.RawIOBase, AnyPDFType], - parent_object: Any, - context: Optional[ReadTransformerState] = None, - event_listeners: typing.List[EventListener] = [], - ) -> Any: - """ - This function reads an object from a byte stream. - The object being read depends on the implementation of ReadAnyObjectTransformer. - """ - if context is None: - return super().transform( - object_to_transform, - parent_object, - ReadTransformerState(), - event_listeners, - ) - else: - return super().transform( - object_to_transform, parent_object, context, event_listeners - ) diff --git a/borb/io/read/reference/read_reference_transformer.py b/borb/io/read/reference/reference_transformer.py similarity index 95% rename from borb/io/read/reference/read_reference_transformer.py rename to borb/io/read/reference/reference_transformer.py index 24c300a34..60a009a1d 100644 --- a/borb/io/read/reference/read_reference_transformer.py +++ b/borb/io/read/reference/reference_transformer.py @@ -10,7 +10,7 @@ import typing from typing import Any, Optional, Union -from borb.io.read.read_base_transformer import ReadBaseTransformer, ReadTransformerState +from borb.io.read.transformer import Transformer, ReadTransformerState from borb.io.read.types import AnyPDFType, Reference from borb.pdf.canvas.event.event_listener import EventListener from borb.pdf.xref.xref import XREF @@ -18,14 +18,14 @@ logger = logging.getLogger(__name__) -class ReadReferenceTransformer(ReadBaseTransformer): +class ReferenceTransformer(Transformer): """ This implementation of ReadBaseTransformer is responsible for reading Reference objects e.g. 97 0 R """ def __init__(self): - super(ReadReferenceTransformer, self).__init__() + super(ReferenceTransformer, self).__init__() self._cache: typing.Dict[Reference, AnyPDFType] = {} self._cache_hits: int = 0 self._cache_fails: int = 0 diff --git a/borb/io/read/reference/read_xref_transformer.py b/borb/io/read/reference/xref_transformer.py similarity index 97% rename from borb/io/read/reference/read_xref_transformer.py rename to borb/io/read/reference/xref_transformer.py index d3e470532..685d2eeee 100644 --- a/borb/io/read/reference/read_xref_transformer.py +++ b/borb/io/read/reference/xref_transformer.py @@ -10,7 +10,7 @@ from decimal import Decimal from typing import Any, Optional, Union -from borb.io.read.read_base_transformer import ReadBaseTransformer, ReadTransformerState +from borb.io.read.transformer import Transformer, ReadTransformerState from borb.io.read.tokenize.high_level_tokenizer import HighLevelTokenizer from borb.io.read.types import AnyPDFType, Dictionary, Name from borb.pdf.canvas.event.event_listener import Event, EventListener @@ -36,7 +36,7 @@ class EndDocumentEvent(Event): pass -class ReadXREFTransformer(ReadBaseTransformer): +class XREFTransformer(Transformer): """ This implementation of ReadBaseTransformer is responsible for reading the XRef object """ @@ -77,10 +77,10 @@ def transform( context.root_object._event_occurred(BeginDocumentEvent()) # type: ignore [attr-defined] # remove prefix - ReadXREFTransformer._remove_prefix(context) + XREFTransformer._remove_prefix(context) # check header - ReadXREFTransformer._check_header(context) + XREFTransformer._check_header(context) # file size context.source.seek(0, os.SEEK_END) diff --git a/borb/io/read/read_base_transformer.py b/borb/io/read/transformer.py similarity index 92% rename from borb/io/read/read_base_transformer.py rename to borb/io/read/transformer.py index 66cede1c2..c46ab73fa 100644 --- a/borb/io/read/read_base_transformer.py +++ b/borb/io/read/transformer.py @@ -36,7 +36,7 @@ def __init__( self.indirect_reference_chain: typing.Set[Reference] = set() -class ReadBaseTransformer: +class Transformer: """ Base Transformer implementation. Add children to handle specific cases (transforming dictionaries, arrays, xref, etc) @@ -48,25 +48,25 @@ def __init__(self): self._level = 0 self._invocation_count = 0 - def get_children(self) -> typing.List["ReadBaseTransformer"]: + def get_children(self) -> typing.List["Transformer"]: """ This functions returns all child ReadBaseTransformers of this ReadBaseTransformer """ return self._children - def add_child_transformer(self, child_transformer: "ReadBaseTransformer") -> "ReadBaseTransformer": # type: ignore[name-defined] + def add_child_transformer(self, child_transformer: "Transformer") -> "Transformer": # type: ignore[name-defined] """ Add a child ReadBaseTransformer to this ReadBaseTransformer. Child transformers can be used to encapsulate specific object-creation/transformation logic. e.g. creating XREF, converting arrays, dictionaries, etc :param handler: the ReadBaseTransformer implementation to be added - :type handler: ReadBaseTransformer + :type handler: Transformer """ self._children.append(child_transformer) child_transformer._parent = self return self - def get_root_transformer(self) -> "ReadBaseTransformer": # type: ignore[name-defined] + def get_root_transformer(self) -> "Transformer": # type: ignore[name-defined] """ This function returns the top-level ReadBaseTransformer. This is useful when delegating calls from inside a ReadBaseTransformer to another. diff --git a/borb/io/write/any_object_transformer.py b/borb/io/write/any_object_transformer.py new file mode 100644 index 000000000..8c2e18f65 --- /dev/null +++ b/borb/io/write/any_object_transformer.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +This implementation of WriteBaseTransformer acts as an aggregator for +its child transformers, allowing it to transform AnyPDFType +""" +import io +from typing import Optional, Union + +from borb.io.read.types import AnyPDFType +from borb.io.write.ascii_art.ascii_art_transformer import ASCIIArtTransformer +from borb.io.write.image.image_transformer import ImageTransformer +from borb.io.write.object.array_transformer import ArrayTransformer +from borb.io.write.object.dictionary_transformer import DictionaryTransformer +from borb.io.write.object.stream_transformer import StreamTransformer +from borb.io.write.page.page_transformer import PageTransformer +from borb.io.write.page.pages_transformer import PagesTransformer +from borb.io.write.primitive.boolean_transformer import BooleanTransformer +from borb.io.write.primitive.name_transformer import NameTransformer +from borb.io.write.primitive.number_transformer import NumberTransformer +from borb.io.write.primitive.string_transformer import StringTransformer +from borb.io.write.reference.reference_transformer import ReferenceTransform +from borb.io.write.reference.xref_transformer import XREFTransformer +from borb.io.write.transformer import ( + Transformer, + WriteTransformerState, +) +from borb.io.write.document.document_transformer import DocumentTransformer +from borb.io.write.xmp.xmp_transformer import XMPTransformer + + +class AnyObjectTransformer(Transformer): + """ + This implementation of WriteBaseTransformer acts as an aggregator for + its child transformers, allowing it to transform AnyPDFType + """ + + def __init__(self): + super().__init__() + # fun + self.add_child_transformer(ASCIIArtTransformer()) + # special object types + self.add_child_transformer(DocumentTransformer()) + self.add_child_transformer(XREFTransformer()) + self.add_child_transformer(PagesTransformer()) + self.add_child_transformer(PageTransformer()) + # object types + self.add_child_transformer(ArrayTransformer()) + self.add_child_transformer(StreamTransformer()) + self.add_child_transformer(DictionaryTransformer()) + self.add_child_transformer(ImageTransformer()) + self.add_child_transformer(XMPTransformer()) + # primitives + self.add_child_transformer(NameTransformer()) + self.add_child_transformer(StringTransformer()) + self.add_child_transformer(ReferenceTransform()) + self.add_child_transformer(NumberTransformer()) + self.add_child_transformer(BooleanTransformer()) + + def can_be_transformed(self, object_to_transform: AnyPDFType): + """ + This function returns True if the object to be transformed + can be transformed by this WriteBaseTransformer + """ + return False + + def transform( + self, + object_to_transform: AnyPDFType, + context: Optional[WriteTransformerState] = None, + destination: Optional[Union[io.BufferedIOBase, io.RawIOBase]] = None, + ): + """ + This method writes an (PDF) object to a byte stream + """ + if context is None: + super().transform( + object_to_transform, + WriteTransformerState( + destination=destination, root_object=object_to_transform + ), + ) + else: + super().transform(object_to_transform, context) diff --git a/borb/io/write/ascii_art/write_ascii_art_transformer.py b/borb/io/write/ascii_art/ascii_art_transformer.py similarity index 93% rename from borb/io/write/ascii_art/write_ascii_art_transformer.py rename to borb/io/write/ascii_art/ascii_art_transformer.py index 47c95414e..d87f26e90 100644 --- a/borb/io/write/ascii_art/write_ascii_art_transformer.py +++ b/borb/io/write/ascii_art/ascii_art_transformer.py @@ -8,13 +8,13 @@ from typing import Optional from borb.io.read.types import AnyPDFType, Stream -from borb.io.write.write_base_transformer import ( - WriteBaseTransformer, +from borb.io.write.transformer import ( + Transformer, WriteTransformerState, ) -class WriteASCIIArtTransformer(WriteBaseTransformer): +class ASCIIArtTransformer(Transformer): """ This implementation of WriteBaseTransformer is responsible for writing ASCII art in every PDF """ diff --git a/borb/io/write/ascii_art/ascii_logo.txt b/borb/io/write/ascii_art/ascii_logo.txt index ea43a33bc..8e3a68613 100644 --- a/borb/io/write/ascii_art/ascii_logo.txt +++ b/borb/io/write/ascii_art/ascii_logo.txt @@ -1,2 +1,2 @@ -borb version 2.0.9 +borb version 2.0.9.1 Joris Schellekens diff --git a/borb/io/write/document/__init__.py b/borb/io/write/document/__init__.py new file mode 100644 index 000000000..bcf77caad --- /dev/null +++ b/borb/io/write/document/__init__.py @@ -0,0 +1,43 @@ +""" + This file is part of the borb (R) project. + Copyright (c) 2020-2040 borb Group NV + Authors: Joris Schellekens, et al. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License version 3 + as published by the Free Software Foundation with the addition of the + following permission added to Section 15 as permitted in Section 7(a): + FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY + BORB GROUP. BORB GROUP DISCLAIMS THE WARRANTY OF NON INFRINGEMENT + OF THIRD PARTY RIGHTS + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program; if not, see http://www.gnu.org/licenses or write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA, 02110-1301 USA. + + The interactive user interfaces in modified source and object code versions + of this program must display Appropriate Legal Notices, as required under + Section 5 of the GNU Affero General Public License. + In accordance with Section 7(b) of the GNU Affero General Public License, + a covered work must retain the producer line in every PDF that is created + or manipulated using borb. + + You can be released from the requirements of the license by purchasing + a commercial license. Buying such a license is mandatory as soon as you + develop commercial activities involving the borb software without + disclosing the source code of your own applications. + + These activities include: offering paid services to customers as an ASP, + serving PDFs on the fly in a web application, shipping borb with a closed + source product. + + For more information, please contact borb Software Corp. at this + address: joris.schellekens.1989@gmail.com +""" diff --git a/borb/io/write/write_pdf_transformer.py b/borb/io/write/document/document_transformer.py similarity index 94% rename from borb/io/write/write_pdf_transformer.py rename to borb/io/write/document/document_transformer.py index 810b2610d..4c414dbfd 100644 --- a/borb/io/write/write_pdf_transformer.py +++ b/borb/io/write/document/document_transformer.py @@ -18,8 +18,8 @@ Name, String, ) -from borb.io.write.write_base_transformer import ( - WriteBaseTransformer, +from borb.io.write.transformer import ( + Transformer, WriteTransformerState, ) from borb.pdf.document import Document @@ -27,7 +27,7 @@ logger = logging.getLogger(__name__) -class WritePDFTransformer(WriteBaseTransformer): +class DocumentTransformer(Transformer): """ This implementation of WriteBaseTransformer is responsible for writing Document objects """ @@ -56,7 +56,7 @@ def transform( context.destination.write(b"\n") # invalidate all references - WritePDFTransformer._invalidate_all_references(object_to_transform) + DocumentTransformer._invalidate_all_references(object_to_transform) # create Info dictionary if needed if "Info" not in object_to_transform["XRef"]["Trailer"]: @@ -77,7 +77,7 @@ def transform( object_to_transform["XRef"]["Trailer"]["ID"].set_can_be_referenced(False) # set CreationDate - modification_date = WritePDFTransformer._timestamp_to_str() + modification_date = DocumentTransformer._timestamp_to_str() if "CreationDate" not in object_to_transform["XRef"]["Trailer"][Name("Info")]: object_to_transform["XRef"]["Trailer"][Name("Info")][ Name("CreationDate") diff --git a/borb/io/write/image/write_image_transformer.py b/borb/io/write/image/image_transformer.py similarity index 97% rename from borb/io/write/image/write_image_transformer.py rename to borb/io/write/image/image_transformer.py index 0a57700be..0abb9d106 100644 --- a/borb/io/write/image/write_image_transformer.py +++ b/borb/io/write/image/image_transformer.py @@ -11,14 +11,14 @@ from borb.io.read.types import AnyPDFType from borb.io.read.types import Decimal as pDecimal from borb.io.read.types import Name, Reference, Stream, add_base_methods -from borb.io.write.write_base_transformer import ( - WriteBaseTransformer, +from borb.io.write.transformer import ( + Transformer, WriteTransformerState, ) from PIL import Image as PILImage # type: ignore [import] -class WriteImageTransformer(WriteBaseTransformer): +class ImageTransformer(Transformer): """ This implementation of WriteBaseTransformer is responsible for writing Image objects """ diff --git a/borb/io/write/object/write_array_transformer.py b/borb/io/write/object/array_transformer.py similarity index 96% rename from borb/io/write/object/write_array_transformer.py rename to borb/io/write/object/array_transformer.py index 52b301df9..eb202ab9c 100644 --- a/borb/io/write/object/write_array_transformer.py +++ b/borb/io/write/object/array_transformer.py @@ -9,8 +9,8 @@ from typing import Optional from borb.io.read.types import AnyPDFType, Dictionary, List, Reference, Stream -from borb.io.write.write_base_transformer import ( - WriteBaseTransformer, +from borb.io.write.transformer import ( + Transformer, WriteTransformerState, ) from PIL.Image import Image # type: ignore [import] @@ -18,7 +18,7 @@ logger = logging.getLogger(__name__) -class WriteArrayTransformer(WriteBaseTransformer): +class ArrayTransformer(Transformer): """ This implementation of WriteBaseTransformer is responsible for writing List objects """ diff --git a/borb/io/write/object/write_dictionary_transformer.py b/borb/io/write/object/dictionary_transformer.py similarity index 96% rename from borb/io/write/object/write_dictionary_transformer.py rename to borb/io/write/object/dictionary_transformer.py index fedb6b947..efbc134d2 100644 --- a/borb/io/write/object/write_dictionary_transformer.py +++ b/borb/io/write/object/dictionary_transformer.py @@ -9,8 +9,8 @@ from typing import Optional from borb.io.read.types import AnyPDFType, Dictionary, Element, List, Reference, Stream -from borb.io.write.write_base_transformer import ( - WriteBaseTransformer, +from borb.io.write.transformer import ( + Transformer, WriteTransformerState, ) from PIL.Image import Image # type: ignore [import] @@ -18,7 +18,7 @@ logger = logging.getLogger(__name__) -class WriteDictionaryTransformer(WriteBaseTransformer): +class DictionaryTransformer(Transformer): """ This implementation of WriteBaseTransformer is responsible for writing Dictionary objects """ diff --git a/borb/io/write/object/write_stream_transformer.py b/borb/io/write/object/stream_transformer.py similarity index 96% rename from borb/io/write/object/write_stream_transformer.py rename to borb/io/write/object/stream_transformer.py index 266e622a7..4ec46cb82 100644 --- a/borb/io/write/object/write_stream_transformer.py +++ b/borb/io/write/object/stream_transformer.py @@ -12,15 +12,15 @@ from borb.io.read.types import AnyPDFType from borb.io.read.types import Decimal as pDecimal from borb.io.read.types import Dictionary, List, Name, Reference, Stream -from borb.io.write.write_base_transformer import ( - WriteBaseTransformer, +from borb.io.write.transformer import ( + Transformer, WriteTransformerState, ) logger = logging.getLogger(__name__) -class WriteStreamTransformer(WriteBaseTransformer): +class StreamTransformer(Transformer): """ This implementation of WriteBaseTransformer is responsible for writing Stream objects """ diff --git a/borb/io/write/page/write_page_transformer.py b/borb/io/write/page/page_transformer.py similarity index 85% rename from borb/io/write/page/write_page_transformer.py rename to borb/io/write/page/page_transformer.py index 43592689f..69e6c5574 100644 --- a/borb/io/write/page/write_page_transformer.py +++ b/borb/io/write/page/page_transformer.py @@ -9,14 +9,14 @@ from typing import Optional from borb.io.read.types import AnyPDFType, Dictionary, Name -from borb.io.write.object.write_dictionary_transformer import WriteDictionaryTransformer -from borb.io.write.write_base_transformer import WriteTransformerState +from borb.io.write.object.dictionary_transformer import DictionaryTransformer +from borb.io.write.transformer import WriteTransformerState from borb.pdf.document import Document logger = logging.getLogger(__name__) -class WritePageTransformer(WriteDictionaryTransformer): +class PageTransformer(DictionaryTransformer): """ This implementation of WriteBaseTransformer is responsible for writing Dictionary objects of \Type \Page @@ -54,4 +54,4 @@ def transform( object_to_transform[k].set_can_be_referenced(False) # type: ignore [attr-defined] # delegate to super - super(WritePageTransformer, self).transform(object_to_transform, context) + super(PageTransformer, self).transform(object_to_transform, context) diff --git a/borb/io/write/page/write_pages_transformer.py b/borb/io/write/page/pages_transformer.py similarity index 85% rename from borb/io/write/page/write_pages_transformer.py rename to borb/io/write/page/pages_transformer.py index ee4dbd166..d7fa52a87 100644 --- a/borb/io/write/page/write_pages_transformer.py +++ b/borb/io/write/page/pages_transformer.py @@ -10,13 +10,13 @@ from typing import Optional from borb.io.read.types import AnyPDFType, Dictionary, Name, Reference -from borb.io.write.object.write_dictionary_transformer import WriteDictionaryTransformer -from borb.io.write.write_base_transformer import WriteTransformerState +from borb.io.write.object.dictionary_transformer import DictionaryTransformer +from borb.io.write.transformer import WriteTransformerState logger = logging.getLogger(__name__) -class WritePagesTransformer(WriteDictionaryTransformer): +class PagesTransformer(DictionaryTransformer): """ This implementation of WriteBaseTransformer is responsible for writing Dictionary objects of \Type \Pages @@ -52,7 +52,7 @@ def transform( object_to_transform["Kids"][i] = ref # delegate to super - super(WritePagesTransformer, self).transform(object_to_transform, context) + super(PagesTransformer, self).transform(object_to_transform, context) # write \Page objects for p in queue: diff --git a/borb/io/write/primitive/write_boolean_transformer.py b/borb/io/write/primitive/boolean_transformer.py similarity index 89% rename from borb/io/write/primitive/write_boolean_transformer.py rename to borb/io/write/primitive/boolean_transformer.py index f22b46a8b..fac9effbf 100644 --- a/borb/io/write/primitive/write_boolean_transformer.py +++ b/borb/io/write/primitive/boolean_transformer.py @@ -7,13 +7,13 @@ from typing import Optional from borb.io.read.types import AnyPDFType, Boolean -from borb.io.write.write_base_transformer import ( - WriteBaseTransformer, +from borb.io.write.transformer import ( + Transformer, WriteTransformerState, ) -class WriteBooleanTransformer(WriteBaseTransformer): +class BooleanTransformer(Transformer): """ This implementation of WriteBaseTransformer is responsible for writing booleans """ diff --git a/borb/io/write/primitive/write_name_transformer.py b/borb/io/write/primitive/name_transformer.py similarity index 88% rename from borb/io/write/primitive/write_name_transformer.py rename to borb/io/write/primitive/name_transformer.py index 186a7a546..e75176580 100644 --- a/borb/io/write/primitive/write_name_transformer.py +++ b/borb/io/write/primitive/name_transformer.py @@ -7,13 +7,13 @@ from typing import Optional from borb.io.read.types import AnyPDFType, Name -from borb.io.write.write_base_transformer import ( - WriteBaseTransformer, +from borb.io.write.transformer import ( + Transformer, WriteTransformerState, ) -class WriteNameTransformer(WriteBaseTransformer): +class NameTransformer(Transformer): """ This implementation of WriteBaseTransformer is responsible for writing Name objects """ diff --git a/borb/io/write/primitive/write_number_transformer.py b/borb/io/write/primitive/number_transformer.py similarity index 90% rename from borb/io/write/primitive/write_number_transformer.py rename to borb/io/write/primitive/number_transformer.py index a145d1f2b..3571f55d2 100644 --- a/borb/io/write/primitive/write_number_transformer.py +++ b/borb/io/write/primitive/number_transformer.py @@ -7,13 +7,13 @@ from typing import Optional from borb.io.read.types import AnyPDFType, Decimal -from borb.io.write.write_base_transformer import ( - WriteBaseTransformer, +from borb.io.write.transformer import ( + Transformer, WriteTransformerState, ) -class WriteNumberTransformer(WriteBaseTransformer): +class NumberTransformer(Transformer): """ This implementation of WriteBaseTransformer is responsible for writing Decimal objects """ diff --git a/borb/io/write/primitive/write_string_transformer.py b/borb/io/write/primitive/string_transformer.py similarity index 92% rename from borb/io/write/primitive/write_string_transformer.py rename to borb/io/write/primitive/string_transformer.py index fad28ab70..36fd71772 100644 --- a/borb/io/write/primitive/write_string_transformer.py +++ b/borb/io/write/primitive/string_transformer.py @@ -7,13 +7,13 @@ from typing import Optional from borb.io.read.types import AnyPDFType, HexadecimalString, String -from borb.io.write.write_base_transformer import ( - WriteBaseTransformer, +from borb.io.write.transformer import ( + Transformer, WriteTransformerState, ) -class WriteStringTransformer(WriteBaseTransformer): +class StringTransformer(Transformer): """ This implementation of WriteBaseTransformer is responsible for writing String objects """ diff --git a/borb/io/write/reference/write_reference_transformer.py b/borb/io/write/reference/reference_transformer.py similarity index 91% rename from borb/io/write/reference/write_reference_transformer.py rename to borb/io/write/reference/reference_transformer.py index be366c82d..147d44880 100644 --- a/borb/io/write/reference/write_reference_transformer.py +++ b/borb/io/write/reference/reference_transformer.py @@ -7,13 +7,13 @@ from typing import Optional from borb.io.read.types import AnyPDFType, Reference -from borb.io.write.write_base_transformer import ( - WriteBaseTransformer, +from borb.io.write.transformer import ( + Transformer, WriteTransformerState, ) -class WriteReferenceTransform(WriteBaseTransformer): +class ReferenceTransform(Transformer): """ This implementation of WriteBaseTransformer is responsible for writing References """ diff --git a/borb/io/write/reference/write_xref_transformer.py b/borb/io/write/reference/xref_transformer.py similarity index 97% rename from borb/io/write/reference/write_xref_transformer.py rename to borb/io/write/reference/xref_transformer.py index c80526291..692efdc1d 100644 --- a/borb/io/write/reference/write_xref_transformer.py +++ b/borb/io/write/reference/xref_transformer.py @@ -8,14 +8,14 @@ from typing import Optional from borb.io.read.types import AnyPDFType, Decimal, Dictionary, Name, Reference -from borb.io.write.write_base_transformer import ( - WriteBaseTransformer, +from borb.io.write.transformer import ( + Transformer, WriteTransformerState, ) from borb.pdf.xref.xref import XREF -class WriteXREFTransformer(WriteBaseTransformer): +class XREFTransformer(Transformer): """ This implementation of WriteBaseTransformer is responsible for writing XREF objects """ diff --git a/borb/io/write/write_base_transformer.py b/borb/io/write/transformer.py similarity index 95% rename from borb/io/write/write_base_transformer.py rename to borb/io/write/transformer.py index 65867ab6a..8745d626f 100644 --- a/borb/io/write/write_base_transformer.py +++ b/borb/io/write/transformer.py @@ -37,7 +37,7 @@ def __init__( # fmt: on -class WriteBaseTransformer: +class Transformer: """ This class represents the base transformer for persisting a PDF Document. It allows you to add child BaseWriteTransformer implementations to handle specific cases, @@ -45,12 +45,12 @@ class WriteBaseTransformer: """ def __init__(self): - self._handlers: typing.List["WriteBaseTransformer"] = [] - self._parent: typing.Optional["WriteBaseTransformer"] = None + self._handlers: typing.List["Transformer"] = [] + self._parent: typing.Optional["Transformer"] = None def add_child_transformer( - self, handler: "WriteBaseTransformer" # type: ignore [name-defined] - ) -> "WriteBaseTransformer": # type: ignore [name-defined] + self, handler: "Transformer" # type: ignore [name-defined] + ) -> "Transformer": # type: ignore [name-defined] """ This function adds a BaseWriteTransformer to this WriteBaseTransformer. Children of this WriteBaseTransformer will be called in turn, and their @@ -63,7 +63,7 @@ def add_child_transformer( handler._parent = self return self - def get_root_transformer(self) -> "WriteBaseTransformer": # type: ignore [name-defined] + def get_root_transformer(self) -> "Transformer": # type: ignore [name-defined] """ This function returns the WriteBaseTransformer at the root of this WriteBaseTransformer hierarchy. This allows child WriteBaseTransformer implementations to call the root transformer. diff --git a/borb/io/write/write_any_object_transformer.py b/borb/io/write/write_any_object_transformer.py deleted file mode 100644 index f1bd7f190..000000000 --- a/borb/io/write/write_any_object_transformer.py +++ /dev/null @@ -1,85 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -""" -This implementation of WriteBaseTransformer acts as an aggregator for -its child transformers, allowing it to transform AnyPDFType -""" -import io -from typing import Optional, Union - -from borb.io.read.types import AnyPDFType -from borb.io.write.ascii_art.write_ascii_art_transformer import WriteASCIIArtTransformer -from borb.io.write.image.write_image_transformer import WriteImageTransformer -from borb.io.write.object.write_array_transformer import WriteArrayTransformer -from borb.io.write.object.write_dictionary_transformer import WriteDictionaryTransformer -from borb.io.write.object.write_stream_transformer import WriteStreamTransformer -from borb.io.write.page.write_page_transformer import WritePageTransformer -from borb.io.write.page.write_pages_transformer import WritePagesTransformer -from borb.io.write.primitive.write_boolean_transformer import WriteBooleanTransformer -from borb.io.write.primitive.write_name_transformer import WriteNameTransformer -from borb.io.write.primitive.write_number_transformer import WriteNumberTransformer -from borb.io.write.primitive.write_string_transformer import WriteStringTransformer -from borb.io.write.reference.write_reference_transformer import WriteReferenceTransform -from borb.io.write.reference.write_xref_transformer import WriteXREFTransformer -from borb.io.write.write_base_transformer import ( - WriteBaseTransformer, - WriteTransformerState, -) -from borb.io.write.write_pdf_transformer import WritePDFTransformer -from borb.io.write.xmp.write_xmp_transformer import WriteXMPTransformer - - -class WriteAnyObjectTransformer(WriteBaseTransformer): - """ - This implementation of WriteBaseTransformer acts as an aggregator for - its child transformers, allowing it to transform AnyPDFType - """ - - def __init__(self): - super().__init__() - # fun - self.add_child_transformer(WriteASCIIArtTransformer()) - # special object types - self.add_child_transformer(WritePDFTransformer()) - self.add_child_transformer(WriteXREFTransformer()) - self.add_child_transformer(WritePagesTransformer()) - self.add_child_transformer(WritePageTransformer()) - # object types - self.add_child_transformer(WriteArrayTransformer()) - self.add_child_transformer(WriteStreamTransformer()) - self.add_child_transformer(WriteDictionaryTransformer()) - self.add_child_transformer(WriteImageTransformer()) - self.add_child_transformer(WriteXMPTransformer()) - # primitives - self.add_child_transformer(WriteNameTransformer()) - self.add_child_transformer(WriteStringTransformer()) - self.add_child_transformer(WriteReferenceTransform()) - self.add_child_transformer(WriteNumberTransformer()) - self.add_child_transformer(WriteBooleanTransformer()) - - def can_be_transformed(self, object_to_transform: AnyPDFType): - """ - This function returns True if the object to be transformed - can be transformed by this WriteBaseTransformer - """ - return False - - def transform( - self, - object_to_transform: AnyPDFType, - context: Optional[WriteTransformerState] = None, - destination: Optional[Union[io.BufferedIOBase, io.RawIOBase]] = None, - ): - """ - This method writes an (PDF) object to a byte stream - """ - if context is None: - super().transform( - object_to_transform, - WriteTransformerState( - destination=destination, root_object=object_to_transform - ), - ) - else: - super().transform(object_to_transform, context) diff --git a/borb/io/write/xmp/write_xmp_transformer.py b/borb/io/write/xmp/xmp_transformer.py similarity index 94% rename from borb/io/write/xmp/write_xmp_transformer.py rename to borb/io/write/xmp/xmp_transformer.py index af7bf35b5..23e47b0fb 100644 --- a/borb/io/write/xmp/write_xmp_transformer.py +++ b/borb/io/write/xmp/xmp_transformer.py @@ -12,15 +12,15 @@ from borb.io.read.types import AnyPDFType from borb.io.read.types import Decimal as pDecimal from borb.io.read.types import Name, Reference, Stream -from borb.io.write.write_base_transformer import ( - WriteBaseTransformer, +from borb.io.write.transformer import ( + Transformer, WriteTransformerState, ) logger = logging.getLogger(__name__) -class WriteXMPTransformer(WriteBaseTransformer): +class XMPTransformer(Transformer): """ This implementation of WriteBaseTransformer is responsible for writing XMP meta-data information """ diff --git a/borb/pdf/canvas/font/glyph_line.py b/borb/pdf/canvas/font/glyph_line.py index 47f07fe5c..21c753316 100644 --- a/borb/pdf/canvas/font/glyph_line.py +++ b/borb/pdf/canvas/font/glyph_line.py @@ -7,7 +7,6 @@ or contribute to a specific meaning of what is written, with that meaning dependent on cultural and social usage. """ import typing -from curses.ascii import isspace from decimal import Decimal from borb.io.read.types import Decimal as pDecimal @@ -146,6 +145,10 @@ def uses_descent(self) -> bool: """ return any([(x in ["y", "p", "q", "f", "g", "j"]) for x in self.get_text()]) + @staticmethod + def _isspace(c: str) -> bool: + return ord(c) in [9, 10, 11, 12, 13, 32] + def get_width_in_text_space(self) -> Decimal: """ This function calculates the width (in text space) of this GlyphLine @@ -155,7 +158,7 @@ def get_width_in_text_space(self) -> Decimal: glyph_width_in_text_space = g.get_width() * self._font_size * Decimal(0.001) # add word spacing where applicable - if len(g.get_unicode_str()) == 1 and isspace(g.get_unicode_str()): + if len(g.get_unicode_str()) == 1 and GlyphLine._isspace(g.get_unicode_str()): glyph_width_in_text_space += self._word_spacing # horizontal scaling diff --git a/borb/pdf/pdf.py b/borb/pdf/pdf.py index 18bd8ebaf..ee8b6b662 100644 --- a/borb/pdf/pdf.py +++ b/borb/pdf/pdf.py @@ -11,8 +11,8 @@ import io from typing import List, Union -from borb.io.read.read_any_object_transformer import ReadAnyObjectTransformer -from borb.io.write.write_any_object_transformer import WriteAnyObjectTransformer +from borb.io.read.any_object_transformer import AnyObjectTransformer as ReadAnyObjectTransformer +from borb.io.write.any_object_transformer import AnyObjectTransformer as WriteAnyObjectTransformer from borb.pdf.canvas.event.event_listener import EventListener from borb.pdf.document import Document diff --git a/borb/toolkit/ocr/ocr_as_optional_content_group.py b/borb/toolkit/ocr/ocr_as_optional_content_group.py index 515913ea7..760fe7f60 100644 --- a/borb/toolkit/ocr/ocr_as_optional_content_group.py +++ b/borb/toolkit/ocr/ocr_as_optional_content_group.py @@ -12,7 +12,7 @@ from pathlib import Path from borb.datastructure.disjoint_set import disjointset -from borb.io.read.reference.read_xref_transformer import EndDocumentEvent +from borb.io.read.reference.xref_transformer import EndDocumentEvent from borb.io.read.types import Decimal as pDecimal from borb.io.read.types import Dictionary, List, Name, String from borb.pdf.canvas.event.event_listener import Event diff --git a/release_notes.md b/release_notes.md index 603e9feec..280b7a450 100644 --- a/release_notes.md +++ b/release_notes.md @@ -1,18 +1,5 @@ -# :mega: borb release 2.0.9 +# :mega: borb release 2.0.9.1 This release features: -- A small fix in `ChunksOfText` ensuring the `LayoutElement` does make unneeded copies - - I also added a few tests for the new behaviour - -- More documentation in the `Page` class (some minor work on annotations) - -- A new annotation type (or rather a convenience method for an existing annotation type): remote-go-to - - This enables you to embed links to websites in your PDF's. - - I also added a few tests for this new method. - -- Fixed a fair amount of MyPy warnings - -- Added TextRank keyword-extraction algorithm - - Implemented `BigramPartOfSpeechTagger` - - Added test(s) \ No newline at end of file +- A small fix to remove the `curses` dependency \ No newline at end of file diff --git a/setup.py b/setup.py index db002d4f4..b44614331 100644 --- a/setup.py +++ b/setup.py @@ -29,7 +29,7 @@ setuptools.setup( name="borb", - version="2.0.9", + version="2.0.9.1", author="Joris Schellekens", author_email="joris.schellekens.1989@gmail.com", description="borb is a library for reading, creating and manipulating PDF files in python.", diff --git a/tests/output/test_add_all_rubber_stamp_annotations/output.pdf b/tests/output/test_add_all_rubber_stamp_annotations/output.pdf index 75f581b83a338069edc76751b2a846629152a429..8b7f7dda16a7e3a487e07e5b908382a69c4d3cbf 100644 GIT binary patch delta 762 zcmbQOF4Bs(7pF3ug4vb zt~~l!Ab)*>RxPVgkH^Z|N8x2m79V8)30Bxmj(#fjVY$cdAoZfdw?a03d7{2^dz<&~ zf_EZC`#Cc`)YC(DIfXh-$vYKuwWQdg`JTwmmznoJ`ul9rF7@=9S??9)Vtv{8^2{%9 zN@fKwT&3V;o@zF;Y-xMv?0Mhn{}qe<*gE@lQ%I^-rr=wj^FHa9Heb&4+qtS)~cl(vuHpY!eRspIup^6UqD>%UfC-YDL)vHhZe!MtRn&t;tLZ!eK; z`yfz!qMCJ^r=@|3k&%(9k;UZs?7EYKS?8jOsIkpN6Zy)v5Jlu13QuqH z5)O17#hj=*bSHap%|X)jp6fUgZ$I}L6rRE4BRq?cMDlshqVNnRm+~z|5&`)mfFI2b zi{%9vHQ;`YGBD6o(D%(xaY-ymRnTy;GBPkSG=NKQb{8yXa!yN3OiD2|wn()!wKPdH euuMrzOfv;4OEF6|Fitc#v{SGlq+~Lqh!g+|-X|;o delta 762 zcmbQOF=cqIcj<_nNV7w$|q437UWUt7|N0SfTKCraf zqMB>t{MTET2pb#4u6(5sv^{lQ_Abi>ZuxC*zD&vgss3$>c8ROktok4+m+H%xFTeb9 zrlczvqVU?xZ%f;4t!0|q;{k8v()&JUPUpjBuje{9HeY*?pva0>>Jbw2U<77PxrfHuOw>fYB zwR462l0cD5j}6b*ZI7PTYPtNR<&w;*M^lb3H<3@NSGe+WSHe%d?(?i|iQ7EQc@8R` zTlhlsMyk)91(pF3`r!q=KN&N)bSyuwcVwEyeUtIRtampfCUiK+sI1@y`|aY zW%~>1Io2Ewn;Ds9m^dwrEDel}jg8DF&u7=29LzcwO+<}tCYs1swuLAn=TLZhlb3Ly z>nP?#)uB7ti)#*&uJ>HWk$C&L&!F%OCLiHhgd~#BdlrRfFu9a(DUt}t9|8PmZdfcY zz^DQDYm|Y3rh>k2eu_(CNveW|i>+7F> z+|%dRd*Hk0Q&Goxeuu65m=+2LWzPSxbuPoQeTVIx;@*gam9qV@ytM90r_PNTUSacU zmVDS&@KWyFT&HWZCr&FVa$l+)D(muc+nG{-b9R##XD7~{_f7Ww5trRT;Y+5htY6}~ z#oX3-uIG8b<(5-d@hvKePMe$=Uo~UL%gq1pt;Mh8-*KA0BrDjnJ0rg;&1&+zxqii3 zA;KW@)Gq7x9N3|E?Un9^Y5z?oy*7#@BO8Fixo3!U^R^yi)XJ%P>X3w22 zD*Q*ZDgSgWf0X=Z~pIdy{Ol-`NN5F9bf;Z&L30wiZldXed&KtIpgT_^u-@`+;MCPqd^rkkg+STL$VIYyRI1_qi6`o8%oE{P?n3K}j}Mg~TP22knA zUsz)qjVA}OsWX~Ru41#UH&QSF0fjtXE-=Hu(7?nLUChA3zywpw#0*2s(!>H?%+SEx z07J~k0xCAygxxeYImIB=)G*o9A~DU#+{hr=&?v>&BGte=(bT}$B-zr$PQiwtl2|S~ aJFeoA#G;alqSQ1lLsL_8E>%@me>VUvp9%W_ delta 676 zcmX@ge~f=a3?rlIPWbr$YAa82-xYIxNsDIv61Nfq zThqB-{{HHg5QS+|Uj|g&FuXkZ-~Dnu+wG;^u@kd=6ipX3zg+n;q^ip5Xedg(^-A}`wErfPU^@}M(*4to6ntYGx)`I zaQm};>~r~l2rvG-;oHa9x5?*sZ>+C>b9U`jnP>^$gPX2z+k0$v`lF8<3J>JT%P{KR zusFUj{(sMR`AL86dLG$WU7WDwBpxW5jk_|zXmMFcQh0^ zD4f##pDX5&u>IyC(=>Ml%?nQs)wywIoJ{3+ur68n0Kbq5kpKVy diff --git a/tests/output/test_add_free_text_annotation/output_001.pdf b/tests/output/test_add_free_text_annotation/output_001.pdf index d0fbc6e772721041650988c79fec359ce37ed3e7..6affe821592b65555ccc05ab2d69177e39a454aa 100644 GIT binary patch delta 1008 zcmZ1`uv}n+A7j0RogG(kNl|KIE?32^yHkDhZ#f9Gz5gj%oTKWp;h;cK_S7ZQvVdb8<&GMXozt26&cAG1N@2uk1oqMc*Kb+ZKeq36D*M0Z%jvpU+7wxTUOtJIv zvh_~;y`ibX&RXdFfwq|fTGtQc2we@l*2Qnbq8)jx!n?!vz_RM1`s14)d_H!v^G(IF zQ+dn3b%y*3Irn?ky*UZZ_f)L>*7wO*rq8(&cujSsR>VoMi<@7XZqB}xogQ9%Yh|s{ zRJ*CglV9%q^5}`hUaNn<=3c(}Lx8u+JxhK~O81MKUuNAjeYth>YD?Bqk0qCu7v&k% zHgIRy%)a*G^&-#w%zPCL8u+Aa;dIY;(ane=Au?%{vFV)FBvU4ne} zhaZJ&SM9dg`S9VRj30MT_5WY_r^2p2`S0SBPc!Ny`yXX66xPV9Uw`~V`D2B-^^whb z7GfE(_HQq&tvmkJzRRRGM(T)rd$ioson?n6o~wS@t?}xL+66D?qwb48)O~x=mbg)^ zp8KG(0&mgtEea3*J>!czvDWcP!>WS))tnipHZd=#-gt;{vInz7;*nDwNxW5@54Ct7 zdfVTODSf4T%|7x@#hKX5h2p1-9>g79;k5mx;w$y}k(XNi?`E|BS8NO9KAdPWS4P8U z-L8Ni>v**m9I9end2S1%H(!gBIm620?n?_lxAoRLvqpOU(?abGv!_M(6Z&SJKZvASBjL_#H9x+%2h=7s>qZp^+Y=yObdPE96M{8V)5_& zoCdAs94R*c>)Ds?*JN*QJ!tw&Q_9SmeO~D^ZnoY(?i+S9u63Po$Kd<+Cf_&JoffZJ zDqe=G$UHgN62NhoIlrx7_tXfBFAFn2^j;6*nzG05S5wf#Lwsd1ZB zG&^mV4_5W7rmJ{5bcykv|2FC43gP6Xn-gpWZ!vy+x;^y&mse-l-(QyJJAGVsvmXlw z6Q`wtiII_!sj>0ocs4O4UL9LBqv7ORZ0d~0lbP791C106KtLgnmkZ1=Ff=qZ!4$JJ z#Sk;HG{X=xF|?T6$8H^)Y?@}AXlS08Y?hX2oMxV8Vw#p}VwPlSVQG+PW}cdAr(i=+ cNh}vQKPMKIR1~GAaT%IfnsTYCy862T08UZ5(f|Me delta 1007 zcmZ23uuNcsA7j0_ogG(kNl|KIE?32^yHkDhXFCYAz5gj%oTGZ$@W<}$VV+el6<6LV z-V%B2TZm5gcjdzWwduTO3m$dtuw0TLe{b&Jgl7*^Zye09u!_-r^gFzx?-%Q`(+{^? z`26yZM3{j7bKQ?3IWssHCh?w84-`#Z`{O|HhAFN++golhzuBdJy?!3+eDitpPWGjr zdc*f>hR4eDPixk^yvlj)h3}%Ws?a@8=Y8DLwMoxo>cJqhjyRw7^J3@58Sn18>?kX& z`E}=<*FO47#rT-g0)o|HTFTOZrfi1_vy6@v7B(ZgrV`N7JpX***K#NFClU zl4RC9^?G?=edvv>*!fv&x*uKk{Il9^^NLNUf0XoDRiA5@e)vIoO`X}I?W;FS%dLw# zoF7*A$N%Z^(@(Wu_fNmR_-Lt3*J8$=WAl&w>Ax@BZ@$^t=6zFg>$R_!`R=|dkNLmY zW76@hjx{Aao(E3LRF`?VX8OL4MSi(VYfYx?H|NSv@6VG6i{2zqZ^Lv+q1=y~>0SQ2 z2d#I+T-a6=eP2DjAx+1cVVAhHj6tVLgP>bZ&x!2|t_#F1RjhfZKHGKqy`;aBkIp@Q zMpUe7p$Y3d(;lso+02XTKF##s{b8ll+Yk0f46+g|debHgx1L2X8G2vXaMSX`n&A1y8Bf>`zGK@W=2&#tW}j$I(tYnEf$B%H_bWbB;8tsik&vq} zZn?ep$eo4!zRmY5beB4ue7)qnrl8)Ngy+xPf)CACd?&e3-yrYh(un$ckLZ8mjAqsh$d)`5l!1|Xo2$IAs~7#JFw8e@uCnqY_-S(;*qnHZW+?q|1- zO*OYjOEs`CGdE2(PE0m6F-$W~G_Wu*PfSTMF)~WEv{SGls3evPoShSkN-By{)3^-H MEKRsnRbBnv0Ij#Pga7~l diff --git a/tests/output/test_add_free_text_annotation/output_002.pdf b/tests/output/test_add_free_text_annotation/output_002.pdf index 12e420d25f4b6f9c80ba3a5cd3b9c3ac6f19b0a9..4524ba660f04c7310fc4819de53380c01d304c34 100644 GIT binary patch delta 849 zcmV-X1Frm)6O|LNcmZj!`EbasRgzwMNGf`cHtPYV@_NmFB=p~R78`6UP&qV*)aLT; z?1yI_-W_jXG#u@oBjU$5i1zvgrt{&n)X6m2hZV&0 zvW)ST5PN`4_vDUe!RL*qli>jr3X|wKy*hs6o$<7j{{bI=7f+AVtK+ZVIZMWeXwW-S z`(PzoM9-$z%&tkVon6f-s6!%^K9zHm=>uFqGfs4i@=Y)-Y- zMe*Sz{?(&dRNG~II7gj4=hKaF_!$mN-nNAt^g z6h{Myqw7h3avenO$eWHmHCK>lLIr(*`U#5DMJ@q|Pl$ht3-|4i#i24M1Qw2pq zJo8Y0r~zy|cl=yiXM75{MI)*7DEKTBO6rnnSVWcrAC&&491Io)*O;eh*z6p5)|oFDH1Z$8?gq3LL2|>~-wHOd? z6XK;`k#LX)6G9;j54;(|?N(yp(1)hMH(pCZDNyn{=?hAQ3p?1kh0&DqXNY@7=nITn z`m7Ma>-?!+k|Y5sS~NV{OU9#4jFrxU^+ad~#FyVz{nM*6zfXSv4$-q*1iJwVIWROb zGBPzYF|!~BeE}#rFf=kTG&eCZS}-svATLdCWJFB~lWn?w{ delta 849 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 JRdw}u0|3Z4tVI9- diff --git a/tests/output/test_add_highlight_annotation/output_002.pdf b/tests/output/test_add_highlight_annotation/output_002.pdf index e5d216d74c1013ce81ae2a402e48d72df49a6e55..b510d2ee7e883d89938fab8d6aacb80c02a676fe 100644 GIT binary patch delta 1018 zcmaDQ^ipU;3?rlY&<_(P&ldBoE>L-6psh1VJzt5rMg1$j~&-0~z&rT|?QHWD< zeXaz==6jQ^SWwkEUhNF|6>=_jS$_fJ+U(nswQ*%_^_oZ4SZnLQU%YI? z(^a-tBgKz?_573V79N;9J+rpYs`6ZW^urIzI`w6X%1=+0mecQRyT9hokNKzi#k<3= z+0Tsi6Px}~rO!>k-F)*CwORYrZ2`SUz* zUbec-%bE%MIu^y{GOaZU*<;R?pWa_5F->}tfDO|ng>pY`Cb_)#4_oiBx$v#v`kpqyuvt)=S(v*Zc6Y!OfWOuXL~3N8YJA6PvkE{FKpyxWg;z zU*#G5*qz+NKY!W9zW>fVllj`JN=#R4o>})h;KwRntp$gwSXZ9g!syM{;$+UWvbg)w z!q08J&a9E1Kcx(m=WUtsiOu0t*vl!p%ee0O>|8P>==`$Jd`2IS9B1C;$TaU8)1LOO z1xKvJ6^w3G8MeLWGf+Po;ut7!-bN&gCHlOq{q_25lJl9~UGUJd<+3~7GHF+el-R_j z2P*1SM4MG)zAN=uI~+_4ed8QEYno#5@BO?6t>qjkHulYz?oVkxc<2G!XA$1nbD7Uu zeP(TTs}p#W=a4O^Vt(du^g*?6%`P%uo%Vdn7UKJq;H1&=u+cnu$8Ap?nO_%7e)L`s z;+nF@?^jch)x$%4WqFAvOaDkdnkV>+>G3o>ZI=&L^{c{FJRQ2kc+c}q`nW_qdFkc^ zTftk5A5Z76{`d0g%=^plGoIQU&9aD*-O|9s$jHcaGYeZDqZ)`~Xku2OlB%HLVr67tWM}|YJ9!3sETi${Z|v%frjzA3tm{n`3_w63kCzL~FfcSRu)q*A zG&9E#GcvHm5HmJ3#1JzvHpUP$2igd>Zt@Kdvlw$z3p2}9(=^k>R0H#*6icI&v_vCA zLrdcngS5m%BRd5fWAl{MG!skHBonh_3!}6oOAE8Kq|_Ai#FR7(qhtd!yI3weJFeoA W#G;alqSQ1lLrZgWE>%@me>VX3mYuHv delta 1019 zcmaDU^h#($3?rk(&<{W0l$<>Tn^%pH}#k(Kbt}h_}h5L-yS>95&W-LjzWKka5UaVDQl?}*Z{?=jtDTjm+D-ku za9OzejYa0Y{g<;JxxbrvW|qe5Ng<+ZQrchK{BrB&)|aK5vn}3URh;NG|J2U2Ut+3G zzOmS=R{!t0?fPevt)#xpyP_CzlJDZ?ms>YyUw)l-y?|?#-;ztqi}H+XTeve~Z=ZYd zd6V%UZ^g8`k(HJ5=B>KnZ&#k%WwFx#QM~c4F6rGquZpjnEVjGD)h?g-bF=W?=y`WO zR1}*0NqegPKcsF`#GXz6QVJzwXY$z9+T`mjX&fo%wj>b0E=6E9xtHmoUcu+&_})zwt-Y+-=%jjDG)cGhn@_d}$h z-7V;4;D<=HDOXf4Z|KlrJ@#99rG(1ECE|&97`e<=C&|CMw1sEp?fw4en~N-v2|vE~vl+fdBCSo7(5f$u#R#3ih0sMzhJX9M<(_ z3I-sckjKjfW*8Wn7+7M68JbyOhye}75HmJ3!VohtHo*`xH!y^VO}@@y7L%5mW|3xU zVVZ1aVvuTPnrdihl$K~}U|^bPX=avYVy9qZY;I|uoMvHUW^S5nZkS}4Vq$7+oSI^i mWNBe!oN8=h7t3X5$5mXCSX5F`l$yq6XlZW2rK;-c?*;&j#i^+P diff --git a/tests/output/test_add_line_annotation/output_001.pdf b/tests/output/test_add_line_annotation/output_001.pdf index b6798ed96fa5ed670933463d3ca6700731fa3b86..a22536620f2b8a2c1092aaabb3477cf54a4397f3 100644 GIT binary patch delta 867 zcmV-p1DyPu5StLNUIBk|+At7?@A(ybY-bpP4Tg|gJ4t%!A?eU_Mv)iTjwKs?B=p~R zg$=eR&~a!Esp0Z!^}(x$*Xs?8hNIo*i1_ghqP>2BWIjwvJxgZ$vVwR%J5tZUhM7<* z*T8HN)m7Gt4?GkrS=M+Nzgk| z`(h>R_bOr#v^AKEMSuKAYC)>!LOM%SFtpwes>VsxP)!Hm6$a zqWEwUf9ugSs^fn$KAfXYp7ZHOIQ$HYU#;rx;^c;hi=*XtyMFvn*N^A(H{O3Vxg5vz z7_l;XJe^x-dq0jBT{fsE(>pv*UEFjyE| zqfXIq*tzhWXTD(2$bST<8_-$=$qi%wRB(uWFAebWE^*5 ztnw^GPlR?r{P5eVe|mN1`{@so7Mw=2Lj(u{C^;}RGBPqXGd5ZbmGVRU66 zC`39kFfuVPIWRObGBPzYHnVdEO94YRHaKQEHD+RFH8?n9Gd4G6IAt<7V`MXAW@2Jw tWHvNDAUrlUIA%FDW@2VFI5=Z7HaBHBWimHoWHV%DVq#=uHZ+p~2paSajywPW delta 867 zcmbO&Fk4_l9Aka{EeC6&)d}5-aC|GaVuW^$oKUEvR}AWx)Xz5MH*SRh#u*_*;&D6cBUm@ zCtKR&6@8n+Y91IyoHRNX?evCm+uh05b6Mw``<+WUZX8-xUFxx<{?hXzyDMK_u}FVW zyO>#3`sax4<0XBY^gKfkdTr~7^I1PLc5*`UEZSb;NLU8xD&Y!84jWK zJL31Un55ohys$Uoaf9a)#vX&DT$hcFHAgR$<#EjaeKPId%C!;yQwm=P?!M%tKPB}* zZd+ih8*}Mm$$#xL+;n}8Uo0tFVj^3*@QbebiUzLNqDv~LNpE=Kpi#m+VdpjtS*v^r z8POEgm!=7BHkpP`c^jUrJr(S>hU=bBRFK!o^vO}oeD&2UIK0+uWte#JTDRh#f`(Zl z!K|*1HlG7lFy`2n+sutlui@I^ti1Az#t$7~uV<>4H+1N*9{a7l@`dU{PxV7Pm_>5J zj@q5^zHF3|S8vX^>;qq8&-3(vU$adlba?UtmS@~}BU5qCINl)R3H!l!Y+J+}iw;}t z5zR@u?|tO4Uq^UMo$sMWKD8Dn3Aqa6mfLfW99qcl+kF2=j925N>z?reS}`{cp40X5 z)7+l;PI95XLEg*FPAuy`FVAwF#Ihvg;)fi4$>Vb+R@-o26J97Qu>a4tSM%dyf7Jfs zJ$`nM*JfuH4kir?BTEBgATW(GFwj)c_svgnNi0cK&~ULbGB7eUfJ<*KX7grrPBln0 qFitc#woFSkNiwiZGcvL?Ni<7LNij__F*7tbw^Ohoq+~K9hZF!xc!{e3 diff --git a/tests/output/test_add_line_annotation/output_002.pdf b/tests/output/test_add_line_annotation/output_002.pdf index 8673f89f66f190ed540be87f0c2dbc7021708ef2..93c58a10358c3be5fd70429574a53844e0f7b583 100644 GIT binary patch delta 1075 zcmdlZv|DIH3}d~SogG(kNl|KIE?32^yHmZ3ZyAWRe*Y_4e)F6Gi?xkY*;|#D%et31 zUzc>IW6|L+UGkxE87-pRX8MSW~+Pf|TCmEXCQ{YHs-efb^M`Q?_D5Bt)! z%B{DW2fYlQ_r1Jo>p`}?g++7XV(mZ8ez|1bCOyy4qh8xO=J~FFxz2O_+jY;j1Xn9h zwR^hrMLmrpGA?)vvU-*0`EdfU5=d`cRTj1=Bnn2Uh_ZQN%_Sf zzu@D|EpG8*YahnzC55k@DqikcU%T<>Cd;c))0ebQ{t?~3%u{yy>BE+|zWArBmDgm(B`3dDl+EqAFWhh5?QHeB zDY^07cVoW0@819X*ROP1uK3aqjV)$z6-K+JPxP4NC(ATseAdJIj?62EN+f)bvwK|*6!*H{F-FDI@ws<)vtXpUq2y`p3KtB6Ex+mBU!`)pRu%>ll1_peXKN zW3%AB>H|;p1J)}zyw+@Cn0Q&OL-EgthFK!PtgeAJp95Af<}j7pm1iHqqHtm*K<+>k8ISu zx2lh~2q&k0lCTxL&G_-~`&IuWugrYE{Qe}FIc{93c`3!4!&zo9vRfLM7#SIvZvMvV z$EXJ47@C+HnnoEIXe#LY=BKzMmZU0ZxL6q(7#SKs)lSZ0k7YEUe1ct#$;fi@2X^av z69oehP{`xu0y7K@jV;YF#0*W%FvTn_FvN_3CZU@LbR>qDnJLuX$*VX_V^h;i%}k6< zEz*n(QVcE9EK|&rlPoP#Obrt)QZ0b~vQw~0O*Jz%NHH_9Fi15qH8HkKGqW@@Ni{G? jNwrKeF*Z-Oi{%0r35i7|6-B9OT!xm$hFq$uuKsQSLmsjQ delta 1061 zcmdljv`1(|3}d~yogG(kNl|KIE?32^yHkCOZy5-*z5gp(os%w+B+a9^y=>B#OU{=T zKJQV|-yrL4_RHf^{e4lh8}powFSK0Jc6#+y_Vsdc>$eN^F24J`*BW&$&S2Q;l1MS;cfeO)<4$!vB$IOknH&@ z@5-|Bmt0$J^ZxyptY+P+%RemkE~|TDK6%T^P3t_a9*rvNnCH9x?KR`=Bpw z`1;(b?%O+d*54?)I`7q*?#YKe|Kz%D-qCsbNkN}g<+^>m6?-COCRNJIcyGy@QTU>~{`mKL zfyi$YCLd#8So*MKu@k?MP~n}`&I_ito%-(f@a?3F{D+I2#hh#$>ZP76%XB<&_p7eW z7Bp$idQN(<-YvJAH` zRIqB94SSw(kCus4hSb>~_D4iY4P@Omzihmu^UC>UbYcMG)N9%&y7m|(oNNqu;ikZy z8)#K>&%i?Kq}QeF19K`aB^|4mW;hugn$i<7b}C`)8c|+O90nl=KNy?pOrS2yl}q! zKz-kYpaoA#FHN7qDPC4kY6*WP1^Xr%=WzKQqO3h2z9Lh42k=??`(!ki*c=K0QKSnhW$I#fo z#5BslKvO~AH$TNCu_RSN!^O(Tz{t=5s&;ZFdn}{H(3DXDrc_aqq<(sZc?SO#Z~_Bc}(A5SBbu?FK}DBdxcHMrO=t5 zXXWu_TzEaPsOpw}rTW(`-M_rNW_m@rykC~S%=qQamnO@*Pc>`APQ95@rEmLc>gCJ- z&X<4toA)s7my?$H)GZzNe9!x&U)p>*({H9$6Ih*9vzWy7lTv$)vVV9ho;((HbEZJ7 zMD*<7YgSI(b3a^LYglk$`<-_d$2LCkS$Xj#& zZRwo_&aqy%99~YSaxVWczrtpX?234H_Qxx8(yXtnj!*jgxnS$8b^Bg$##w(?E?{;|dK1Cypd%eTNiY^A4`-0%%# z5!@Ee)SdRP|M$M|cENdjZ)h5^&8#i|vC#7S#UE_aB}uC`J2IbQ(XccyF)}hTH8hSg zFwj)c_svgnNi0cK&~ULbGB7eUfJ;v{=7?rAo7~T#&S)`tJCHP)e4j(T-cZ2+1Qhak zxxfqq0}Bgd3^7Y1Q*<#y10!<`F(YFG3^8*vBTO+%Gl&=;!eT=UQ{%~#Ijx;7QxeTh x(kzlJER&2(%*{*<49!zg(=04ZOw5wZl15 zU8w2#yO);9frQ_SO^kv2`Z@x5HzIj!X#@%T*Q*KR{`#Sq& z=KtT;%@f`pF-&Z>S_3?;L(h1h5Ym?UUpII;UwtK4o{}8+0 zMe*1C7f-a744ghGx?r#M`Q62b{~vjr^w#09o`uBurv|qdM*kIhUEd$R`umq)wMPfo zZ*sMiSV>mwJ9DI6+@Z)w=DsHK&L~ zEO>K3BlgXYpeBok349xLuSYPvJlc6f<_Fh}*Kf*Z%ut)lH+}kY&Ef}gMe{h{EH2@F zHRa^S*^^j=a@O;R9sVQFzVLpl;Jm#zG>upzYs!BtwEUYA&-{}%rG#purR?8votb87c(?4vcM2CGB(5zGdDBF6tgski18sTHncD`nLLTp zIyS{T&C(z#In~%8F*(`T#5^^{(7@E#z`!gu$;iMsHN{TBhMJcLM+c0XdTZ diff --git a/tests/output/test_add_outline/output_002.pdf b/tests/output/test_add_outline/output_002.pdf index c66d36d56f59d0addb63ca618f4a34758014e04a..748ff4cf1e4cdd194df1d435d4aa330405cca37e 100644 GIT binary patch delta 916 zcmew={Y`p94P(89ogG(kNl|KIE?32^yHn%+n+-&c-v2A|Jy7^?#!vNqnI-#Xyzsd% zzO6J`+)U=mkFR?-INj!8E97UZu(Z{EdM94*DaX3UVd32s)l5OJ{W+4b#V=doQ)gM=`@+M=LOwltsJzs?Ir)FVTg?J{{TCkf?Z#TMOJ6B?m8Y)D z{#EMGJkS5u%gp^x=bBv5dnK%ys+B1y>vP^G{nF;knSN7OHEZ0RdNajpiX1Oc)&Jkt zhfieR2?}4573|slBB3hHYVy3fe#Kg$!Y(h@ol(0i8PiZGyY`~(<~DngN%?E0PS(8G zx^b&z>RRP3H#zfdxjOU2>(}2*zrXYRQ)i{0q8sKuwcB)#JxzS=x0|Py*K5r`_EGmjJuKCB|(}rMMOLs)){Jj%Tc{+$*QPY<67x>Cca+SQfCeo@f0QxQ(s!l*kR= zOfJoB;e6eN|N0MWyg1BpKJJak%toF4)_*R{Ni^BVpzN5mdh$ay;myg+``9%s4NQy- zP0UP8q6`c)74&`cQ(O{DQWZ2@tc(nd3=KfiMnqZutGFXdJjHCHeI0fjtX zE-=Hu$iT#O@&ifMw0p~+-LUSUlP`;5#i3@}VEwKSO=%WEAA zG~LY7(9%4~z``UcE!n~})hsQ|I5`dIZbNf(V*@({8&jjS#AH)b19J;wlSC8aloS(# pw8X@eM582g%S3}TbGukBaGpynDyb++P2)1MG&15+Rdw}u0|1!|M9KgF delta 969 zcmew+{Z)EH4P(8zogG(kNl|KIE?32^yHgMPHyel?d;d@L{ff@SEj$wUOsw?P@|Kk! z-j?_JP+Rk?zrXDw7Ur@v?`US!i{C%()82TwryT1ZPYZ9ZsAda#Dg0yNq8a96KBZtwYhrSo4OkN6~=V12qaX)XVm^-^!Ur~3a7vFlwF zf6agKL~F^w>64-hPR@OPZ{h>{k2@l)FKpoEJ63FYrtC%7{v*HcKfe0P_V1KViw}<5 zm=x#wvCY#r{;23$C6VS{a`?bDrS?U-2{Q|Abc#C?zge_So^adgSmd6QkNV##NV0}& zSQ~hWTko5qz^AZ;Ip?&gm_t>ek{SCxrf*ieW!08>E=ARJ?4W^Re$7*k8* z$#J~av6e<=#z`ru=1ED(iOI$mX@(}IMutg=rp89*MrjrXW_AiTi3X_#Mk$uYDTd~W wCPwBd$tI~5W~oL7riO`@7M2!fcClRGjG9gw+X0JdFDr~m)} diff --git a/tests/output/test_add_polygon_annotation_using_line_art_factory/output.pdf b/tests/output/test_add_polygon_annotation_using_line_art_factory/output.pdf index 2e8ac885097c577d71c5f2dd3307bde4363580b0..09299e10446177cc4334d0e463be1a572a728500 100644 GIT binary patch delta 980 zcmbQUo^j54#toH>^`abd;?LLZDp2oL+VsJFVfV+|>sy^}uhHp{6MOLKOQz=e-=}ZK z9hen)HCbT3e1lXi>+RV$x0dB@-xz#gUiJrJjh{T*UztA8n^-c_?`GRt&6Kwr{da6{ z_Wob+OeAN2>)nZcXFE!!W;Jo#ow{@7%XbZ2dsU4tPu}-%{*7sRmrXSj>$z46%KG^G zF28j7vZo(JVPvY+6uE6@zbyIxdw$>ZZF<*5R~{1yQns2gZ1JtpB}> z@Bcl=Unacx@0L#=ou4M3-@UoMF57bZ9?NY8vzU%)=d2eySO4hama+qR@-lT1mkPHz z@BgK_+FqgEx!~O7=qc%pCpXOzk~01odn{5!rBIA*$%2Cu-(<$!al5I*@pYH=p`!RB z>3r#PY%lXS*LQh8=w<$`lyW_jlV#g$-k9Vnrb&)7=Dp0F(jcQ&&2Vdy#vCIdb`b?n zraugf)(#5&VV2Tu&)I)I;$hj$#ca*QX=z|$WMpJ&Y&Kbu(`IrP>l-AIdbYbryg&Z7 zlNYhiKoSAzsOOl8B7&@=p3P>mGuHux{AM0*K}G}@Y-JM9Yc!EbyvQOzLpC4ct3cMq z!)>#k2eu_(CNveW|i^@5Vtdgo$GANonTrabJwq<1WTzZh4pvB3!&9ftPh{@#`M;_nr) zWv5LI@BZ=i;#l15tx4ho5buQDlJ7V^XT4^nzYZ=QMr<^W5WuD`ssolR{X^-xl z-|gA{2fuHg+gDQKwoE%z*5%c@Go`-e>{njs23XrZ-CiSXed_5hCDnRgP2NS#FJHba zsY{r~suQn7USi%B85UYP>2KK}m8FB@Oh^m8(GT=MSJ z8soc%Shl>*>A6>vT(Nk9l2O>X>mH)d9Qh>F{_QY+}B-anFvvO_2hxzP{&p zxvs;X>6}INGI_TD62St!%)6DI><{K*FLekrp0_?*rFI{@l@rT zh{Gh7BaBRS4GyxpR?=qJ_X4#uNAq#=Lb~X1h5xD2`DB9(7R$2AT@`zWFIGi6yBD8ZK5w21bSkaOusjgM*o!(^3=7 qOi~Pul9DZrQp`=bMWDVf|DE)4)09$%OM diff --git a/tests/output/test_add_polygon_annotation_using_line_art_factory/output.png b/tests/output/test_add_polygon_annotation_using_line_art_factory/output.png index 9b9088624f0e74bbb245d696f985c7b9d8d6c3d6..e5dcacf83da90981fee8562b62e507ae253e71c7 100644 GIT binary patch delta 11615 zcmX|HXFyX+(*}_)ASy+=NRi&8i39-==?Kz6I!Nz5aF8M@AQGfEQ55MlR7ofbMoLtA z4J8nP&=L)VP`-HYd%yh3nKL`PJNxYJ%rhr1{AGAU6}@b0Rr@7s)9s+sv)pbL0#yAO zr@$Qx@6igrii64WOHFidNT-pv{V7ZbG^~^kPl9W1-)ve%4Z&(|ttcd~Bxbjwxtv{&HLN3@$H;M3_8mgUY(Wb7~w{^_iK zjl;_@d4}K4_)RHXZLVs{e|N6hXw*gYT3Z#9Y$kxigQZ05dZsp(Nx-}>>6!O6v`6ft zM*GOM0h$(g%+N0EY}IoLRR0~uUxkW0{j;0iL1*GB;y5IHJ%7*%WU?y~=ih93VolnW zhA&~xVowhGo*dr_DaJmYDv>iCi$_egzYmGLIEfKH@}xN~YGJg}ZT`H7Yzss;p#%sTVFbl3K4^OWj4ZmOiF zaIMkP<2H_bU%>#tkq>+_)R!@$w1lq}g_E|a;p&Me+pq;>S2VMyrC#`k6Y@RhGuQZh zY~S^^76sLr`LHr7fdYHgVD5DgKgCT6{isrz1tPVfQ1`v_m-XuVXYl{7E<1wuj@0w4 zT@YsTo@S^9{9*HMmMs%EAdT90m_eSai_Y6hN)R=MAxd`(z-6Q$(bhXg73!&T2kE!9 zj>Xn0xN?jLhgksz1t+dIFiICsaYrxe5xHh@af(yhyY=UNh~x=6E-Xe0st_BI9LKj; zi;k})6Rh%15Nje*$NsA%=_vpQ9Diar4Co%h8c4Mf@q=7bKh?*& zVj(pS2wel%OiN4wnDPzFL)OpeUD@H&-eTm;+@a$4gAVvA8DZ)5t$XZk9iNE4XGkmS zx$pFrTlp z``cT?SD}P3+s#k4{?AJT^A%OyBXx>>3d@^40fO=9I}NLR^||B$#@f<=@%_%BR;$Ov z+ER@%pQ|%Uu;xG5>5}AwZJadYnCs7{(usdY@?u~JO2XkO2MK#dx1z|#?HMq%=uUKm zovij{7>!D5oCOitU{WF6FMChaGUjw6*a?EA6FU=!$rBqGiQnC`#E^_reAujKA5sYb ztMNqZweHMy%00cS5Y<1k+*hwMh26qMKLTa7SqRKX-v0H0nxYVTyD<8dA3}M3!kEH1 z{1oJk&rx>At<6^SRSea$YI00HN|^(nPbc__Qb=ZjDaHkf6d#4xVqv)m;q~h~1-_?m zMIQg&e%`)=x}}sBKzrJkAWO129XJ4vj)h9EeU*;D8QIHUSFh?ZZbl)xY)~1fVpQI} zU7Z*pH{dL8F7_1-%crH0RF9QBy}chXMq2dkOj*A>S5XTJb-$G zBs_G%oqWvv+qL&xeI-qzU;mN*w@TQb}R_jFx-vZwk4ZuBSltSeBxxm$Rso-o#`Fgp0n z(|LC8`(vPEHeF-a%(BZZyEBj@!171t)&pNch}5l+M*Uk^v>mhb6zM|zJu3Fa-q(n> z`G!20)3)kDeC`0Z6Dlrp8A!(zf$Cxla!nvCT9L=7+I#myL$x|)`2&Ti5wwkI(W4-5 z_@c$HRnB{d52?~N@mEg}1eb{vT~7duVN`;R0wxC;GJ8d_U27(^u|5R!`s8{EXdUMA z`w!*koU^X)?{W@Sc*wR7*_C#;*0-_(OEu1joOpRNSP@E6A_|7(#&z5WNMb;@7NAsn_Ju*Go{YqpIy55ytxl~A@XTYy&<-}E4CXlLipfEil{=aqB)+XKGQAgZuep38;iBQ)xVRLxXu ze=4fZG%nNMh<_Zs_El;j78d%4n$vE;U3I2}g(6(P6+;zY+)R1p#<{HT4CVkazDUqqd|Tv=Aiy1BbTUoBiiU>f)bK59p4!S6}&Ug(Jh zeN&anO5*=Ku0iD4PQ2=M2MMRgwDO-HS0(bGwYglaWw2j3sgs<41BRfKgPtaqowaTF zC(0g!Hgt#+i_FHw!Hz}F3SrYCQF~6Co^twWp^qO-aH@H!UlqSQ+i|x#n|>}mk$HgG z+UCy~>^n1>t%U9zkb-#==s-L+-{`bwyD*F}SYXmpV#!*#ZBBS!F&g#S_6>o_2$vDF%3`H zg2ju_%cE_AM4lAMJuAXs+*5Pzdw|t3V1D5N2F-A)ozuP;wA?|Qncy_m2d7#$?S;Q0f50Vn#aH1h3Z#3*VSe|3iT~~#eg>Lm zKIQpm$qm>c2RlQCIQQE=B9deD&pZmilVY6;mGP#h`XGrbv~tjRl~V(d&*c>P-gp5r zu6=U~i{?=1n6HyUmM9(7e%2*6G>HGg=r`D%An&70@CRz{Jf$DE`B)O=%S5tI$h!*Q zsd4Ee@1;kt-?o3KF7}{LH_TqT@ZE^@F&ybxx0j^{(b{(wUyLnT*Fe%J2n6!X-F<>esa@_{;?dR-Hx7=@HPSz$A7((-9z%%BGd z!JHO#B=1)7%f$efZ}KVcLO-YP4O(D}Io59;pKmd5n7DjF;Z1*NQlc+>*2|yG^V|h7 zQhFnH8^hDJgU@$%zk1Xt%!?`?SqGN{QhJmdWQH=WYsF+CeI>rW;mBP3=A09LNjD`x zCgwJu51hv9t5-pb`M^teZst9O{8zr;G2RsjtE4A&V%YW+KhE9`B<(S~tSfL%>A7U5 zaH);TZEbt|qB*Z1TP-v71MvDv&jo3dTx8M^cMrua$L*V9DQ?zL5zAm%wvD%Eu^{sh zS(?`-7{`Fn&ncGGHq`1=^G13$G4}}kT=^d5aw#~8 z8MTZv+N+Oq%4bUnN6!2_hy;|W`fWK2Bz<5c@Ev~MW__$X`2=jfFyDyCea~RXsnWV3 zA7ThkyYyvoJ4xN~t?i!M*J)SeAPYG3TBUtsgc`=%v+l(e&xT(v{deULAo?6JZDTw5 z_tgeQPoKZEG!hMwsZ48(z$Y;V77ZxMt^Pzv`C%7E4PoWfRs9q}Nos54qYt~5txWJ2 z-6i63yds}I)gCdHZI-SdCtE-B_S|$y|Mn&@0dZ4d3-^sLrfp6tmX^Ya&7_?otMRfR zVDK5;Mb76)C!3aOcZ6deARawz;>e!A?t-K23F;F@ZAlJn3>%Bn%SzbeG;fYxbCQLy zs5}p$OL&$I&RXqVZp_#3>nYO4UXdUQaA7XWmfS%ocYUyaOz}&?6!#-Fgzj8Zj0iJ= zHt>x-zbbNKcI2%PN~>1l0+rm1`k28W;1x2z(=j^#5(56c!gEe5>NX$pj4qA>R&e0G z*CWIq*uIo{>eV-S&9|TVk{~gTy?gfK#U~5+ADgfDV>#Fwrgn|08kW1L^+3@<%)Lsh z>Qfgxbj!HdtK=#=Kt!&sMMN{YkfG3%A zE_8)^)Gp5PgL&a#28YFXMm<>2w0iTP@WI<7P$vIz+=OSA^leTJ)GenkFGGTGwOo+~ zN<|{L*d~+b1-F9qhVVJn95J9J$L2!FQZ?F_vESd(gF8Gp*%Kx0`-NGMNaK7kpSd+~ z**WIcupkWhmfuospAY69=xG3Y%V1vy)<;m9NQN({w7M{@2%73?J_5MMk)2@3nlrjK zoC;s=s`^x!I=SGEm^xUM{4%2+f$rRI@=>ekSC$sW<2lB1B8HnH zyut;SzGur1toBBdp>uZOnz%om6!M$)n8JarfL#qBFtwFC zzy=_Ev@##8Mpg`522z=P97eYKtEcg6t@xXQ3-otM(r9)W>NciHsFb6{-W-Y;@f~x< zU>jB>?v%>N4tqp(*;%T~enjnqT1@v@&QI0)j=d()x$mja%nqAZm;AylOx^3}j6HXW zN1$3e@ZPuCjw-%xj!^%IX1qXabN{>D{a4Xm)Aff8YJ^!Xz|YjhQq4BIRTbXqI_}3( z>LyzKBxCVO*JP%6<4k1??7Fev+mX|}ih&^e)BUc)w?-SekKe*G}0w6BN{ z`U(&E7}8a4fDqO(eo$>cR`2j)rA^{URJIRvNj;uU_kPYT-H#JW9F{6^Kbj2T;rl+Y z$xgJwTT;4Je?-vBSBGIQ&8zQG8gO+yr5u84q8WC76o6gRR+Mo8@Oa((XhB-Zsfw@E z$5)!mfe!COX%F=nVkS5$#g98*CSeJ9P z+HaKgSmn7TI)3ei<=dTv@!N65iB~qykD*gFlsqB8P!o@6kT_4dOAtdaY$!#*V_!yQ z2ytoz%S&V({4plzdJ@7b&MJ=W=lc;kKoXk*8s~LtDCztgc2yRxua=qZ73u~XRrySS zhox4Z%zq&>Yd!ELU)T_zc#o|8w(m+lvf@)CM_E-}_`OwcjQQefw1P>yWJjRZUG8V& zgZGMDXvAEL5{hw~L@5C8Z&1d-piRTbayEkK ziyZg-xNWo7v1~xT5+$PTg=!QtPy~cq)@@8l$E{h-kn{+W{Iop2(}yCb4~yDS2PLtO z1RaV^WW$Y0x`$M(Ji|bnZ_`gGRv+%EwGo~vQQ6(ViBk?`2Tg9X2GUJ#9&ft`wZ>DW zG5P4^MRE%*5P}TU*21}*&LXhaFwZ}q6get?gVDH)g(Z>EV^M$W(^0UoGtdQhNNSv3 zD$g2uN2}=d2Wa|s^M&chlh>UNoidsyGfP=n^{xtL!*kEgWtw^9TCS!pO81FhhWD{n zjT`KF4~m6N%M`vmQ*BJNzwgCm!<4arMRC%HRw>k5q+PI9BJ(&3)WV7*#3(*lTXZe6?#kvESyg zJlG0g^|jVpomLX;2#+f)JUaTqM9i(e%U!csTpN(ZN6D9hj)fX55O5WZ(8ZdVL_FsR4;dfL*VlHxBQElJ8R6#!`v+3iU`Hlzz7 zV~>QUni^_#hu}~G27Y2mO#rVxF6zB%LgT|%)OO#KyE$5M7qiu3INRGA+r7i^UTqq= zoP}NXjcN7UR^MY9%+~(+GDpViwyKBiqTJ9Gb-bEvikL0nm@AAr_3Vi>L%=3Ww0Wi= z4bs>@dnPcRAHB<|txwb){nbQUR-c$K7RC$s{L%bpikT;UkhYDm5<-3d@CQoa=|BzBe`T8bp zdrd#Bg#y4gi;@=Z`!KhcUGrDaTI?K0Y2Am-F0IMVZLzGzk{2&s-5(@%UXu6fFZWA~HM-KqnN?f=Rh?m?RTmMU(iMk{sE%;2)cGi#;yvs| z(9j$;*neTPQ}$>YV$-{u!FTO0PLB0>I$oN=xT?W{d9ESxKI~#$G|VacE|U2U&#vwP z6p*s9-26q3zUm|wAir~+~&k%+(H8#&Tw z|Eoxet0qTN!wAYzZR zai>su*p8-(*CzgqrSNXVP`&xfPiJ|u@d7#Ia)#65Nu1*$92W7RSfB6~((P7*4lZZ>}>db4&bm)iO6{x2NP zHOrRF1e=7>{CO-sllo87E0u0#=&tOmUZpDK=S|;YPlKJ_h|aK}aVA@;5m~eHyP&DEohD+yA6i zQ6`>m|Cc>rg}sD@|0dBeVLcPib7ucrH(}TRN%`eVMnC`O6N63*eSLDaoe74&S1YDB z_|NI~e| zaAu%am5H=zcX2^L%Ngrt)H z^_Xg?YKL+3)5Tn}p*FgIyvHx}eII>mH!7M#e8ymN#{l%Kj&vz2dSq6cJjKNz1Z^2_ z%V#&o4ka>RXnr;QYbS^|I#|6YKSqrVpR`eZ5Zz{yut%B&R+Rjl=dTZX_NxUD_Q-=` zxygcZX0ieXE$mUw=BFhbbG60?!s625_WY`^Lkt-o16!}riFc&!U1;nU9yaCncH)JI z0xyPg^M<&;53TWbe4^~WFqTP=puKk9#wFpVYleUW-On_2nqPg&2Tw>eybHSriH}s* z9?;fBtc7((FTg-Yu7H zOT;5@%it&IM3JGb%++7T68+sD(VBnxrb8jMtlrDl{{gJ|E^2a>(@ophuljWLR{niAn6Enuyt3#H-#|S2na3EBQ#DYtsBBZ!IjHydb&7<6 zTC#1#PYcC|e>`-gy^c3yFLzXtiZj7GPj;OvnslebM0K3|EdwljAnW2wHSrePD|_gW zbpK|R6r+K@fy%{%ykw&Xoz$9D1>I>fnwv9IPY@Wc1rNE5e97c=n{MhLhC-k&l<{Y* znQD`Yc}wm)2vV_gM37&pmyx?8RKvk;Zv4I7s{?bpALlg)Q=4a2F9a_fH#2QK71!Fx z(UJB&-jqtUx8rgzO$rNL#OrV$N^ae6>4ZKrpG%vt%Q-S{{o!`DWXTi6OgxDeaU6cY z0I3kM z+OdCHz}8D&EONNW<7<7P3X0Xe#{x{b~Vp-jjpO?OkN82|i&kH86UPur5Y#d{*2H}45`@guCf;|;=; zc;AgZm~jc;h@9Ds%>o()9M3GZ2S%|N5{~kzG8|KVHAd!37jpWA$?nPm#;X9#cMxet zt0l*sD0|WMP=a`2Gbw@M__crKu?+F2;t9{UzWc+NLcu+Kkh$}d75mYP6ue=FBybNs zVGw@#S+3uE(;n)M7uWxiw3ln25+QUP7{{gQU}+&g!N^=VeDwLNwmUsG%1$}^hhBSjIYOlzJ9)R zfusl0YW}`k9+Xd~-PMFg9P4-! zDPgmLdo~R2NLn#fh4_)b2Z^MxV@|A(E_K)N-tZ>%3-c`XzZWrxv$S|b(p_vz7nfad z_5CgGqCw^O)oHw@zVWz|0)m$4`%GO=wXqctU{Hae5LRxVQbQFO`zbesZuxE#>BN6L z2yGh4e(;my{S9LrYwp@cR>4K{x_mJroz&EFXv@ijDYDQ=AswN79La*}9ZzFEpSvRf z#U%3ll#>j z5U+mvB<6j1sUfd}%se>h#Q-xU;I^XGf*{HIs*nNO?$4z~Hs7itF`w%fl{2e5OVI|a z!`_(MpIu9M1*=R~b_D|_SIYp+oId|n38D(>N6L36{59;0thP~B{es45*3HQqu2EBv zzX{lt^jnwD)u~Xuo@F~^I%oXFq*7wu80S85aDyv`E6Fy9M&geu6yW{vxa`A9m$Uf% zecW2>*&T6t%9R=wZT91KocPp_r!{*fkbv`Z%;nzNsMwB5%brsE6zi=%x*F3(YDfUj zwr-{-#x#cgcR|)z)|_Y-SldfAE=>hv-BnPS-z`` z$G%b_RKsEh&%5C@5OZ$uSW|K>p7ozQnUvMbAOzq%@c}!>wjJsy-jHQG3{LW4@u_jr zk;G$KRnNfdR!xV$rRPqHm3D}N{PY^{{lQ&U%BjCOHUmROzz)WtGPHZ7P)t8fEy};>Y?Us_vxXqtbM@V!fu3^YI{u? zfMZgyvS*2^`fj95d}MYrxS5Gu=M->oJ7La^->3gRwSM7p+)$jTV!Y(S0eqI4JSseJfu$vnF7{`fdMZ#EUI$0xh4DElD)fKQtN^MQOUf0B7ww)Y+_T$Z+hcsa01JZmxpQUT+g^8K^^9 zz2)d9^2Q?jg!xf8S&0~uT{{9eFh3rk^>ywM;WfeuuiEhm)HkG9Pe0|oi=!;M7TI|| z;F05*8$dwcWMx<*r3+ME(Y1VWFMJ;ptcEL_OHyc*^$LQKGh)v=Y+<(jk)aqpQQv+rO;P&7L)4-~DZ z)(^m%lPA?zc0mojPBVLeS2=S@G&H2VuUO!IN5V}iL5bkJ3u7boWF{FE@}2YiM&!q< z6Kg}+>e5XS z$GW&M4OE)F3^(YF19}2`zOw5q2Fano(#fH2tlU3Z(ZH05R|RHJg*3c(J)H<$L3XJsBdpWG&{pzm@d zhS93rf2(+6YXdN>&5T}bGR(~lWul3+DF!5G4&wV-}WF*|KVG(l^Si~=gQoY@$?kvN)0#Vn)v7ddT0Xid_0|2+U-wX zcAezh0a&feyDO0UEge-TrKMimH-0HsO`OB_yx6M1K2WDMNw(;K8nwOm2$JJsg)2s3 zipP}41(=$5E{w50=J1y5&|eh9F5uU;iBKAY)ZR`isTcKem0ga%$mPGFbLYgns@!%X zQ_yqv2@1*#WdmMcd4H-Fb2Wut_Q&y}-$pL^E zV|QU8n6|ogDfFiGl)S_CaNXBn^YTJjpN6DJu6pz0ESZN-v=nJ>xHM#YHtgK~gTnJZ z`~X#Z{`j4Rx9G#F<~_05qvjbhhy$TnJmTd*Wg%EprItkHHbCKUxc&-lXHkD$#HEE& zqJ5Ga7#QBQduFM(a9H|s7VlsUZKS<$UuYxvb<50lu>H1S_mlezhw9(Lc^2RQtv4?& z^`N`T!9NCS4mVNNB(`tAL{MI%GFmNRUYc(|>;z#;>KmVRi@0RUQT^0wy!HOE8;2@T z7cR1PeDr~C59kdMj>I1wh5Y8e&6g1}35)M%Z_w*WHnwA#s%o_^Zp6&ljO9Ex^PARx z-eLB8O$3FImelF_BJPy+l6}p)!u8S(!G}MS$W)!NK1@5+E(9I_DWS$zvmgkDCxB_Q z+p%9MD;;3re=CqW~A4K~spsabbE^Nbk57?Z_^=oNaKh`}Qz0hog* zE)A#Kpp&oyYb!PF;snZ~;R^U@kPXg{k6xSZLJjGX=g4vBT1h~EBxm0(aloD;Fl#qh zE_E!(#ahAhOXn8HEkX?76puO>qk#8l?5PPtDrD1TArt4a3aN@Ib@? jmrg&u?9i=_u`>#t&nr#x4HSA5tq<*5^dkB+2X!mVo zBu?P7+m@iOYEJ9Wl`v@1;qeKHMX|z|aLN{X-DR)=R=E?}Ce+G--m=jqyQY8~mdO&i zVDbrR^AsrFHnjn7krisd^?B@I%epPwiId)AkJ2d}T|R#7;;B3E20Q5RO+}S!@cdC@ z0{JRcW$x)wB^Yod`+WF2CC9PkR@2wH5EUN8%3ugf1L~c0i$ur`bo$Uw^LG zA@#*3INOf379|EwCUYL8A9qc7?GXsbYp$d{w7Dta7At@6^kumZh%& zogfC-5<2DJ~cs0I(6Exo^XT*tN)}1q*7lQyo zA$)bvq~9jZd_Q@xIhe6^f7~um(|_d~ zw_CU5Hy!_9NtRRTS#BFmWz;OX6#!S`1)p4Is_O+UgQ*)wX9VFkeBtjtP5fH_-zvx8 z&VESwjta>2@yq9J^1$wT{}f5U)n44?j;CL|oOfaKvJh4e4woC(Q!{L+TnaAP)dw?v zUA3>c!jL0J76js5iEoVJ6~EB9C=kqN_>kgR0e8S-Rc_Tixv+=B{J;^6nI;t);yj7d zz5{N{SlitTh^;#+Xo{+I_c*=6vU$2kq5%)e2?0)d$81i3ccUg_+w?vXy_0)1vBXZs z5T~(c8@4{j6F5#IVqpV3gU8BWtlN~bE|TgeT?zd{h-PcZ zQGeqe0LyJf8}0!lHKf@6+|#c|E{q;tndr>H-BVapovy|HY)Xp6#HnQ+r^w8UU*{b2 z7+tYNAzZ0IfdALFWB0>9$W|Jg!$FAva^?_x^Cg+dbm|hO0i)QM(>701=)p^DG){e4 z4RB`f&7QERFFzF9oF?|FTitfy!KRR6>pYH0&NA#rcwkK@TD~#VbH+m1i5Q}&vgSS7 zo|oe6vA7Vp)?g6=jmc&2Ny%)I3ihy6oSY*@nQk<{F5|``2eO{J+7=cJOs}TwpHDSM z7``?gZLHT+fI4mBln#87F*VjNT7DjoA9GhWyFsH;um@zR)|4d3qN3$sJi$B=E52DR zsVoQqe%~|0#x~+Jx$F`)fiHt63A{FjU%Ynf*R4}dm!`quN0YcdB8ex}_Sf{ihF{la z+DKnRe4Xtjh~@;FI9s#qP^2ohG#kA48*Ez`B6#H1+0dDn`g{#p&gr0WA0eB?Eq)a3 z(~lId#4kw&S<=A!J0jdIsH)7-HN|w86d2%OLpV489KV?_;}K*iXj>5?3~M^Ne#zI1 z;P4Ce6AbgO5eg$mTNgiH8iY|h)YlX8d7egAn0QTm$P zB@bBTpgxf!eBE0J`&~e4IGNUb`^33qQM(bL7_ zMP{#lr&W9s(jG*ItLYxJI!F)uk&^^QspXx{y@s|~ zzf48B)XHv{P4p{$Y|6m&!Yw)II}iWM11G%=wr()Y1Q?WY`g4jH0Kl5DWU>ev*)`U{ zpmUv6E)geYdni(4uXIR4EH{1{efA9pwLq3M!WQbepwn}~VM^5@!iYS#QuF_&lsSLQIDSjG@J?Trof4xt0D! z%4?nVDSOuO{ukY8_>_KmAD(t~PM_xblaKcHcmj_nG_RgyeU2mT@ES`UfCgRXcn3;>LlF;vAncS3EPfj&!!MQjy5)2cJ;xTj}rPZD>m(>5t) z4A^#J<8HjszbXV+z{M4(45Qu(zJCp=c+i~WKl%+HGn-_qi>T6>Y!1D+OlBxg0LyG$J7|2 zu}zQI2%6n=8scgXwITp(6GCRs=g8}1-dc~`#6$l&AM%FjA?s=rPjBi^y4y9x-_%?|erXKyh z!{eQ{wb9kq33D!41&&g$WY(S^7%1q&)NV4{9|bnSHs0`44H5G(_k^gE201OiFMES%b|%KuTaix8s!~Z z++NAU$@*_Mi*P<$%y#Q4O0@wFsTZpi`N>?no!9(s>;Il8Du|%|I;bvR=m_76NIMY9 z%@2{}yYQPV`)g)5B1}OjHv*>Nz_b?CdM!UpG8V`|;kRy>?Y6hJ9H+`s1+JvPF0TI) z;9iiM;9RUd7fp&}`Pn~&g?2jgh&gW7it%93trwmi{e$A=CDy;Q*aocRaQd6;R z{5aIM;vq}>8$N9gdkyFwtbKw#o(1-^W=0P^tamNp5XK~6o$|?5lF81LDE|T-E&u1P z8TUa`LW^uw{ouUF{LH3*Qoa$BrG9O51i zY$N>Wo)IG%-(5(*^3b0_)jS(^QCm;A{59uHV71RO**;smQQO;2dyq~YK^Z+Pl$ifrBYb=pMR#ZhxSey@N z;Jl6$Z#dvS&ZqahnmYBcN9#LEM}FR7gGBx0Z&r2n@2z&aUvH)7)Jr{afOisDcqGW_ z*$7nnTO`Q6dP)0e9>haccLb!u272V*pQk;yJ&`jw^<70rj5mH|OizS$Hr?pKZK*wS znW67Q``cBpsx3}s#)}1>8%3ajAb51f!3t+RPbh`ED4AuiI_YI0%QY!p2 zF1R@n&)M^a8hi|&!AG>4W7u!&>4M>dwRUGm1T%UT?VkvaeyYYoK>#AcSSO9LmtqW9 zCw%KhMDvo0FK1CV-8nzfwunMg2I>@Q!?3A^dob~mNEAR^kR)qWHXvv?_QQUh~7x?7%$YIzsPJqrg!6dZ?oD}05=eIF2 zK8j*`+8QPJoIxwDwDzSHV!CJ0*=rB*rP+c@iA*A!;#tg}Z(09o8+3NL*d0b(Ia-UW z@ElGOvI>jSi@BAqZu^Em_oV{ULsaz@r?;9K0qO*@&N%h8M;2TP`Z}udKYuA&AzxYib8_Z$JIY&&=F z!r)KOBFuTG@ug%1ig#Orj&<2n4pu$MbSEck8;rxIe{;bm6;;{7d3Hn+D-%XIlZqqXm*!eHbzr`+9^sK^tN069MfYWwUF0E6_zh> z4{s$oB^g7_YiT}jv!4m@JX+*B(|zSO*=d56@d8x{jTR`FqWHjn@cT_N)y4N~eE3F- zX7l$r%ObxhdtSk2=in7N01`i~Jdr;A6rNy{_3**%gq}q*IGiV}a=G=ok|c_bOML$$ zkWuAFKV20Ose#N@tCSIbWVZ*aRd9r1)o9jtpa@~NeRq|A%&YnX2c;ivJS}=1<dbFt>_X0Ep& zLD*Cf`}(e=8{k>w@#RYpDd1;~>b7jYYxd9VcH#Or$~;@CQObsq1wQhm1&{p-VUN|1 zegWphontv|FaJUAM)#KWss8aT8t`vJfzAnt7!+i;iWi(e>Z)Dhu35LX=$&3`eSOEm z7N~HiIx^YK6ck_IU)+AtsMav^Nn9jwF@{M-By_xf8&GSy@1(>X-MnNSkkDgS14~fu z(lP4xm|dTXs@qX2r^YjzK<`}5iD^7y>u_0_nyO@+tVt>R&^3KQhd+XvH!gFG`I3Eh_Cxyq|!quZ;b z;_dIivrY?B(!rMSF07HD6sHkzW(djH*rnYLiSUDDhb#8raOf&D3|&CfcXl) zPg-vNt2vu*4KrWVfR~HCDCqJ?9QnfVK)|9{0(hL~aCV@K;MIRo(GRSNJozZb;>C5} zjE_xe9u~@8IBLqa`a$AsOfD=UgmFp}74YZlW0Bx2np^P?dtStbt7mrShL4host^D= zS$F8_?)gYcoG1Q5ye_ggz&)bul1i4OIEL|t^Qw5v6Fhz0>In>kLYW?uzy8qo+r0E# z>DK!N3yefzF5eGdh%Y4j;h6B|`)P^M2W4aOIV;^;! zH>iKRX;!LF?BdyXeIpzi5}){IFf0p@SX5ZZR0la`L0#1V_s)aO<4?2)HU>m&L6XT-F*9(PbjM>|t*E3ldx(Nf-|u~$>$@VZEuO_PM0;!J%ca6JmELQG zy!d7q{j;m5#OkcR!t2XwX>?wXZ>mbm#29uLzUYcI$=z6BRSGR$99?|@fKVr?FV6Dh zoea5DYek+3Ww0DhTbkmvi1J~RvDk^9pGLbkZ1E8!I^3=V4Sz0z;Le0bn-5z_!`N$b zTKBtGx$>c*OEpHznfpG{rcr0dr2?tXnz%*GtIhS<-qHG&<54b3l6o0+{O+Tp`Dfc^ zR!7?|+t0cWh~>}payoemf$U`0gSr@7vhi*xTp8U%O~)yNd27q{a)!ADZF#JWy(v7 zdl&tA5zt%zaFsT<>B@=LrN%DvnC7>zK?$Q`i94g8&e*H3(u3Q6$rDG9ef=#DZz#QE zXjRFI5_HR6d|y-vq|q>&5z?Y8&?FZ8A!WJ0J*H+~usP!|W{0qoGF8-Ec`G!s+u~F? z5d|aT*ob*yYd2P_Kt4OTt66rNPc?GYjEDR!x0FUxW@q5eKnPE4qE=QmvcggN>rFvy}O}^*Jqy}DmR@2 zv4k?iI=z-yO7fSquj|LBrv&ufQyVO-4oo+mc+b^K+FP~{_p zgu1Wi{zr)2VCwY1c|zd)NQWTrkLyi8U+*iXEfH_*A&Xb4N{zP^`_IGNsm2I`ut(aF1!;9;{BEG)b1G1c)_R#C~_O66n zz&lxpKns^hUlf<6X-w>j0y#*Wl%+xJCn2_xS7QFXz$sULj$k1BugV+H%dx4C)UA#p zPnO|MLgmKlyRes8GUnWD(yh58e=fkaKf8Z3ti_1!2#BSJtc9^D#^bbkmz@i{{eSv! z*teRrBHo<*6xxrFSW4B;LvwoO0c(iCIE-W700YOgB;SoHzEc5ED*Gl2SWm)_LI)k)=5jW&%SsXIXjhgQ+muYht%qP_SN;Hn z@4ZYVME@Sfl95$SNy#;76%EjSd+>#b^QkZs4yuc6;$*7% zCrDqOFpK{fY{U-+?tjW0X#s6m_LI`h?3ab`R!SnuA<{Uroc7G*-rEnThV_uE*JqWD zs@ap*)dZkVQ8afDo7qEzfBxJ26=z*r1!0dv2Lqqp;{BhFjS*4CjHt{p@sGk^yE`^0 zYQ$#o{#XA`|1=?t(Z*<9%!C2@jy-jX|CuqEcyHmL!g3XKPf`Dx78nU=^J5LORg^RS z=Ei?}rzUKEo9ymLyL0Y;33IDa(erX#Gu!kKkJjHFQY=${iI|I%bGmPgN)`VvvA*Xi z5F?0%{8mv;|IbstNj2b3obBcwCH=qFa{+B3Eaaz3Yvg}gi^kQ##M#GOqox1l==aP7 z1h52|nGZG^|FxGSe207@J^aB&`#*{OUx`%T2OGWrBzGy2zZIfm$Jmi{`hRB>5P))g zfWtjp!c;D({-?N}{2nG%&FsSU-vB>VeEJ6$%S!C5=-mEKiYxzDx@SB$lK$eq71FfO z{D&3x&>S8~5BpDwGW%D$`6jkd>h6D|g;yBC|I)|&SdSGw=MIDaO}c=ofB*$xYf#XA z5{zo}7C8gg6v_Sn)AsIvuJE>s+7?j@ z)!;d^eCWf@qhygii#JcHZ1`>2h|Kev#IakaRQ$GTMCKwL;+Vi`SO&kXALZdO(W@B+ z{%{%91K@a`yuvxG{yw@=(Rx(&$v~FU(`r^N;@!a$=4;6~hj&M3yZOlbx+m0pNwC^g zIB>ZZNbS}V-q)wZ*~iP8pz$xKXR8q~x0|P7E&M#wC@?P{s>g;v77~P-8*4h+Hufwj zQ&C+q)qJF4^a0+A6OPB_GarI^8Byx`jAS8pDCUV~S8f5k^^-^pE+0&Ja}U+?bdIFY zvRmBM?r`rkwWZp!^)UMRH0W%N#pIGvKF6Ci8&{`hBwO*4KcI-gIJsba zucw4?5X;}40zzFxP*c$O-+&!GY}nZkO;ixMRW59N?f7VDG`pz`w2BG1#DmN+b(}+Q0c z{@@!8ZxbvA(GHuAqYM(wqGT&(42ry?_eNaVZ#8Iu0c4=O_|o|A?{q?56|E6 z{@!j_m{TaGd^UA-wit4zdro_Is>0i!h$&vj4OJ?On+MQ}yo{_>p_0|{84#Hb_sunm7ad?FEKxY(IQN<#Z*;dh z9*fWFPmIg>tz5+&kDARkiQu>ZJ+kxjn1j3H$xqqIdFXU!89`u-o=1`ewrTkHg~|<(iq< zGpR{hdxqILpPkZ%F`2M;uaz_m)vdn{u1q8rL_F%2qiwJy^i7|}0%>*G0$6@10J(E9#!_BCdK@@Vb{VlOnoy0u4=>!@_iICIaFAVbm-q`M-5&QQ#B;U zg)D>oH>u(gzS~FHFipjJlO%U|5{e`45^6)8n0$TSAX~TRx35usnze#WeK7VpAo^pX zZ7lJN)FBxO3;Wf-Np_)x&-R8?{lZ9d;9gLMU~Z3c&giQrecilF->;o$fg%+0c&Wez zmcpmnNMBv>n`+6+B=Tqa7Wkl%*$25)sdEq1xlcemp5e#ao97lBE$^^;s#Gley;aDv zWLP-l)q-T0RUuC3Nn$T0B>{f(4xu7(d`*wuj10YBP>lw|PvL{ot>(QQRAo~&?+ZjJ z6%fjOBq^tuNfSL{ni71H469hzy-n|luK6(XBZv9kmvfz=@PwbDe-!V`>uVYPyic~m zLZ32(-NcaEtJa;a-!YPgGsC~=bm~c=@WNQ#OH|#CgX&f?vfnQ8^8i$JeL}X|t|48` z`Y`{_Dhdz8gqFABiz=b8Zcoq?I1%V&qx!|6uOB9&$VZ0S@7{lTnxcv!sb~!_*-8C9 zNVHL@j@YTE?c!2OHNmeIMxPJ$I@6*xUE9-zfAw1k4fwR~B#-FzJ1|53XWjevc33_AEE z`2D@BlNLx7?I*_#0i;JsP9r)F#0%iL&Hzd2{Il%^iW&qm?;GD3bYg7BHGZD+X6_0m z9|G^j1f0@yXisIpI1a~O%vZ#HB1#%>Kp(tzpxT9fvIn|W3fu&sel2d)U;(ix93SG- z8_W%wW+rvZB-q0nuO9llxD~uEGjjI1d%qY%O43hK!~b-@TKuay+!|yt2iHQLRlbqX zB9+g`HmNhaAoVz?TpQW`_#kUz)ap24!>=9gZ(8!YKmi&*Do}@4)Lb>M9)DTLD%64& zpxv0Viv^4f;G0TpGJw#Y*N>6E_xzhrq}H*UicX$=a!M+sY>^z@)ufCc@_>k>kHCj7spCM zu9hr$SyW@Ftc%Jzw&F&64(kVIHupAkznGXoHp!R6?04mw2{AUlCx>D; z&0=sap4847K4z_|e^(+aqM=!nx_w9EZZiTlWNnGJstZni7D_AO5q%wbPSmM_LOhra z+W_@KSTX!pCoXj9YStGMiESb06k-YP#x~_7#+7Uck%#4Krh-cUi0>cu8ROEr`V2bL z#w-&Hsxk>$pn-rtH}6lv=$jXC@WoSUa%y*QdyK`vsOtRXwLi8ZOn>!Xo#ry7Q46<+v9|%s2)(Mjn8Azl7SG4r{ z)!r02Lf|;t>(3TX{S2^mFJapfnz%XMBzZ>UeZVUmr~2X3=Rf5~b7)$Zaer{TD1Ph{ zi+CQs0r~NYWv6ArJiXB`c9iS~54wae%a_rmjW6X(9nO_(387@m_V{{k`!o(-ESRZv zvtNUq`@5A+K#02xly6`#N12LkChmg)Jy!eUjY^Ehg>6^zP8gqB zhnwBv8tmq6odR~SGk@yjJ0r2xSd{6f@Uy-n*;Ln10}scNkn`$9ze;OdYsR}X=Y|~R zt3QX-yob>Mr6~>QjaO~4v&}-XWWmeQb!t5uOeX0zNI~19U~b>7p3Qxsy>Ir{W)pPj z4hzflzf#5GKfJ#jdWD1vc#?h#i-V@RrUV`^c6@ld7_JKF_yEx`NNWnw+zjm z@(1B)f*&$HZ-7-ny+fCmMxTePQw zxyt=#x~S_lGj3^S&Th0R=kA1c)IouP^3g=V|b-04`lvO%OhVr`2$Y(zD@YF-SvFkVMiwoUXq74B+gc9S%dfdSWx zBMNN@T*aP3^ad5Y{b4_%xdc0XNv^~$>>k&BS`~#GE|hW$(<8%GDhdwJh9Y@6JU@q9 z>p@~8Jkv8_nb{-7H?SNdy5j(`Zw_`%gI`?T3Y<5tVZvy?A`2~BBw4%!D z#_1fXt1n_hEn%d;igd@Va~^gPcw@PI>+6)JNl-$QzdMoO`(%Q)V$woWd+0sPYxg1D zyOH+!k=uc!`E&8%?_z0Q&XT%NuQwKa#k$UE4Qa@|C4)t*&Beb?rB^(rl69TIWXhG(9YwqRb z+t{&zc0sSz0wKRe`*OLp#}68#YwnW0{k(7aExuwjS9U58LGLPK2P&q-XI|g#pt24# z9xf-Uqsb{lg2`kUelH0B=Yq6GXPIKB@42Zc3!Msh z13l$~fgosTdHe9Qs*MLR3#GQJ8|+O}>A_iHVZ9Z?7{$4pWSP|YzBtt)uj}4#eDw-n zi_S)7!sz6S(0Su2K1@HCKu{z#19g>dF^y;JfK$^{Bl*49=o8=qtU}py!p^)%ZCS3< zx5knfRjx7lnwpOzw3q_xl=onqtKNUaZ%#eA&?cf#8_{XHxh#lnFApQUMtB^f@rNgI)X~@6mN?23^^f;pbjdFXdbg%tBu|}BUKNE!*Ppn_ zP=eTs!2gEfC9o=pJ+HTRLY02^0XtHjpKLO=_V(R1$Tx-xX-Z;nW$5ZhV*}Zf!u(wr zy9s2S`s`)RCN2Spe>0b}Q@#y(=gg7qmeu*W7UT)n zF)gJ^nN=q-Uq$0~*)wlsytA%E%*1(}>_1-X_|b^7-r!jUYe*w1pqf$plIItO$xr!e zjZ-UW=c4J8@Bd}$5b({P3*%h!yp_DACW%g2n=Q&%6#;QY?*}famDYa?kWVZ8JIWYR z+h=h=^P|Y{{fg33%11M^r@oNw_OsQbIG$8F=wQQ>?RDS{yRa&5x;EZt{-whIj3h($ diff --git a/tests/output/test_add_polyline_annotation_using_line_art_factory/output.pdf b/tests/output/test_add_polyline_annotation_using_line_art_factory/output.pdf index 4834179bd7e71c8cb480c8e2b012fe735f5e22ef..0ea605297bc10cc71c9154f2b4387acb8d1172ff 100644 GIT binary patch delta 984 zcmaE`k@3Ms#toH>^`g=?dgo$GANonTratVyq<1WTzZh4pafE=a&Vi>dF9*&0K7IS% z2IIo6<&HIV46D9~#^gVmHfzU{O~MD{GCw3I6uCt`l~O2P61z}%V`8pWWYr_#m$?rw z*~S!eZM=Ub*Hb+$WS3K@ez+eL8t0NE-BrbJ#Xf@ zCF#pA&*2JX4cw)>`Q#RT+c##HFaLXAuV)jqJ4k$qR1naCV^TX`wR@A(yEU&-z{><_|^P_xj$p_DMqb}#4&F-`7!3XDK z?Kk=EzIwjsU&Fia2Q9nv3#YU(`d;n{mP^h2aCXrbi79#Knwjr@)Y;FwDO%uFNo7mU zboX@5^clXFd7JCIBu<=bjFs#9J%zFLY!>hJj`&q*WHQPLO5DePJlWEmXZg zxRB=)L!*Vmf_|~tUk-m}J{!f8xtWvMnu*iWz{JSN$kf<;as!X;&&NS|a2$9VVJSL0?F4!@@c)ufw z01eq}&fkKp2x!V?MnNT3BvlO_j+=AE{<9$q@i=bYCY#KKBm^=mUL$}XNeE=tS93pP zA&}QP-QOV;ZEo-gL$ZJKea}o}ZlL!;f3kgw+X06QaUTL1t6 delta 984 zcmaE`k@3Ms#toH>^@0-Cdgo$GANonHJ#|RFRqt5-elf0GV}lbmIt=a0{k<#i#osGp z%TAjb-u>ebL&$4xi+^WUZh2m@buPoVy<+xlPG>k)M={@H(wzRfCI7~ZpfI_5*9vKi z@BG*2HN8)_mVNo7$0vN1RmYXsnXhNP<6ChtdO=y$sr;X6Wm8Uce=#W}*DF&%*2mv}`DNqFnto2Ej!WL1 zT4Q|o0LzxwIX(B7k}DQZ_>-_^&iV;jIyYViAG2ziJ@?02H@%>@N#?&*=Ki+Pv1lw99 zkw9E#p8JnaGK(3uI0U*BK;TAaka1KSYRZZs0LtL~y~5`NjJkNd#!f zW^?`)WJN$zHZuw;u_CEz@NnFmEB2oaS%}AR^ETOJE+iq4S@9YH{76C|v%Z@9Aq#=L z*6IEZp=fi1M;Ma*o9}yOB69=17b0;%Uf68mI}1%{vV{Ltgo%^yd)iGl3AlqK0t%Y2 zz`IByAa_&-p^0ps6P(S+4voFZe4!FB_GaDCQ06!TQv(CT#6+_c!$e~P3v;8?lq3@i ti=<>AFf=r=G_zB%A*dvl%g&CgxFoTtq@pM_jmyZ;!q}2aRn^ts4FJ3JXm
je z);p~_+R__7biE0r~rDpgpx|O>2$ARX^lb0Ur9;|Ng{r;%0KK$VG-pRsOKl+5; z^?S>`^2^Fu-^;6t8+ofHzp&VQ%l^~s!l2!2yo07jo)o*d`K9UV>`U3<;l;OB)+$c5 z3oV}fa_5&vPk;*R|IWUA^Tz|Wy~_hHe=bn{{Ld0)nYy;4>!(%k zw%Gab;iDCQ^RD;*fBEZU&A(&6`_-l|{+VjiwV3h9$I>}5{*U^PJihx#;QX!!5erKH z_Be0QJ`Uz}1 zbE5WkU+pIlQYatPgVe=mzk>P^NAdm|n;crIb=F-S^v*~qpxB_rCrMgMO~@zs?Z zBmSopJ~k{*ZHd!3-5|}oSS#As{^6NPdIhiatpD&E_C!hWEq?jLA+hLc>!I@807lVk z+8(9Lcq57wM0PQH%#EJHH`jcQl-3EaQ}y8uk{_2Gonp=~X}j0*Ir^a=(oU%^ol@mD zr+h-Ex}DsGuRSsSH4hvxI;Mc4igvO>PIrKjJEL1tp4xYpt;9c;qgy< zjnBT8_2&BzJ&^h=!rMN#H+}BUCP(G}f^+g5vISMjPyY=*sQ7KKi%hB0o-f)$e4hlI zG+G`unmg~f>!l;}>w?LT&g(&3Q}+1%Y6^OIh|e!C(PZf#zDM%}e=$9tW~c3P!fOBW z=_;NMU1GfFzfJnMLO6NpW&vBlTZ|tM=db?v^6Jd@%k5V&UpTUTvkwaglZK^%iII_! zsflrvfq|xizHfetOJYf?f`*Hgk%5t+0bF`=4O=v$`Q#gHYD^ZElh~~TEffquKp~Hp z3(PPuG&D896tgtM5Hqqg!VohtG@0DPZXKIsX=<5lo|=}JW@=)XXl`U-24t8Sr5UFf lTc#OUnA$1W5L6P&1W|oFrs;aL3ZUEv%zfAxD delta 1023 zcmZ21utZ>kA7j0#ogG(kNl|KIE?32^yHigW-Et6c{r;~jPAybq+L6;0)2F=6*|Z@z z<*ih|)Qc%@%Fhxf@Au~y^3ZbjQj4=_Iy={zzltw>Ew9VrjPI68bv4Zu>*EuQfQv6EJv@!Hlg&v$)f?BuxJyJlVXd&|A@ z%gR}^eaw<_tYEh?^&leS)-F(pm&}7;@5?LCRXf;mYEbO zF2lWL-TcBAW%b9u*NbHS$}kX}lsYe4UFPMU=?gm^``I$BH3_LP;d(#4H%~$=dy@cD zJ<}zH?Y`Vh@ABV0XuTul!ncC!`|jxt%XF+6c8P1t7<8I62)eE5(YUr?I#2HFwhv3^ z=d80b6?;8jC(q{Dx}FQ%sgebY6GKv0zf_-da|!pHU8ni}JM#o`A5JupmDlK5zboL! zI$o^>hpJdtp4-Cc&DY{&&akq$`_jVCZNbj0k)HKGxeS!&ZJF_j&EZqn%PF6ia^3UU zxnxSv`OeRLMjwwHXWkXZBv;C`r@3pv5iM~Aqgxe*E%W&d)Q^TZ1`3?F5y@hZKL6J4 z`ZdYA-O7m|o|4 z$WhLTqt(FXLmJ2S=+0JW`B`lCAEUe)Ctdf9573Iaaqy&W&$21^9q$-B#V6dkl-|k_ z`TYBrNh+Kk7Z*Le8E4dIWf*3~eNlL!tbqNWZLj9X&HY*Ti<#w`!I52?y;(SzG%SoP z4UCPAO^l)p3^Wz=ee+XX5=&AQG+eBV42%p7;L?+;*`gUOCSPY$W3n`u{GZJ_&{Dww z1QhakxxfqqLqk(TOfgF%3^5~1V+=79L(|FK?AEbnrY1(I#s=o*sU}H@=1JzpCTS^# r7AXeFM&_0lCI+c?3N{3l#BzbNcVbaVMNw)Rm!X-Z5tpi}tG^onPN%Rz diff --git a/tests/output/test_add_redact_annotation/output_002.pdf b/tests/output/test_add_redact_annotation/output_002.pdf index f5f9a64855304fe960272e917f351f5de17275cb..9d2c969e6d117812c6420bfd7c68dc581a1f9fd6 100644 GIT binary patch delta 895 zcmV-_1AzSY6ZR9ZYXN`Da@s%;Mfd)SUM5u(M&cpkT~fBQ$-+*NwQD?Tpi>%+n1@aN zK0QbvsSGKZc;N^(ckVpsIb5|iFdB|_pCjVOH;DH71*Y@iwA9Ho+1m=@d2+CFW;=uM*I z^lJaeZ^qNwWnGf0%u2S1o=vY=U6WqBx|-8Y?F*^&shXQi&!rbnkJGFD*S|SS#s@d( z9jU!p$rjPG={2is(rZ^&a|-HENTpBJ++_Ly7tr`@TBEOv*6=SEF{{?f%e$z)*kak7 zYORan!%6(DN3(yZj?4IPjyieHryJq$Gc10!+}p*;4G$Mb?RUF={7=`9=kqt-e>Axq z%`f9o91S3jt|!TLJpM>L-YpJs(gnu?t?OqTy4~OL{U1e|J{nAgWSQsM2}e5bWhkPk zQ;$F^4HX}a!uw^T8-~T2EQEl7G{|k!f`I#*J9r_t29bXQs>1#5C7>D04uI~(3I|Lg z4Pb;3De&C!4EIjm7#WiyM!*D!tz>))@&<#N9+@f^oyy4VPK~_?}0?ddfEvCEy zki1no<$Qmsf;UqxDW%kN;=F@QJn`{>u9twvodEBkA}F!S1&E9`UJT)<1I$S=RZtYf zGY^Ftz{YdC&$V^Nr+`~DlFE#N&oZH;E}4c!WGOJ-9Z5wm3CEoX;}%eGSQY0`m!W0I z-1~0=OyL~@8PESgnQzLu`4tA&n5Sqs>})*i%ol$Q8u^dlbOTz8Ah}!ap9&7K? z6XK;`k#LZQ5JDjg54;(|?N(yp(1)hMPrQ~=pyYMZ7nBMYc5reFqbcQg5ciDG7Z|tn zSs_B!`8~ZPNdi)|Xn3}lj7OaqE1iYtiO>#+AAVc)Pp{5=Km7s6e8jm5Wo~41baG{3 zZ3?qx1eE~^IWRObGBPzYII{x=(*X!MFf=kTG&eGn-Uk;6IWRObGBPzYIJ5o-n*l>) zWHUBnVrDWqF*Rd0VKFy0I5IaiHeoS1V`E}5I5#&wAUtL=H(@bjHDWO}WHMnkWnwcj VWH~ovI5%WwHa9sjVKbB52^v(Jafpk7jD?LkRds{&=pB?dYuwf=x z)f$*hrdUENOY3#otgshan9dUb&~Yt!pi*KpdYeId0zRdbu^x%86sIK9UI^Ea<%lY<-d zj?~_)Wryh5^xD<6>2<4XI0bbmq}HcuZZmy^3ut{dozdq-XZV+km{n)x<$c^-Y_V)l zb=Jkn;UxYxqpN?oiOb}0jyieHhg;$BBP@P)+`Gle4UZQ`?KiuA@=w=K=JQwHKbc=f z*Oy6@#3P8}n@Mz&Chv*Io5dlS^}(?~>xLPJe)o5L{~sdDei+PzWLXs22}imZWGLde zSC2p|4VCYW!rNt|ABM%6EQEl7G{|k!f`EtHdw3zY22p!^dI8=+MNnc@2oO1KycolG2Uw6|s-P%{ zXC4YQf{o{PUuf%$&j7b*Bvly&pXWkJT`>)d$WmauJCe#l5>9#%#x0=Wuqw`>u0qR@ zx%b}&n8G^*GM@i~D&JIa^D7OmvB=PH*x7j2xi5biH1Z$8=?1hGL2|d;KNTEeKS;!J zFT_i~BH^G2A%s#G9(Xf`yRF31p$|=ipLi{$K*{T*FDVl)?BL{#+AAVc+Pp{5=Km7))BgD4~Wo~41baG{3 zZ3?qx1eE~^I5IgfGcz+YH?so<(*X!LGC43YGcYxi-Uk;6I5IgfGcz+YH?#f+n*l>O zWi?|qVK6l~HZ(P6Ha9mpGGsVqIW{&jGG#O|Vlpy5AUrfMW-&HoWMpGDIXE_CGcsj4 VG-GBlV>B>0I5}lBGdPpn2^xh*qrLzD diff --git a/tests/output/test_add_redact_annotation/output_003.pdf b/tests/output/test_add_redact_annotation/output_003.pdf index ab9839e15f774490f38df033aee353eea8c65931..e3f41c07121a42acc775f06e44e4814cded02057 100644 GIT binary patch delta 114 zcmezQl;!7BmWC~ik2KgV4NQ!Tj7+z`)L;x{gz=^WdB)Q#v=~#7MU1wKX)|)d6>V43 uVVuFHkZfU`nr57qm||g`W@2GtnwFAcY-E;dVxDGTY?_p2H2t0tqci~DqagJF delta 114 zcmezQl;!7BmWC~ik2KgVj4Ta|jg7az)L;x{gz=^WdB)Q#v=~#7MU1wKX)|)d6>V43 tVVuFHkZ7K2oMf47VU}cOWMY|`YHpBbW?-0Vl$4Zc4CEV3zh}fK4FKGKAjJRx diff --git a/tests/output/test_add_redact_annotation/output_004.pdf b/tests/output/test_add_redact_annotation/output_004.pdf index 9ad31b2005848cf1ffe001d872de6875b14207e7..83f7a7b6d52c160c35dfb76f074e6d75bea470ef 100644 GIT binary patch delta 125 zcmaEo_9ShCv!RBifr*ikk*SGMl!1Y!g1&Elic4Zis)B}#m63swp#fZabGG4ZMrTta s(?p{*6Vo(PLsK&&3p3;7WOE~nRKsKo69dE4v{X9<8$wDZdm2jv0E(v}!~g&Q delta 125 zcmaEo_9ShCv!RBCk)?sLv9XC^l!1Y!g1&Elic4Zis)B}#m63swp#fZabGG4ZMrX5R qV~bQ{3p2Asb0Z)t)i^mZ#n8aaEH%j@B{kLD+)lxUkdn!s#?k=25hDZu diff --git a/tests/output/test_add_redact_annotation/output_005.pdf b/tests/output/test_add_redact_annotation/output_005.pdf index d4e44179fe288415a64aee83149284b90f8e403e..52b7b9afee015f2efbb60b7818d95dd59b313a18 100644 GIT binary patch delta 159 zcmXxaF$%&k6aY}FgOXEpsp#a-&rh0&WU6lBE+{1A|DlUeJ9sR?vv`4?L>wF+ys4l1 zSEUyL2oddjsXx`~2Td)S3&5t{p6;bfBiHM0hkzRXcW$cL4SXi!9Z6!yki`}P&lXbQ vkkDeR_ud(4rOoUpiA_WgOXEpsp#a(dwESGlBv3hyHFv`YlbdD?clKl&*BAo5_NF=;e&tb zr~aAgMTHKC=(W`EZ1oFGz<2@JM(Zsy51q6hQFOtHoID5IhGPiAz`#8nbyW& xTA{=)M(guEqeGogs1(P<1{?w#3P2VESH?HWdvzbfFg}JZsqfm6DvHDT_yIr|DP8~o diff --git a/tests/output/test_add_remote_go_to_annotation/output_001.pdf b/tests/output/test_add_remote_go_to_annotation/output_001.pdf index d19f3e8c25a0e72955e0ea62d98874f2718f2eb7..2784b33b03da5878caa9867f2c0883c09d6c602b 100644 GIT binary patch delta 753 zcmdlZuv=h53?rl2e@~^~<`GL#F@ALR_V%YA z=BcwkV(nQuF`oC)U*3SF>mA-`YHo2|bE=Qwc3AU&&dhC-BacdM@KK3fs2sS#%saB; z(X=zS4=%0V@l0gVy*XQ!2wSJ_iV1b}x;t&>tC!CjxNL<@FHf#JY-~7j-38W_^_O&( zx@|GHHJ$6_@2_t8bQM?7t8HhrF7Nwdkhx6#@BH&IH^SbgS*eH4TzaMB+p^`$f?vLT zsj}SXD#*ad)LqSj8rNN;_gdWgG~I2IgSF*tg_|>qL$+@z=D0rfi2ph2e) z>A{B=rr1BTD0w}<`(Nz&?{{0=dVs#xM_h0{v~)C}J|{ZJwH)t=|_8x#BLX>ZQ|E38TgwCA}$(NzE2W*O$WjGUGR zCPqd^rY6Rl53%GiYQVWs1_qi6`o8%oE{P?n3K}j}Mg~TP25{-g5p2vm WEGnreN=@T3G&42jQdM>JcLM-gIv()= delta 749 zcmdljut#7+3?rlY)2$fobz&d?v8}ikuJCQnlv_$+xyKuFS0DY~qI3V`+D|+YY(je14fSu#n5tu2 z=l$;OgG=@?)m(A@>as6?_)T3GP&&b@Jat|5F3SZj=N;aDX}SN&$EW3VspqPCBkh#} zvOfNP>X(BrbNaQeY7W_@z4=UuhON)7mz@8f8~fhQx)US5Bx~~|u8Rl1JSj15e6{+IBPt%I{9xfC5-#NAO$c`7jb9Zb$ zcllQGL1PQ~uHUap?roU8<<{b@{r|7nZF^fU{rmVgr)a$mZ5KsMYL~v&X1*`nfAJV& zbZvo!<1x8nnO|SeSNvc1{CA$zktwWs9O+4zn_SLy=^buwSmKx*YtrKRIZr&<#J*syI9ssaq2~#wwr7Z4 zl3e^jUoBs7o5`k_qC|nSaee*AbN(etxUK(r^Kwc3xBkz}z3quV*p^o6|J*FiJeQHv z!pPFV*x1;_X!AjqJVp&TH_E_3Q$gQ1KgA`nBvnDf#mdOQ$j|^TJvp2$n$c+TW;S(3 zlgYQ)tc6V#3_w63kCzL~FfcTj9LO$QZ((ANE@NO}VTmDTX=#WqW@u<=j3H)ZVSpiK zY>s4JNl{{EPHGXCjg5X#e*Wa$?8?pt$w`Uk$!Ug3#)+xMAa9r@8JZ;~8yF=enxt7I Xrr0Ui5K=N(kwci>j7wG3)!z*O=1Cw8 diff --git a/tests/output/test_add_remote_go_to_annotation/output_002.pdf b/tests/output/test_add_remote_go_to_annotation/output_002.pdf index b3098e7674d17a7bacc30a8785b918f3749945a4..771335fe5e26c3bb28a943afaaf823104b128a2e 100644 GIT binary patch delta 624 zcmew<@KazzC1d^6PaD1Ge!eF8j`Q{|UfI`dy~pbFf96OZJg{vBYgw^{gXQy+)(;q# zB|eL8uBc`Vd8w~3&ynk`!17JW2j*RVkgs^QFD0yy&q8d{x(gd4Hkf%wRy>+?X7<5_ z)jOVvB<*FtG|5j!^YYVGTtTn4oe5ojk5RNrENhwi-?r)`rPzhsLG?=`y?S3<{Bos4 z%hq=8lPRmUJXYQ|TJ6)nwB6I#_T~S5%imgVo&9o7Nb0m8<2zC3+4?Kaw<bUd&mYEvu6*M#4#oTjzMvw06NfmQ)Wj0)9ZTAnh zJ5%`L+WhW+jyq!5IC~|RADqQHhxK9J@ro15+oYdlC|r5z>3G>y=&gS5p`U6?q}l3) zmrm&A)DhB>o2S|G!D{BA@FV5|?;4I(|FiXQ*fv3yVQ*V@mAZ!x>x@V7CHvF9&q+R* z`mfvXu(Ex3&hpE@pJhtx+O=K2uiEzXq1@j@=gEw<1qzC>tIsnqq%*JT&t-o4*ZTVZ zo=Y$6?F~013tbmIq_ph$y!i}&#|7X|c zNaneW?3M;5Mn*=aoBy&DFsea0CMHn^2AT@`zWFIGi6yBD8ZK5w21bSkFtwA}IvJge t%ni&fjZ@7nEzOe?Q_T}iQ!NbBk}MNVO^wV_lMGVr6l@46nHI8^kjKZa@!Y18UFLwv znWSt%egB56znn+RJyym(x>m+?qdfYLZpzPzceKtkUU$1BY9+{RmZs|MA2X@C*y0QS z^?6Qf(kJ$nJo1>jE}(RRS9$6>YhJz;7d8i4+rHd>M_BkJSL~!!^=G`YT>6(SUl#oG z6Sv$pl>0d2t(&D3$JeT$3po>y{VrZyu#59$yW))_ zl24MEx~Futr?Uy#oR@oO{7kx|%we+ae<@W3_Y-mr^A?-#6;zqV0tH3e>JtnM>B_76Wtm0)R$u?$ zvH6F+z2Syzq4UCr)Rw)UJCDJzU8o}UXZfw8gi=D#cjjA~GhiAj`!fu@4KZ+?nPVo9okhKrSvfsvsBOzmX0PDZCR t!!$!nQ!^72Gt)%VL<@ry%amlJWOI{L<1{04)1*{81seiNCdY9|0|1N?7?}V7 diff --git a/tests/output/test_add_square_annotation/output.pdf b/tests/output/test_add_square_annotation/output.pdf index 1b397db07aefda333ee2831452670f4048bc12d0..0eb010793a5740a8631c34f5623d1a61ac9c4346 100644 GIT binary patch delta 700 zcmX@cf0Tbi3?rk-CbTU=emt5h1FHuvS$F9sVg2miZY{wwjq&Z+A>w=SE)c5(H~moH1I(yWfI z42l(4`P=BVkGTQk+f%()y;F4lXD+!Rtv**YsMl5g*R(>uhwCQoxO&PxE9P13+%4PB zU7l3*jpyR>hx^?2^5>|9Rd4zB(f93RgFPGS>#rBzxo}X=E%-o12OlB%HLVr67tWM}}F zp8Sn9n$dW25Su!q>EtRl>v|&v0}xQimJ$y>ea)_{ zc|V<<(?WRp4xLAjWdoM#JN)6)-0HsPR3F3dc}M@Z>D)iL_7hKq@sgN@%7Giqmg?Ak z^mv!6kSTv|p3{|LPiL!*%9lk~aVeDsKU=kYHgndOv=e^*Kc|%^Es9y_9dxOF$|Z$c zGw03oTb{lwcn()6>%?7}o6l|0w)J`QWy=5mbBph^&L2{DWmx;Nv6r=TFGFyheZl+hpV{{v zXAtB{&D;EiX%-`=g^{I!v9Ym<>E`JyW{eteZj^z6rh>k2eu_(CNveW|i8Sl0mX%s)0cYkYR3Vnqr=4XqsYVXl{^ZoMe=iW~X37P)RJ8 bogG(kNn%k+MNw)Rm!YYt1(&L-tG^on(8C7r diff --git a/tests/output/test_add_square_annotation_in_free_space/output_001.pdf b/tests/output/test_add_square_annotation_in_free_space/output_001.pdf index 064ee88e049e628af719ac1c0def0a97a16b9eb9..eaf30947a2424147bbd3cc74e5299701a21fc7c1 100644 GIT binary patch delta 26493 zcmZYHaa_$;{KxUfr8`1a2wAm4n@p5MA+*VaD0N2^U4%>&8kww%Mkd^muMirI5H%Vh zlW7w|Xk@}gBV;ZbA%5p~e!qwBIq%P(d!E<#d*8mha?P}(q|J_!Hc1CGPewQLaqrQ+ zdv`CzG+r}O2?*1GydtuD3^w6oQLMsIjuDv|AvYn4^Ek~YaZiYHk;vllaO8Q&7$mNt%j{M>NW9B5S6}jrwSU z7qGdtUklHh%Z}+NVKFF8XP^`knK=_1=U9|WM3UpM=`{Z-aM4f39^JLl?n2FLX}nXQT)C|c?Pok{rj3t2~|cV;surqQH~Ia z`3{?plLRpt*qzIWEH=oEI)z_wZ;^Z)s-!PQ8M*|ep2)srZ1mrwv|K7k+)|A?h5bXQ zGIyDL9ICjcp!`iFbvZWue?T!4*|tJxG^seH(MsXi_#+!vK;-LH*f^|4IZwo3#K!YS zS=6V(UszcqABQRdYf)Z{!r$zB(&RUCh%#;+inW4rLJ{uF?=yQnHZJKXSBRu+z^2be zlo}#iHenN-fzog@NDA2w}rQA$KH6tG|JzReRFE^fb| z+$3V$kIfecP-=9xkEb61-Qw|ji z$Nb;_v_CXq;^PZZ9R5VPKxFYLY%Z>VI_$}^VkdH%^jb$jqFQRBJp&Sr}KjO)k@rPtrj&hdBcYg^@=Dmg^6^|>L zG4KCXak)!Gxr)t@3Y7W^%~<(9dDl>){zkF8j#5g*P>GG#4U}pk88@*BzJ;PSp%f5_ zxs8qU9h7n+DR;5)twJ#q$@&MIuzM(0_fd+7#8+eE`T(Vpi18sd{*O@Vh~(5@qkoKI z`!7lfk;Et1c$iVDh@?NoCh!@G<~d3}k?2}%9R5QoBa-|A8=sdbHAFJ&u+hCjv3!kE zNF?qJHZJuj6+}|sV&nG?r4}VEy8-;FV{8JQP&Cdc z`9z}IW8=^PrHn{&M{ImtP-=)|eu9neQxwZiD1}7gT(NQKj8Z`)^)qbzx}ek&$#%mg zqAQ9`H9!eEXxAiDV7HCd?1T>T{GLBJp2f<2n$fl8DhC8~;HlbwqN$ z#6~|D#Wnz?gh=8LY&?ddR1rxZhD~4~ie@-UK9T4V*f<2Clo3e|#>QtPN)3_B5Nvdz zD3&^uLLzZrVdF9irGiN6Xl(q#P-=-}kHIElEQ(DyN->dy2yEQOp_quIjmIV+5~ZF< zo*tX12`F|GQA&vzCSl_hg;GrO@Tk(@c$=;Kjrzd

k~kL|k9jCnMA8$m37n6j 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 delta 26493 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 delta 77 zcmdn`kY(#bmWC~iCpFkDj4Ta|jg7Zo&|r*ag!7EF7(Lh&3{#VgOwALG&C-&L5=~PL a6H`(QQjINBlGDr*4GdCKr_VBAlm-B)$QJ4V diff --git a/tests/output/test_add_squiggle_annotation/output_001.pdf b/tests/output/test_add_squiggle_annotation/output_001.pdf index 9b08645e09e2f2a5a597580ae4ec0af325d536eb..6446060cc7d528297610fbceb243f5d9d22d1827 100644 GIT binary patch delta 854 zcmV-c1F8I`5T+2YYXN`!L7ZEwB)#;IRPH(2EMq(s3wS@0^xt>ZfC1I6h?_$SzPvm8 z!OY`#haCjdVE-Hu-@iiG=x120ri)6)i?|6Zh*t5Dcm~GL_)xV5;(6FcSt~y95Ugbt z<1IdR54+*X9nXT#n=MXc$1`r**5HN85)4!wDJoL+w$Kl09K(MDNUr0QTT zdqmHs*Uhd=ub*AZX|I|@YJDo_F4J@AMT_I~+W4RET*k9Q)ayN|CRocJ(X;7wv+L69 zXV-G_>X1mSPvzWYdJi9<^Xz(~FYDg$FNNr|xANjPYztd&x>LP%VRSf&f9+@)wsx5v z&QT}N`FJfXeu97X&tCLqeR9M7hoj*)D?j?D@}t%2mGuYni(qvT1yMMGD7uQ4S3&%q zc)Xb%qId|7H5xlkI}EGea{Uh?NgmA3QJQA>Ao9Gh!cvis(iUMjs7s)cn#%V^;qBZp z48wX$2E0W;YUIXgK)~JgEj*Lmg2(|?X@89p(30f=Ztalg;Iz)?(bF!JWh0Ru+1uECX&ejH+oiQvM1ymZRAStp!gCPq-p`Cy%a)Z*Mb((!cB^gP13YZa38ccWtAUUIogdL_z-b}fq zgc8S|a~6Lx@yN#m+ED_Y4FbG}il9WA3lJIYoS4E73z(B)s-Vb=Cmsql0lt?8^1@i{ z62KSKk}8ja%QB&4Q8D$4$dG5eKa$E(5{?ED#uq@rW>xINqB1Q*=I(#(VG3svNIU)y zDt}WB8cU5^%oEgXb`CrhnJXDI@*lzO1~djia=&P7ZUvjzjS_J<2=T_HBrN3Kgis32 z1E;5O^CGdd=zP=Q8(&B%Q1UwIN=k(FJJ`9UE-2xz5cdq<7Z|s6St-2N`AfYaNdgiy zsCjmjjDtapRgrn?3EvKgFTbh#r&DKspMC?S*T$8zP6P-72RSe_GBPqYlU)WF2RSe_ zGBPqYvwQ|k0YhPAH#j+CVKy@`WiU23W-&4_VK6i_H)S?vHaTT7V`V-dJYi%vI5}fs gHZw3~Fg7=4F)}b=Ff=qbWj1CuIb||qWs?jD8jbvme*gdg delta 854 zcmV-c1F8I`5T+2YYXN_3hd8%ZNqXrasoZn4S;lxO7Vv%~?!WJ>0RyUC5jTeve0g{F zgPF(g4qFJO!TvcSzJGvR#&a>@}zN~t~zZ9a=-pY%+uq|x0?oRdAh0)<8{~8&c_>J@e_Zne)gibtCJfZJ{%3dS^3dFl^-paudF{>UIbScQ4oa_2xix_`E?M# zCmwHRhbSI`V}-_!(+Z3&Bp!^=BGsbYK(S_M zJ3EEX<79I+sI?gPWN_;+x0QunD9eCb4WnwB%{cMIiy?U0K0EynF$6sfhtcKyKw*A0 zgu=H%qXH_8Q;-x{p}~*^q0ml17P&!b(K^k(p^}WGJO#{%Ck-aN0g#+gMZykKC2yu& zQbLJi&pCe!nRw#k0qrOO&jtbBLq$*`%>{^zwoXjphXu?@F;!6H#WN3ungHKR19@Sr zb_w7PwWP|U;Id38SyW8@A~NI|?~kN%l!T)}gmDKb*sO|uSX8EE$lU#JJWSy%0%^zp zLFI4CL1U?LgL#6Q&CY@6B6B5!M*bt%-GIg*NbYEt&8=V)yHO$z2O(a&l!S%cn-EH& zdEoREZg&z(i_SLVgvf3USZyeSvXHmzBbMoxjv;k|ZEO zgPLbY$v7CqSQVMKp78B}`0|^&e>!#M_vts^n#P&4P6P-72RJf0Ff%hWlU)WF2RJf0 zFf%hWvwQ|k0YfliHeoS2W@0ciHZo*6VlZVlH#0RdIbvfuGBILgF*ZIRJTPK5VKF&o gVlXo{GGsYoFl9G4Gc__fVq-ZnF=AvfHj@kp8e`axNdN!< diff --git a/tests/output/test_add_squiggle_annotation/output_002.pdf b/tests/output/test_add_squiggle_annotation/output_002.pdf index f2c805478a47014bdbdc5eaef6ebc81b67caa214..4f2e12c4d9c7a9ffc0444f6da7ca27ce6510ad61 100644 GIT binary patch delta 931 zcmV;U16=&y6yFrEZ2^CqKoExS{S|X;CCf3`ggCcWNqXrasoZn4S;lxO7Vv%~?!WJ> z0RyUC5jTeve0g{FgPF(g4qKQ_XZz=f`2H1wM!!I`oJN(7qqqqx2$%7Zcm~GL_)xV5 z;ziI#St~y95Ugbt<1Ie+0Ndfo9nXT#n@1u1+;+N&m!TA#|f%k*4&VRW2c8~^j2m+|}%^?FaL z3D&Yl^lWotlFuGhEC@ijqQ2178R6wP13X&o#G#IiV6xs>MA~z^4TBq4JRFaXDr+^vpq``zY z0FpDRNZ5a2s^ra-OG+ql>^Wy46Hk0RpdBUP`5?f1s0d1=xd4&T)`=2uFi%jk**WlBWUhZ?(8zxTyBp9L1j+rfxfN_;H%i38 zAjE5zlCY3_6GAC851gLD?M`B8(fOvqH@=WkpyYMZm6QnUcd&CyT~NYbA?_KzFEDQD zvQl`j^Ot%}k_04ZQ1k348P5hWRz>EmCww~~zWk={pH7|mefkY1|HhsQWo~41baG{3 zZ3?qz1eE~?IWRObGBP%^0|q<-COI%PGBGqbFfdv$FexA}O>bmGVRU66C`39kFfuVP zIWRObGBP%^WeA-CT`@K^H#B5pWHU2lWo9-uGGR1hVl-hhVrF7xIALL9IX)mfWMMQl zVK`!9Heob2Ibu0tG-NS1I5RakW@I#GG-5enK3xhvJ_>VmVRCeMa%E-;GBG$a3MC~) FPe$R>tOx)A delta 931 zcmV;U16=&y6yFrEZ2^DUKoExS{S|X;B}A}+5OQmkq?aC&ik_p*dN5OYy=FfW`tLi7 zZEUMhIW&jV=JM|Bhi4w%9dBVWp6s6^;`>*KYW)K9<#=A|#e7kR6~xQMk$46+%!E+6 z1{SlZiLzFF;2~JaGR9j%>;bm@lRKUTpEsSK$c|^K?Dncoq|$$kFjW9~`|y-=0`w;D!OH=AMNS;>(n7ASGd=;_p^;R26nvHmC3VR(EFw#R@%~6E21z*XMHqL0g3YSfhq^Q^ zL+0*(6JQGO5XgA`4@!Si4h9Q@8_W|lY<3Pj>&$-_3>x{5V0Qyriy*mQ*0+L9><5WB z>VvC>(vo(S!L`10GTe|mN1_vtsn*v6L%Wo~41baG{3 zZ3?qz1eE~?I5IgfGcz=^0|q<-CO9%VFflVRF*#Z=FexA}O>bmGVRU66C`39kFfuVP zI5IgfGcz=^WeA-CU14QmV>vlDI5K81Fl96{V>U51VKg{5VP-NpG&MLgF+LzXWHnVmVRCeMa%E-;GBG$a3MC~) FPey~Ost*7F diff --git a/tests/output/test_add_strikeout_annotation/output_001.pdf b/tests/output/test_add_strikeout_annotation/output_001.pdf index 10ca107dacfbf253dc03e78105c011c5a15e3cd6..e89bb05c2dbeeae088bce64c918d561b886527e4 100644 GIT binary patch delta 877 zcmZ1`uuNb>EMxu2qFW9EZSU*4?9@U<+>(sd>r|q^6|^gHx*7wO*rrWGtyoNg{b;A_hMd_Eb)2=VMes0~fE#d7hUbR}!)h-vmJbL-@msdaL zzn^pVc&Nz>+m+6!N<~7ZdaU$+dMD)TVeH!FB; zX<*FUBm1jN>btXc_pC0yaL_`A|@3@+a--@&6%pdm{F1`gie3 z(Uu)O?u8}|7W?|ruPddl3 z6VFw>?ACa7MeTx@^UvzVAIiSHXiMCw$bC>*fw$=S7KI1@p7F(>W#-3CwnkSBp$idQNvty^g>x4$NXO>pREec-}vw3qie~}xVZNQ%wqa3=1rn8^WS` zZ6?FSOV_#;YswoWHJ5R9HB~%Y7{Gj^>fMi-&$wR+ACQ&uY;`}ld}Tn8xX)pwO(GKS z`GdDFeHMTIfFiJEqFi$l#N=i#KFtSsyA*5t74~G;0#ulai delta 877 zcmV-z1Csov5T+2YT>*bhbJ{QvhVS_mdu(SIf(-=7t(_#j^pJGuIitu6Y-?FY9|`^U zU18&oDRdl~Luzw*wfgYx!>jccM#ItmIU>G&f#{%LV7eGi3q7084q*lHVs<2+f(HN85)2E9pi zoL(J2^3Hf#M_Cu7%3vv5M9-$z%&tkVon6gouMUZn`c%$MrsvX&r^o5l@ju^rH5*sa zp!cK>!BVz}o=vZrU6WoryP8u_RU)N6m2;En16)Ak*|tWXm#yJn3Nh=}%FDZ`E^N7K zPPNuWadi^^>d}8yRNG}-ouf{k^WjD~{0Pe*t?2FY@vIAuC0f@{J9Mkxas7`XNgk~;^b@t`QI=^Z9OC!g803!l2t z4*x?8qZWp0bTz3cOy*rEeANaOP;R|~M5o$-B?m&G8-UcAMd{Fa!^WYUtfXuWm=aG~ zOn3tzd8>bP!WL6GZ>CIALWyV7c?YR@;^P5bF9DA`0p3GJP-2}45GifF7{Yf4n2}=!PX}+L70oWIxe^UkqbAubq5;Saf4m^MB)aMKu`Hx_C16qq9xnUk|1)JFS z5^>ZC@yf4BILLwtAs2=R-VEV(Coy;EL(||JucZ_yd7bn*CBlUr?A+XFO87IxJtOo5 z#w~rCi{N$sRIf;qfCMcXp6w;$Q76Vqr@?w6v;*SHZ_EDa)tTR?-%6v$tO{jrWOH=v!K06Z6z=oL+ zD%Zel9M@6SiVr*lD_O>PONc$drh9V7v*7balM~tTOqJbE?Gt~g^r@WpHN85)2EB27 zoL(J2^3G&ZM_HGos$eBsM9-$z%&tkVon6gor}l|d`c%$MrsvX2CdcX3@ju@=osACB zpm(J9!AiD>o=vZrU6WoryP8u_heRrUD(5EC2e^R7vuTY!FIvOD6k=Abm6vyMUD#sT zoNBF$lfy~;t4Dv+xVFpaaE>~8&W9V}@FOgKw4%3*lN%l`j)vc?{N$g?Pv-Mi)*p>8 zqxoeLCGh}~_&duK!V_>7#Xqexmj~%5&|6Bc1os z7jfLFO`w&AiuXq0?d;JF!(vSqf=56adSK~4B@*2%t4;WEvKcrNDT1Bo)0RoOB|LTR_2PRqR7u znwBAR`@ab=g?9*KJpTu!zbOZUg~2uEDH=9A2cCa*<_iXm{71060j))l+%WgIf=%pu zi8$_rc{c!H^~&oqY7niWOHbmGVRU66C`39kFfuVP zIWRObGBP%^9|)ZRLoi}xHZn9aWMwfjH(@emWivN1I5K87Hf1q6HZ(LcVm=@|Wn?)v jIAb|wIAS$qG-EPjHZw6WFlID4WiT*dGcYkSlm7`C9S5&I delta 909 zcmV;819JSC6qyvTYXN`Ba@s%;hVOogJ|kM@lR_Dqv2@(91-8XKy=VAFkK9%g`Q96hp>WpF+UPd!G@U- zD%QY!64g=GiVv)Ur7U8+CBz51%krp#`y4vBx1`c%$`nqHk?gWe=M zPOpw1d1pMWqpS;3Ww4YjqG!`i<=kZY02k1Bwyn|UWo!7CLd?3g^71aK3tO(5 zQ>}GTT%E+fdNhBFYP*c9bJWRmKHLb0A7S~U6}?@a-0*O5H2h}e$NyA*yjZ-l{&;aY zy1I-wgqU@@So*pQt^LvP?VSNN2tD zMHF>v6KJKO{Jl|lJ9~7)u-uS^;1Q4pxpP_&aDQ_LFXVqVATmIeyI;KoG-KHT(7jmW zfJr0)j4)ztM7{yNVrV-zgirlsbJeN0SpQ^k>oIeMgln0Hn?=N{7xHHV)-vC1q>Clz7r& z!W#g|Tcv*!wwTI!Gi8zzN<5p+J4nS79}nny33%KI@E$6H66;KWNNMZE5WYLWj1*G^ zML|6CP^bZHJ$L*}^9A(@;0}$X!lU5RR4AznreP6T3XJzhQr=6#aVNsK0~Bml#Xi)9 zX&ExN|C<0)c!xm7^M6qIn=&w%8{A-)pkcFf;8}mCK4;L#e+0W5&{_n^4fAj-*u=h< zh@(!3SAI>xK^9C1xiCENW(c=CiMc}`ng-u^Eu}!o>!i;q5iaat=jKLJ!k;1T8KEyQ zZt2rp1h4a_dPR~1Bxup_Y%dv)Ix$u{4b~H(9S~oBTlP<{&ip?82CS~fp$cVgWOH&FexA}O>bmGVRU66C`39kFfuVP zI5IgfGcz=^9|)ZRLozsIWHw|tV_`XDGcqJ|MA-U`|$bQ z?_fNbS3Hd*= zv)e4w?9sg)RZJU@rS!(xQv7U7Kzl9%(0(sxVg~%UQ)*R{^RNcneNE$yFVB%Sc3<2UG3W6q!GhM z;n#Y)Z=6u8+A6jW2K}rkRGW+X@7V+T2k$(wP5P^I%CRtVJG#W7@@Qi1j}B}5^ns2~ z*B2KaDgCKft51xqoZ7T=y!fBd1x3a0<~V;u;3ef#Ho-RgLXCH8w-2$c93&8A53bUV*J+1#MLtY$F=l&W2(0#oO7&@VceB!GCi; z8G(IPU&LII)PYfG*#DW#u)by`?LpCK=;vjI{cbJop{uCB<=hd29rkN==vlp!P3rJ@ z!F%*_pC!*ey_)VlxCYn4*-5e3!B=I5vkw_?J=hv2cM+S5lkXQ<*VDA;uEh?Y%^#dk zJ%imBFEVF5?)SyxdxpKAti!e7vS+E43Fv((PBxGrKg-T)6S2dyKKUGVFXxKqvBP<) zBs>p%fpcpz?Yb1X@x8$8uczYK;A8gP=CYOYsC)pgk+#$p7WgDHteuonTdw==Qx+YK>I_^Jz2DuWK-Ygd?E)s+@HUm z`Yz|AxwL27(J=2V&hLowE;5TmeM4q=-(7j0rQcJqn2(-OiR?~3?l-zccC-M!Sa51- zFSNN0*uY(d=*0qwWjgSC2>qr5JKS}o2o1AjIdK;7Jm-&#X?K-S2bH4XzTQ$iA6)q& z@%t|kvNN1r8)^SnW*F~t7hVUh-9)V^qrS+wvm85&x2A&LH$g11ot5&BQ(`fjsmD0C zZJ|A?ih5XPn7_Rm=K&jP&_=h!F4xHS)31WQmd-xTxqU0`(RJw2W|56>Zt>6_UQhiM z=f(!wLmK6l*gzxBKH4m?IxqFIChC69)y?vb&kkpu+lCGPyqC4yUibK48^Km32#JQ& zk{ykCo=&eJAurP;n2f^X?5}SfP)i<@xxr*HTGEA#rY4)W!P;OFJjOIrnyucN)|8f> NW61iyC9Gz*?mv{|K&Su! delta 2670 zcmajhe@v8h9Ki7%0-XrQ0inntoZ1-_!aWDvad0U29H4LkK_~)u$ibZ_%uw1@D>BKQ ztWDa8ujVXjK#~)aNra?Lg)XA}u~E=sZ7xU+UCCx!F$-6HHpl1reE;b`UVDFke4cv_ z#=^X8VP1Cj6`5aH7;Ba#uQW!So;v3$f60G(K((mcafwykUVYZhMr4te59)_b+{|2O z@9tBJ!>;~UFJyFydt2YVn}2!sz3GmmA2bP$pi^P@3X2O*em6OpUv#MNp!~)=6|NtT z#h&|b)jtb{ITqz-3P{`Xg6$fs@QXW8=Wa;+XnJIKaO?S0x3#XR*wm<3OwS+m^(Lx* zN%#D^`R2psFBh`@JU%gXcx!a0DSZ57n{zZF_LfsUb+@N$&#}O7E|z?Dqs8N!iS-M7 zaAYK@cX8gCT{Bqe(|oPSuI(!6*dH1`(Ro$TqIVXLcX~tHUjO!pR~dLe?AC!dWigrU z-oJd_Pw#lHdq>|Eo5oC$<=0NcwZ%34o~jv)SoT%GW9d4hHYFvM&B(hYKa1?j@|{c8 z2GJJ10$a-p+8TnfO$1|8D@1l71e;nxTTm#reWA2fDzS|yY3mEaHlQ)HlJJ_Pxxo)O zcSm5KjVWNIk5ey;M8p2m62p4iO4|Kbp`i~+4Eya-v@2FqU*^0o8awQdQlV#Ktn7*k zpBLO5BXu8n_Q^GL@1a;+3uhgZl?G_?}_!hZ}G$xa>*lfOzy9Nme!-FFni5suQrovj#pz-OqXZ)7arW zc_N+%KF_&fBkigrsqwwQ?5`!`+2D;@^o-ohzURDOz%JO$Ort}?`sED)kuW z=hJA9)Kg#N>@r}7c|y|BFwYQYyAeCA56D2n`ZJujWzznTbFYc^!Yt}PIKRIMJKUeU znfe~*quI1)nb9!sZO(6r(k?Q+h59Fn;eEH~IF^1-!D23YMlQ17a&f<47unG~^kQDm z(q3qDTd;xKx1tyGEG#1*zlYF&&c_aS9WFq_EG8??0-opG^$hK$h1C8g2+`&K!rwrH;?Z&}nso_E8?JZ5R%==!{N5yUS&8=v^*Ht1KIqV5SkFMY5@am^A(eA0V#iohSBahB7S^>c&}ezG9OM#J)6w-VFk&2b|jvG z4KpEBu7TM&uA{6KA9x5>vW)ST5PN`4_vDUe!RL)8C$i(2D!ZN9CsOHCIqz$FbAkO)2n~uuirVn zsxt|CM`|CeWQ*w8^qSc<>9w<~IR$k{q|&EyZZds<3uru>*68b^HT+8vP!j1K3hljnT85e`4Y;#VtryEwVw;o@lc-O5k?sr+O2*B%NIZYu%?`<|3yuX^*H1fitKV_`k0MPU9d23Vxpu;l&U9rss2hLH@IS;9wJ;q< z)A51QH0na>yEdqR3hNc5I@1O$F&l+$08-}`r9o7c>^GMt8~gp zRl%Dnmy}ZK8M=3ni6=fD(Df4Vq!ZvBR0Jhfxd4&T#)~2RbbvW2rV5IJc;=x{1K4=( zc)7OD_!Mx9MpEff@L7K*l+-2Du!t-L#=9e_=q2HCC&IV|6l_+-KGdaY88WxOn*dXI zhd{>je^C0HaxhpJTw|W1VY74KS!cdr(8zxTyBpA21j!9!e=FF;zL$tcoe(emiiCqa zm=FqKc;L+tZnqK(hdwk7zVTX0fs)rrUr;Js*ul;%jHZ;^F!wQx&=(lD^jRT-*ZEVm zBuN5Nv}ky?myDB6jFrxU^+ad~#FyVz{nM*6zfXSvdBB`~vqA(20tY!TG%_+WHj_~X z7za5pG%_+WHnVUBO#wqTFkv__I5;peGdX2BWM(ooWn(lkW;tOtW;A9tIWS^AAUrlO kVK^{2I509ZIb}IyW->KpV>B^lIbk+tG-ftAFk+Gj8r33nK>z>% delta 806 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 delta 1004 zcmZ1`uv}n+A7j0RogG(kNl|KIE?32^yHigW-Et6c{rWN`nKWlg z)x0zO+nOp2?H{El9QN68%G6-KYwzi(kBwU+PhNVgd$778_y425`tXC#eJ2ZF{pb^V zH%^vo<(HMS_{*zG8+EHTzp&VQ%>L8t!b>~Wcn3|5Jjr))^UJNPvoF66yIyc>wX@<> zyU^mTMtS2h3aS zZl8N`dXw>=)2?TBZT|E~FRNZ}Tg=wwR<9TBuM}2DChY836qn1i)+A()Iaj`Tf1SiM>H19q zMogC!%Kf;R-sQi0(0Yf>g>MDd_v{G`dXe84O7yQ;Bnf3QDECB22j)1em$-GV_u*%Q zn=xNs>0Yysyi;{1R&t^EDWeB*!cD>3XD2evQm(9FOOk!n+}s9xUCp~HIYxAIB}m4`dT6Ynr`@vVL&^U7!o&&=QdeH%3Q zI4eB(WspJg>~tnR@pgs4rO@#v^`?0{Dt+HZf#h{ zgwne3^&XQNM0BO*$*Mf|)Ia8xu2`kCh51qY{jk56R~z4F_utR>JoNa5&3-H#Ozaj$ zmIlVgCX-{?B;f2Cwpd2P$+y_l8I311v0DckDHwo&LLM&{m| WEGnreN=@T3G_y42QdM>JcLM+@c(tMc diff --git a/tests/output/test_add_underline_annotation/output_002.pdf b/tests/output/test_add_underline_annotation/output_002.pdf index 09751b3ce5e7f0ba49b6c687646bee47abaa1412..286410dffd5bf5c37cc0be0b60d167eb6efe8b67 100644 GIT binary patch delta 1041 zcmX>hd{THr3?rk(&=4mVvldBmu>pPBJ{8#K!^PlUZ1|3tpp=3}X`lUAMaD(jf%yFNB{cHH(|ZI|O@xmJEzIqSC1`K8m( z^j*&WQ*U4YxyWwi-38y5@TI9*yPRKkecd|W_0h41HCODK;5C2M&a+<_?Hpcje%rH8 z$NKR8m?LYfwe{aUdX{uLw0hNMJ-=6zf86fTd#t86`Ik)Tr#b!RhaRd&{Cl%w`{~Kj za&|IX@4xwV(mvKcQYWtRe@2y{uHGb#PWK5%u3ujLI^*NKiuyf~GLtIhWxTiK%_w|P zUVr?1y-4P-7oSCZ-7M|8Y_9uRT>7a{EO>nHEtaUv6&3j+_w?lc8t9m(D5kJ1aeOyN zjOEV#I|sRU@^;7sh`zh7z!bt@n?6!7j$Nt`qJU^82&4-{2Q2yuPgXCv?YvsKtu1!8UYzo&x})0d1$R&MuQdXSum7xz zo2bI58D(N)?Qtwn|Cm?0VwKVs=11-K!~R}gZG7KsXVtv{cJ9qm)$3 zRC6=qG}9DwOEU{g(=pd_s6b3?rlY&W;Z6C$<>US^)q_Zf1elp_*dJ7{V&t!qZM(lQs&9zuzpms ze3YJW*k{8j(+Ou59ZOyN&DB-usjm$SpKFT1{W-NP;6?M_;?tDc!%E`E9R z^W!g4|Lf1+-{Z4vtMr$7R}QX8X@7C^%dM+hUzV=UwqOkv4|*AFx_zeI0rrgAZF4V9 zPfh053!V}Cb>RnJ=@5t3 zuUtWMGnuE!aJ1&J1U(m9>inEny`5{*q)(;^ZZ?^QPk9@jti7a}?jyQqW|61n(s{wp zWm6t?_Oq8Xv)H_4t>71R>@3xDNZIl=iN{_h!LMs&(;|g=l^Rz#w#|#Kt6#U)*pBti z!igbiA~n-ERZCBr=qPzNe*EX5#pY@8&Q+qkq3Q4{i}qbSy3Wu3)e9$Zy%#u9@sIyh zO)wuDce6B4?1aPTj%_|yb8x}L{~Uhi3$}7hvVQh(SG6ap zD7bdFrL&)`xYWJzQe?+Gj<*dz9&Qi)|K-)0@0asW^&UUBIhJJsBfEu>rGc@r$z~R| zrHpDIj-j!kk$IGXfu@4KZ+?nPVo9okhKrSvfsvsBRPE&R?6Hg%lXW@N84V_fa#%B( zPM*jiY-^!l00Ihmyj)<0fuW(9Ifj^#fhC5Rv7zDQhd>jIF=Wh)%`n8w4NNh`Oid>n za$3il85&s_nOdZznVTjWrkGk-S{PawSX!E=m?m2qrKP6XDcD#hrKOr0SQwjFSejax xnWPySrKTmDnWY&enxvQ*n3~(ga@pB&6_+Fyl~fd^rg0e=7#ne^s=E5S0RY8Lr>6h_ diff --git a/tests/output/test_analogous_color_scheme/output.pdf b/tests/output/test_analogous_color_scheme/output.pdf index 34d759ee03d16b85ef05517163eb753406b251bd..bf15f2dae51ebefaf3ffd35d75da34a467f033eb 100644 GIT binary patch delta 155 zcmdmOy4!TaTqc3oU&prQH*x>lK3$;h{q6UAH?L(f5@G3Izg~UwV=)dU4NC(PBO^mg zL&GQo15E{e-~1Gp#FA764HqjT10zENxb$XWNpD8S6e9x*LrV)|lTjk^umO?=YYM delta 155 zcmdmOy4!TaTqXhM-^Z@zH*x>lE-qd#f9ieg=Cw>lA}l^F>y0-*7UN*jurRVTFg7wb zu#7S=&{WX(%};SjEJ;<+aIrEnFfufNOK%pI^k#H4vota_HAuEdO*XYmPBBO}HcL!1 ZF*8gwHa9djv$ROGQ?S9WWb%9|831QoEyw@> diff --git a/tests/output/test_append_embedded_file/output_001.pdf b/tests/output/test_append_embedded_file/output_001.pdf index 1d4081bda3cc5ca3293b44fd5e355ca97daca625..e1badcc13be00efddbf32d3278bf5477731e0346 100644 GIT binary patch delta 743 zcmbO(FkN6nHY1Zj^5k4bpL)CA+Zx$NrRAEo-Z}nbnm~2K-49Rt(hvTQU8=t6@l31T zUZ$N_eubR#_09L&;G8cdzx?{Kej8)Y+ZwNJS6W4!mbtkEdV5uD{nq#X|99qQ>1@vnqAS%!Z|qk4uh_f7{jtF;Uw(tMivkk&w>YwfM6Fl2ywfb< zWMjY!J%?9^HZ8tT$*i<^(wZen%rk`jqta$%I(!PtJl47D$?TOArUX9YX1}-bcGw=< z1=6YyN(3HoX*CJWc4|10`TQtLoz;ORkziI=N1M+9E4XjeS8hvLxYpQ?xyDubWaouH z2cPc@2zo!W%{4{SVBNMQMN?XqH*-AJUXZX^>)XP6v!^K*bMN6bXf5YRvDx3ecmGa% zDIMOtpZRQ3tE8T7K398k!Nho$-O?ALSWfb8wiL}tviCX?-Yl^GZ(B>V(hLEw#EJ)J zS>DB|PUEZ1kg9pKb&3;{>iWt1miX)_V7K0GGRsKE={!emW1;u_=}Hx{U#fg3v7}^N z{P0FYQoUJ1doKIy&I^1U{QKAbULKxaH@}Y2ZTAe}&GsxDOq`YmCPqd^rUvGd1K7k6 zyv_M+-i*#hX-27OiDqfZ=H`h8rj`cDDQTw3mMP}usRqVLW{C!N3O0n4O#aI*1prn` BPZ$6I delta 743 zcmbO(FkN6nHY3x6gvq&#KJ|5?+XJt4ncJ{r@9h7mtN4v!_rsI2=bOIIUZ%e3@l31T zUZ$N_eubR#_09L&;QU_8&ToCMd}Z3CZGqRSgGx6{vt5*a`E}a$rPt4|dm6G*ZDQ2? zQ#((8iK+6eniD7e|L@GrugxYe&<^rNRVi{s5vo$1(az!dt*>tJ)Al};=Q5mq@6_qv zJ9Kk)zVrKf?dZuw^?zFzN8Y)WS~WSINwI#uj^5(er&YWjad#{;zx>j7%0F+LduRDh z)^PNxMw$Cr^Q^vK__u$N&c+jRfoly;8&t;x_bvY7BEz30n6Y%>rHOjSGJ6vxrbTZO z_``Tfq1>07Y2W>Ohq-s=PB_%jEBLf*N>7>&yTPT^>QneuFcb;@h;b-xQ<$UZHud=g zV{7Ks^@Vk%Y1f-?^{kj-!K*i;E7s&Ef2NDARQts@uNacWcpE?ZN{2Ws{mNxDH=B8y z3`grbrX_kh)?9PV6^yh_dTE(8SbkiR+BTC-C4Xw#oE2XCW^#E-rtT|vAiF#F=xyd* zflPkvjO!LCX>8PF>6lX%=ks7WvyO*hXn@EOWB%4%4fS)=y~S=>JvKfNZZc^O$65KB zdEBaB=VeB?Ok;YS<*nuJ`6Ejpv4&M7C+w)*mFmkzDS3_C8JB(FYwUSmzTvz1clYL{ z2X+6Sb#M+nTyt%wzNE>g?u2sYsBVRwiDt{2eBZctR#$*IG8vsj4Ta|jg1Y=CI_&IA$Xhf w*}NH@6OGbROp;B^jLj_!O+d`#kktAGri;;ZujkWw9afMo=11Z=xHuC-`!z71Bu$jH;tdbM zO73HPON>3hu77gJv*7)%rYExFnJT+d)rnO4RL*rxZ%(j9Z<2o;r`N=fJTsj(QPz7> zRj`sBqG!`!zrpmB9%UsbDQY{e1O)q>x{lEJHtN|VmFa0uB!%qBbMzf@` z%hh2Yb#kANx59tpCs;mpqIb)aH#~ee8h*F()4wV|T`b;M|9EmaURMx9SHb-dk-(84~4pbU0_QV+Ibr?z*n@Ayok*oLY@mH z^`2>5M2;fka!WFUBs}Rw7+(Pen^mz7_1?4$nOop(geihYARG7{?ETIC(W0@q<-Zwd zsce|fIuC|HBfkiCH=uI}k{f1yD%iwfkch8(AzoUC4G9lLG$9yac@XRf?p`Gtk0CY< zKJi*gfs)tBU?>wl-oef_R#S#W>>05yFm4%gBcj(quh%3=K!y%2&kmAt+KaK$d9{c!7gP?I6theO&jT+xFf=kTG&VCcS}-soED9hXARr=5Z)8MabY&ts zARVmVRCeMa%E-;GBP(c J3MC~)PeuaLl>-0( delta 935 zcmbO)HeYN*Ib%KFgM{Ndw@zL%U2axi^|=#Cx%q60Yx-5}_iOX8Eh}r^VY%hO>D5yO zcJr?nd#^Cdi{lkyeJ<^txBRo(8imL+{YQ#7B&xN1%TA~h-5z+Y%iM+~ zduRVgUBzzT?w_A>QNk7ru#_A>3f@+;(=uW!EJ2Iu!$cJ+Sid*v(BCT$D6 zRvlEjVVdot^vkc)t}nfQe%;fMm1+~C=AYVm`b$ieXVsiI>HmLcZhmbxd4YD2FRDtB zD~eE+jCKysZ+&%(pSJg*JeT3@d#6tS-l3bb^PS(Px*^=n_ru+qqq3=X%(+W+#Qc*XO;*r|1Z>E zzS-GGzA3r$TJL4P!>`I?{x8<>*4gA9qJ75bjNJ7pk2P!sk2goLL}jihS<+n?l`PTr zbeaxJeS^t~*vm}~@3(*d;FKr5#2_izWv8s_V#(8tJzwfyaV}-nYPiERjvlW~le%~l{A@C3CN5(<8NF0eebuD=WllkEGxcREj^{;x z{ML{+rQxz;gZ2uJdaoQVMy2I*#f5*oWZ(|+5fx$mc*c35Uc&R6lUlc(`@!=;v{yyl z=`;KM=T4q`)1|~FECu;?}Kil5TkDL3m_7|(=;Tb}keOS&j>suIE8W|M^ix`s$4+>NwKl9v4QF4 z!yNw^V~tFW6H}9n%`DR_QVmU$EK|(j>?6`_c5{pVIic-_KjEu}pxl~nM{oMfnzM_Nx diff --git a/tests/output/test_apply_redaction_annotations/output_001.pdf b/tests/output/test_apply_redaction_annotations/output_001.pdf index ad4a63afcf087958298e7ff7d818491d905fbc85..7947e6f70da46de56ded4920ba3e27363eea2500 100644 GIT binary patch delta 1043 zcmX>la8h7{A0wmDWPe7{`k$iJIq4Ef)(KvDZ&h9{ZC~PiUeYx#!FrnRmx&YV?~9t< znCEnSq2-pg)2pwxhxf;?-P4#M^R~|Y$oKUE@4s^UJb#?IH2v~TyEO_k&-WcE-mp-; zWtE}9>?6KYwmxFzKNuBeI8P{vf5Xf9cRuP=>|On`^UaRs=kk_+>%8(SOb?fCV6j)N+ass=f*rg+*|NNP|V)?;_ag+Ir+ui55M2`_sRNg z^Uplbzf*6rv*+1#&nZWgJtnd%i#?XlUoynC$R0Th!QBMFJ{+&a!rBD zVQKx{*9weFb*dS5iEGOkcIq?;x~=KCkgYMDC-?QS50x`=?7nL0U$c+AQ=t=+x={R7 zu|T9l=+xPXhi3ZzK9G6pjf7bC8jjAT&dhnb5k-+|cKLa>XY{9;y#0E#Xvg#grTV@9 zos|OHPb{43$LFx_lAXi8scfPXw#7MyJzL7?{YI>{K96P6%>^Yd_BZwjHj@D~&XN*ob>g6TNKEp~HG?x2h-qq=Gx$26>FE zvqLxXpFXvPXJ&o=>Ddgy73~hkK3lK&SPJ6y+Kk{C}p~j-iW4=f7@Y}FOWiOmBJ`j%g(hT@y@zON)P^;vd zm|U+@KdwESCHRWz@ie>ZN)>bW=S)-abZ8Uf{mwV>W68bljar`*glz>+F@Aiwz4Y&w zS7&~|6xT{*n!dS+g@Z}M(!j*X$jHpdFv`F{Q$gQ1KgA`nBvnDf#mdOQ$j|^TJ$VsZ zG^6R{e{AZE=9AUftpm*z3_w63kCzL~FfcTpa7tiy< zj{m~P7i6LiKfU_u@ap61!|okQvAOxTuj75Z;;q-|9%7G|T>6}{k6*h({Il{$nVc7# z3$u96qz4M8uB|xeykS~s&+?WVwmHAm%Wb&h@@LIC(O3QIOuURm;7n!>UZibr0TZ6 zJzl@{Z^g!n$NwH5J^JL6(!3)VIn*w%e)&eL@1LsN`?U6od+f)B)=Dpv{q^?#$A9uI z*M7ckKIr4&p88RtYf*`khqXtxOW=C1#xSW%jE47aFf_*=9Ir6#&CC-c_p?xzL% zj<4gS{hE%>Y<7Hkq4Mza9+ODV zqf!Ry@3zeN$l~xRY^vmM-^_VFtxI~0&Zl3oK5$88HcP{jON{Ue44NIW7h>X^N5s;8*gMPw2IeDntbX` zC})o9R`^+Wb3T{ZMtPM-p87|$_p9x5=}K_AaH!z$Y{NTyJg)H7YDm>Q^44Val2hNi z%x8x|^W4?Go|5-(#TYxqCfvF7Jc?!g=jms=R5(vuSoH9oqLH82UWwI4{36$c7s?38 z*F|6VUw>}T{5r;pdZsy>3t2drG%SoP4UCOVjEtfT3^Wz=ee+XX5=&AQG+eBV42%p7 z;L?*9vPCnRP5#TK&S)`NmED@rd~zbYu&t$n0SGAM@p6F~28Kq)1{h+-#)cSTCZ@)d zH?mvD8d+MH7@4LT8k(gT8>Ctoq?wzi8C#f}nwck>rKTAq+9}u&R1(W&XUA1sl2}wy TQIwj-WoT|}z@@6{>hA^spxV9K diff --git a/tests/output/test_apply_redaction_annotations/output_002.pdf b/tests/output/test_apply_redaction_annotations/output_002.pdf index f98d69b8e6e3c69cac853e4654f65a9a89ae1b04..10770fd758685d3670765de0dd9ad8854a377620 100644 GIT binary patch delta 727 zcmZ1@vQ}h645Om4ogG(kNl|KIE?32^yVHD&Zy5-*z5gp(os%xnB%9-uH@TKkw!ZE3 z>Z|SH{qbw}G@h*3^jlW&{(h$|*YziyIqtbM{bY`On85jT_eYjDE(kkam6+kXSnX8Q z$ENlK-PIEQoEzD1eDQx*A-3mUYLSxlyOo=7udG$tYB%+BoqxXH2G@Kk+2z-d^xGKw z&C+rd@G`z5BTuxL)4@c+LvGjHuVzMy=` zw}Vk-9rJwG&yAfOXTG~FIH27nt5)l|*=6=03~TQ%yZmd@3zPpF1UJ9x*|Vd2RP)A0EE=VRx?mztwM#fBq@` z-F{}A&ol9lDqMYT0`Au@uYR5JZSq2dZg#LNiM` zWTIYvVR&LRIhuL4#Qx?}_d`CEF63Re@x+AsSj5Gb4*M1545OlvogG(kNl|KIE?32^yVHD&Zy5-*z5gj%os%xnJhnw%l11TM}DZf{KTc~PH_76;NLD;wOY^r&bv1!q5EEF$(%T0`%m)= zFS$g9FL{-qYwdD=+4XbleAmy8J)F7xTj!Nu^&#hSmp#AKJ^AsMSwG(YpSkR8F;A6y zmi(I3_7^w5+`75-W$ET@3)WJPCD)c0olA98Z;j5D6FPv&RwVw^oWibaVfGL&i7 z<_4ApjO-RhmIlVgCY#mSo-wL{IEKcC#wJk)2AT@`zWFIGi6yBD8ZK5w21bSkP_>hd zIbsa4U}$D(oN8d0WNMsdWR{v}V33kxW@2Qg zU}I=xk!WddXqIMTZfIbXnqq2{l9-y9l9ZB?Vv=HHW@s171x}cWMI{wQscBqBhQ>x* Js;aL3ZUF0(41@px diff --git a/tests/output/test_apply_redaction_annotations/output_003.pdf b/tests/output/test_apply_redaction_annotations/output_003.pdf index 2a1f620be41b5e353fd877ce8ab4c3d94e3b7225..7d11e42616e5d7c768b4f86bfbefbc2429c8bd98 100644 GIT binary patch delta 1153 zcmV-{1b+MP7Vj3YYXN`Ba+^RDyz>=vRH|IEzyhq?lCqsk4o;$+Qy7p$3M8Aw%ijlS zMq=7(4Tu=~@R)^}e*IQtJz10SWcMeIAAWwb?EUkL<<7>geD+;`Kb=|5%qR1ywX%L$ z#ddW&E%yn3YU4^h&gz3fKp?V9`AYI0{%KTVa}J<<((}KxaSMYb`HDh z|7PUbjaOV9_Gf?A=;o7{|FuSe6r~jLPTbDBVsJWPaAva;ASUwKsT7w|sL2^jI9dJ_dNAA5kk8TmhB>qR8YRf~gsw z&L{7V4q$XIg(C6})?NT$38)408Ufd4jQO{rx%TQujq7{Bxdeb0234YV&H^w1-jK5( zM(ULFEev*lg~>7O{4zL^*O0Q56ID_?fM+SVPp~BhKFf368=Wr&fmVsyE!H_j4#}tQ z>U@4ozD0kZz{C=tOL+hui7({ruoc58+Ur+hNKYlvVMwcZ&=LJ-EfpVMOO=UxQ!oJv z4kK@RVBpHr8TbxRa+c8rtE`wGaAyQ(rtAg*rz8fC$^cTyQh8{gGiJub!zzXhlZ^yu z8*I_6IW^Z4hjE>-z9j+FOIBG^#?l2NGG@6E&4GVMCqO{~lyBH!rJ?3i6Qh2pbi_uL zp^#K;G6jo07#vy<^A8wl4p_fKR3OZZbsB3{?*is0Se^q`Kz=hiv5+S$zyszP8M8OM z-Z6fBZ|qDNgMukW`)SO)IChQZUY-g9&3Jkvu zyMcag)1J`OPtlkRncW|m-Dz2%zjrKPOUOJ#F#QUaUYJJ1g^@dhFv?i8r|sV{rhY0h z^dd#imKRf1^Huo|SL8eGvq1%m0S7rSG%_+WHnYLKFAUtGZWjHo6FgIjoWMw!tVL3Q3Gi5h7H)1q5GB;*nGB!S43O+sxb97;H Tba--QW(qPhIW-C;B}Gq0tXKf) delta 1153 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 Ib@g`x0NtrY$N&HU diff --git a/tests/output/test_apply_redaction_annotations/output_005.pdf b/tests/output/test_apply_redaction_annotations/output_005.pdf index ad0615c5bef01188b1093533c36bd408228a8317..ee0bb98671726bd261a166fda2d1846df128a169 100644 GIT binary patch delta 941 zcmew;{7HC23?rlIOvJ-qBu*jgohi-V%^2i;!&``yQUB#m3p zGkRrHOdS8V%I7By4#-Lze|S!&_Dl5Pqr!|yjr)z8*Gis~x+8jyqdL82e$82~X${&Xp^#SXNdZ)H^Zi zdu3kHu3HNn^Idnnd|7eaG}qldFnr0YgnHd*m;7bvyNq9My_@N$epO;+>HPG`FV}v_ zSw4GS-~T$_>sS9TzN8-HyJ4E{BJ<0}cV~XN_0B|n={dKoyU%Z??8-Es(JlMNN$Kdn z*!7!Blf!^0Lg@9<~2>o2MieG_2xC&psxg^9-v z>#{ULLU&85%bb^Fa^HT_@`vDRj*D|sSWk2;I51{V&u{T=-pMS^#A#_@Vq|1wW@x_oChHSM4G`DR#KO=b%D_NVLEkq&#U-&MRYAkW z%E-XT&;YJ_@>BLGCR2mSjvVTYMw2r+tZj`I3_w63kCzL~FfcSWGsO@yFu)>aYBBjC zhj6MHhH4`-3k)%1O9KosQ&US!F)ZrL&CMrAa$3ix8k<-qB_$`DCR(N>Ca0vBrx}C$ECmSTCn50>lrY2h?rkEreS{mEMa@pB& Z6_+Fyl~fd^rg0e=n3`~@s=E5S0RTX?c0K?A delta 947 zcmew){84yA3?rk-W+& zn65vFJfSQXIl%mCF1w z;knuJ)x1()!u;%QW#8{qFDw-)^&bD~=RPY5T07B=ztU{xJ+J;9 zf4`Lc`CeT$@1N{cyNOxNy>A5e&Ybu1+>-01%Ploa%`UxAJg;`ycl*JZHwofGn&0!Q zWG{BczNp}{T;C#Z`$;BN@APM@mk+EqyKCK)X_C*Mb@c)3uEM{wzf7;6Vi&o7{h9e| z-oI_HuTBy^&UCwS`;qsr>K}c)eyZ_Dasi9aiOgw-cl=R(wtuPX#65Z5ViyBG+1$RQ zb6Pbt$Y+y@OnS)j1SOryg$6#GosK1PB=bc zMurA()svsGM=_aLPIlr@XEdCg#bI4DVE80v0Qd` ZT*W1cMI{wQscBqB2ByYbs;aL3ZUAjQakT&d diff --git a/tests/output/test_apply_redaction_annotations/output_006.pdf b/tests/output/test_apply_redaction_annotations/output_006.pdf index a15730936ef393ef7ef581d9e69438023a20f360..537d4f31ae590ec6c60155274d10fe594e7d64c3 100644 GIT binary patch delta 824 zcmV-81IPT>71$N9YXN^vbDJ;_z3W%#=+0ya!Ujxl&9v#IhqUG1A%WOrj6cAhH2=N= ziJ)iJGImOGSnaMp-o9P5GTX7cnBCqBE?gczGe6?NOpa1E`SFRzFKn_=qEsSNqELb> zkt?xPqEg~O%}im>6?FoKUG&y_@FlQy22*YtAsn~)<8E*8?h=1<&zVNeP=?%E<6_Wa zZyGsrRex~{E~Ti+A+{$lu9a9oq!|#E6OkVAmBHyG>$r6e*{Xoq4Yk>xDuk^ilNcWc zol@EX7GUZRlyL=R@o1@APL#~InEhls=AO>_ukT$=yvk3+@zpr=!`56dFA53!iY?i1 zR@L6xtmg4>CeVK)^`idvOovvLT`q0y7lEZw$vvmO1+DaIw9Uu_rFB~zZLC)THrSmB zn%&NR;%v`HkJJ^5hC{18)~{yQL~F9!N854Oj7(5kx5aVH`?c(PKFw}tr_T-o%z3Rh zESe6j_E^7~T@$UzZXa#OVLbv+TDQe<%zF)3Hb@KRav^`)r`L4`*+hl+K1=?0S|GZr zn3_G~D_mf3!|K~<0EX!x3|71$N9YXN^tbDJ;_zUx=$=+0yuBn+6|nrYKZ4{6K2Ljtj#F@6A^H2=N= z$w8l4%a4@gu-aWczWsL5%52N-5_WqpxbS%L%z~JQ6E(`%=*K6Xys*()i&BeRi$V*o z#X^gX7L^t|YGwv|E~yhZ>|(aA!I#3;IZU}}g&2G7ANP8Lcb9*d%CR4}LlyGgniOX( zmVP`|tNM%g;4+Gu1;q9Q#+4Q`h%^VH7DS{6eC2RD$vSSmfNWL3?3&uFrV3%>$Rx&x zL1&b|mU+js{_A^J6R+wM83%eC1<~GIFd0XLeaYtR zH>(!sz=2kI4cc~OgEG1+j(x0G0k+tk z2%6o_e&lQ!phxMNMayB-9_v@LYooQ zEsM6ps6E!NX4gh*v)f18aoCIil+j&r9P-`(Rt?gDxtxEg_9?s0pqi+V@3Yi@r-h=c z3g7M-U*Q6S8`j)TXJGKp!XV@L2neZX4TNi z6oUAQa_WDPRZ`C}2lgSekEl%v&Z!q7`Q)moC(sj>{nW7>pVCHq(83UT558CG4LYYb zTTySVf@1z{Xs$yww77l%oHGD;;|L`?%~=Wwz!OU9BSz{>@jW~8{uhj6nE7RJBByX= z;cvW0>LQQp!`PNL)}- zo6RYl{B-|XIIgFfh+)XAgzzHzU@ztWzn7X6Hx&E>M1#4|vmXQk0tq-WIWRLbG%+}{ zDh56R2{b~2<-twHaIY4V`XJHI50M1VK_8qWj8W1 zHe@$uF=R1iGC5;6J|H|WIAS(5H)LUEGh{SkF=A$6Wj8rDVPiBgVKilBG-ffAz6u&q Ce~Fj? diff --git a/tests/output/test_change_info_dictionary_author/output_001.pdf b/tests/output/test_change_info_dictionary_author/output_001.pdf index 84e2079f254972f23a6b7a06a83ed6cf43228154..c104d2c42ed2bc04af1a2f69d5bfe6d27c2be48c 100644 GIT binary patch delta 734 zcmca8a6w>$A0wmTW`9Ow#`?u4uV&PV_CLyCD6A1apZDlV{G*R~WgV0CEW|Qm?cZKl zTX+1c{!_On*)c);E}fpTM0qav=UpQAa<{x(YPo1d@OlSrUeQK(d)rIAhm)MengSi9 zo_x!6JaG7}?Vbs@8%{8WK8&m8%s94*c>(*zV~mqMm?aXA-0DbTt~z?5ERSP;{qK{{ zb_F+Y{CD!vwd8kR+QdkSpMH`K9{&lv}O-ck{ouafbK4zxKi2#VAYBvM+72 z^2C#+;!5|oII@OBtXH@?(=6d+W55eGh0?r0tCD*S9xD~JHRGAnj!YH{zQ^EkPiyX` zyCDZ>YfhgM^y+5AJx8^9KPnuqdmni0*YLeQKyXULb0!zJX#KVihZ&zOnW3e@^=M|h z6K}%no0E2KJNHARpxtef@WD+FHv4F-^j?-I7|GT1-96}{_n|`dLpzv7a>9<>Vx^%xSOTV1e@fP@!7mSBhDlBvpu1lIjUP>XQf;o>+Bof zg$l25#(q4t-qYelGv`8qHuifw5A)PF7QAr2{6KpBQW1^HxnEe99%_|+bLUWo*Uza( zY?Z&T9@DK2>v&N5?vVB*6$RJsw)EkK=8_k59K()mN21{QXk=BHvlF z&9N*hOd6I3CPqd^W=7^w1_qi6`o8%oE{P?n3K}j}Mg~TP25{-gE7_tMO(wIlt23HS z)@8R2G*vJF0fjtXE-=Hu(9p~rL(Is)0z=H$z!F2u#Mp51PIl{9i`1kv6AOb>W3v=P zOM}!DAlKB`!rU||*~rwyGA+eU!G@rcSS~v|uHur!qLPZD)HE(bb7M0uRaIAiHvsIy BC-eXS delta 735 zcmca0a8Y1`A0wmDW`9Ow#`=$cvPx=2`yXX6EdF@5qDWZ%zfgbqX6HF22RAyr{*~FD z_tkn`y{5TR{NqWVrp7H(k$o96*d5e2{GwS0zFKZ z6t??wGs)$>f7p75&4q6T*Y{iA4#v}D8EiXD`DVCC9pF&D<|ZP2LAz~RvGb4mJN{(#uf+imW%Bdcb6+keGLf!rqxO=in< z`mEb6@N*fj)`CM-tSirLVf5x}aWZFES=@bT;b%4%FV;xUpHc?O^R~?R#OClR?B$fV z%ee0O>|8P>=sepOKBJFEjx+CyW0EUp+Ed@&wcv=AxPsBGD#I3eJ_GfmA&!9p=WRr? z7^2TlJF~U)*zyKzlSy+prm@aXb@Gfg;_W^Wl(5HsQdgW%pS9pI*#!xkwZ1LX^F2M` zXJ~A4I0_OSo{to@KZ6g(#MjXFnHc-#D^w zddFhFxQ_5T-$RaaJ{+wEHXqVB%B?$Fo#kh--LKGH>TvS)5`7I(y*CNZ#oU5Vtyg&` zxlrFA@8xDEmi5KraT8S-HKR;yZhIeF?AJ5(T+>&V4E7__?}z=pyqf#I|9%E;owHV( zV^~y}G%SoP4UCOVj4YxI3^Wz=ee+XX5=&AQG+eBV42%p7;L?*k diff --git a/tests/output/test_change_info_dictionary_author/output_002.pdf b/tests/output/test_change_info_dictionary_author/output_002.pdf index 67938b569a4c73dbcbbe8a5688897fdd59e339e7..9f7290662d640a28ca15ae162f407c56ebc30799 100644 GIT binary patch delta 983 zcmV;|11S8@5YP~?P5}WilTQH^3jGyxY$Zgn!4PtjZUG&C+Fah9{b1(d-7#Aj4M+Ru zg!ujyqJw^cWIjwvJxgYXu!49#I}y*ohM5p5*T8HN)lt@p4?G4dS;lxvh&{r#dvd3< z;Pb}Gne2F`%5JX?iB$Sr&WD=boM40ABsxv6j-U9>IH{woOHx&^k}aYa(`#neq}R@_ z=CoIbL@IrMF6SoGOXZ&Tds2sBC0j%MxTEjmSV%DvdSNBm}*kaY3YORan<4OFfN7Jab%lLSXI(yE?TjB5% zEPl44cZ;(d9zUE6zgzk7UzH!v=WnckG`Skhui{aE91S3jZYI|^@#J6P@osjAXI*eC z(7JxwptD)^$k(`}e5IEuNk=*t=5;B&+i25Eb3{?6UV&B`DguvwdZZhM#fB^d zqkuHX?bCvQhueF2A-4gM1FFKk_7c#PWd}eHVvPePkp?irh_w;L2K0)d?c5MP_mjAx3!l2*?hO;J8sDwqe~4t%LUJ5UCr2Wa z>n=pTX@d%=uwFr`Gi|_<1EJ6jKOg!=NfUcK-$DIK0p&}@;&IO2njJ943;fDjvNikJW6vQ(Rg&M%tvn6wF zo$)E)4vi!yf@Q&HnNU)fOv56w6d3Q1q@tIE<4%Ne2PoLAihZa{(=ud!72F1x{J)C( zp7Hz}l>Vk13>F4An5Ssi>>PO3nJ*YL@(;o82DBDIa`Qag3O2FtCE}MaF7R9 z6G9;j54;(|-A-cR(1)hMH(pCAQ1UwI3rd9xJJ`8}(UkHliF-!q3yfR(tPsKL+=W*p zNkEDg4bS$H@u(AHrL$l?5!wOq<+oM;^y1Cp922FfcGM zAZ`r`FfcGMFfcJOHa8$JFfcGMAZ`r`FfcGMFfcJPlc5I_7c($9ATTg6Ffbr)4GJ(Y zFfcGMF*GwVleY&uU1T{oHexn5W-&1~Vq-HlIXO8rVlX)}V>dHoGBz}0Gd>_ZVmL50 zH#syjVK`)DGGQ=fW;9|oVP!UAH!v_aVPs`FK3xhvJ_>VmVRCeMa%E-;F*h?d3MC~) FPe$Gju_XWi delta 996 zcmca0a9&`8A0wl|WPe6cuAidCIjSx>pGB)C=P}CGOIhr({(bPw;oZsG1b7$!eckfo zpXj6Jy2g_=7MfpkjI3KkRX*SBtY9-c(-N?gE$#7+zD;2@4-6wt8Xb#vdLy{)?qut^ ztn&va1SLcA$)}McRC#6brZ%WauINASyt(R}UXejk%-WA1&lVTUUUz%>tzLcFFUd;7s z2FTnyDZex(Aq-WplWTYPTb z=Z9eye>l45uYGa%(VMp8t0zA!*S7z;`qSi}e|o>Fe}4VqnN?@~qzZ<>Kbc47|J;A% z@!dBQ&g^;+v7q$t7U%81WUud^B0X_^q32I8{oqM`C3mp`nbw+w zu*m)W;$hCy%^S(##+W(b_HtH6{_WpCIOQ=bv4^x)zg1nJd77_5?uZn-j}mV}i(s~L z7w-#E=i56KYu>5Pp6$nb>{q>dcXa%WR?niF=zu(r-1WvO6u5Zn(13_2q?1W~HS~YnIgT z&JgsE@~LE2s9argsw|i_e_2eB*UEI}D)yNbj~+9|>NECRG2U}_4M>{HEg)H+yI0~6 zKl_ZyNvjrUbfn91nKrCV_kMQE>T&P^St(CHmeWn=jTSD^o7v`?qG@nX-qTf|Q++PS zW4?e5k)po?rY}o9@ke6^ufflH(eJj8f0}Fj^|h4H;mI@bzqsM1<%c!K@dg=B>4I;Wy^WLgHULl;kbaR5O;4Q|FPq&Bu z|MKe4^UM10OwU?uj$u(@(y%bHG%z$aG%<)WFwj)c_svgnNi0cK&~ULbGB7eU07)Ag zn;4l-Ucna4XgryPU7gW%vJSg-poxM32q@(7a)B8JhK6Ql7-B{S<``ne1{N4%CdLMn zcd%Q>rY0v_BpRDqn3@=yq@s_N?R1^`JEtd0Nx diff --git a/tests/output/test_concat_documents/output_000.pdf b/tests/output/test_concat_documents/output_000.pdf index 9079e8da3ffac18e7cfb865fbed779ffca3c2539..53662bd60014b18bc8a33a85b962dacbf3955750 100644 GIT binary patch delta 533 zcmX@jdzyDc3S<3W(eHu6hcmYKZFDz&zB>5c^v+O2=9IUa_UCiAZreD6?|VYSggNu3 z6}_A8tnnrr8R!6yI{q?dG)(K6y-d zy+=Ot)Ow3@u8sGnd|4uFtQEWVmV(#!)Vypf>jjSaZFjzGdH+LAt^StiF2$ujs=AAs zU(S5#Q&nblc4b(uz|!AFvwhkx9X{gg|J#1QW&8`3pzBMbf<3!mBvhqYO`bQ`uXxfb z?nNc>X_H^Ftvj$oE4yTR#Nl`@%RSNB>e)-Uz3-jT%$7ZL*YDA_#g>=e8om8?vikeZ zxVIL28=qV*dO!J|xLLU0@1&=X>+PrZKmKv%*WsHgJ?a)mUWggQC2ita{=f71(OZn} zb{0aXepuW-xV}#B)%|6u6W{&#w$-QKQrAK{)n4IAsZGE%xlQ`>rXIDpeTd)r(?r7w zdl_Fgb_q{D$R`*6nqgkQeovVDMb)n+(yB{#PLP}6ce9TF?0#qNj||g#7X0pQn0|m& z=tQAWRK;BVRLADTul3A50@|N8e`exf(y%lzF)}hTH86=XFwj)c_svgnNi0cK&~ULb zGB7eUfJ<*yX7y%tHZZX;HAyiwGe|QsH8r#}O-wdTF)~fHv^2IzGyu|e3O0n4Oy0;Q F1pvnW>bL*^ delta 533 zcmX@jdzyDc3S<3u?RSgS+AbO$yRmrY=c}6UPajz|gK<;Y&HLM1oo+`=%g(NDpE)&2s<;%>aq=!vpsmvI-X=MOoMJ+&Y$=)>nhvCUHZk*mya@ zSk0I>&u@A9vfw!og`3ZnXxPf!da3#UyZLkOsV*;Og=BkW3ds8S`!Bz2d|A`asnl`F zyVGlo?;c>;vf9Y)d#9mI@QH_qBP?T;LnA(|^Ot-r@UHC9cB!)yv!*Y&t^WS*^R%tW zPsAqaAFlPNiofBr=G)a%$Ls607v-5!m zN9yAo_U*qU*VoUU=DI8S_I4xNXG;=Fru=P~aQUM{M%9UZkzrzwbGXfUPNus#eqmd} ze#qa4%eo?Jt!;(nzMvr4%IQ}wmrR-PEXK;gD)qOm$$vi0AIuR3P4CQ^!k8WlDI7nU z@vvmy6xNSzSN}6Fu+;v#`7;v-lZJ(nrGc@rv4K&Pfq|xizHfetOJYf?f`*Hgk%5t+ z0bF{sGOIVEb82Fmxw%QQfrUkKvV~b+Pw4PGp$(ag_3{4A1|moA{}uTjD112M`23CT#?My=-<#eUYRH`OcGLQN?$&J^ zXYhSbXqYf(-n623`qQsHsIDuHJaU93peZ_EzbCRguTA-&@6;hVu9{yux?U}dL#*>n}R($|1z>y~Y1&icYspR#;;&1v(( z6*23ggDy?Eq+m5`-aNnM>C1xWNL^)}Sf#P~T#1gY%&nK2|DT&LZuL?sab9J-)TEh?5;g0iPvyPwOT{6F|dOqL2`VBib-4fT9|G%C<~%Rm{T#orrLZ6J_u;axh*@h}VYe?JNWOBq$>ows6O{C173O~WD|f5Deaat3 z9SKRt|I&=B8ww{}PT5jm6~Agy#p751*>)Lf|C}s1Nw`^vxm}2v5r~<9n0dPpGmB%h zhNXdtk&%(9fkBjkfu@4KZ+?nPVo9okhKrSvfsvsBTzY$T8%rifd}@lBshMeFiixqg zxv6oYnQ>Z5a;jx=lBu~#nwhbsshxriK_#(Vc6MCFC5c5P6-B9OTt=2=W(LMws;aL3 FZUFa+_;~;T delta 587 zcmX>+Pw4PGp$(ag^@0A)1|qHZziYo+tk!lhkLSkXnV+v}zCV3r)eOc>WjF6{Z*{sI zF^%tgLc@eP^QINOo9?as!FK;Xoku?f16KPB9ErQ|!hj>%nq8({te!vQ49Dt7=7%zx z(_hcYzcDk&Os?LwLVCrW!#9IJ{7rN8x3W{de03GCQfd6NZOgiuv%Wm5KjG*9b6Wl* zhn+FzOO|LZbu2NkwVmsC-eTiC+AgI#A!~Z% zcK>_3&!5dYenM9zzU}vfFZ=2@%#3)udTRgw5WBv|+^>&+ywbny#_<;IJ*{+iYRgR;TJ5PQ0v8FtJU!ucO^vxUE&X z?TPVXg(~Jt%n#MoT4in4UX$A+6R)|lZ;$t@Oe-%BZarCrxtspV&8lw~`NOCqA?f&C zno+y4aKhsh5zD#ysg8RRzy4>aH`o3!S#XkYvk-H;5HlkXGXXL4b|GdK$7T%+BTEBg zVxQa^>i%KerQq#DMEX~XejJZ@*UH#nvWWDyF diff --git a/tests/output/test_concat_documents/output_002.pdf b/tests/output/test_concat_documents/output_002.pdf index b9cdcbe4fb605a1a5f7b17d18f7335a5c8149aca..8ffee956957a5f4d4804f64c6c401c6647509d7c 100644 GIT binary patch delta 587 zcmV-R0<`_Zo)W{J60m6je_v07Fcih#{S^066T@i7pRq?X=c`lRmx)y|17z*8uWt*5 zwy~HF_h5jKoSv3)?k|_t;Cp^^S;W%=piZA4OuVqwaTs@Y0XT^*{vN295mvhf;s7a^ z>w<6Cn^LwOe?@p3sNKWaQ}F%f;Xpb*Bhxji3nKMU=B}o*18VdFe`Kepe9Jd+s9dgF zQqq*tAUc|!o=&G{rc<06)di7yD6`IVEIl0B=_&u`H=~70B6LHlGo>_$j;5!l)9IP% z6epqjAW{!y)|qbL3bd;>Mt7+({H2h?yRmY%Myjy%O`kH>A>8l8Z#9aLYL|JxPcgX9 z^=ik+4Wyrjd!G)zf3Uf-+7~My|EYYOBxly|2QxpJVIQMgz-SpnOC0?t9v5o|9J}C1 z31!o42euo$~!2+JA?X`~fT&8A1OW0jq#H#9Ib zIW{z6IAJwrHDhHyAUtC=G-Wk2HDob1F*PwUV>C86H(@wrH!(6fGGQ=bIb}Xw3O+sx Zb97;Hba--QW(qPnHa0Lb3MC~)Pe!se_hkS8 delta 587 zcmV-R0<`_Zo)W{J60m6je^F0^FcgK~_bcwBCWg^&4A`TY^VKQu%fzaf0kU@4-?xQA z+gO$k_h5jKoSv3)?w3m|@IAl2EaLeQP^(W6#9q+oFbG>a2ONhMe-Bj52&-8G;T$QK z>zr@cnNl_$e?@p3sNBQZQ}F#}K~Fk9Bh%HY4I*`4=C-Db18Vf2stqD_UuK=@PtTWxf1hlI%M)!#^JX6Tw!&o_8BUM=Pu1^{35bk#3w;C;wYL{8JPu{!F z&1%QUEhJxt`;hd$f3TTY?W>iK|5QGX;|uG@@zjr|*vIG&e6*bTON9OtkE^u<4qb30 zgtBqAgIoQK*S}56BHgj=TbUknQZPEoen80Scpx-AWZx_+i*dGv8;0aFqab<%(gWcq zCWRe5t=1mA9A7D^j=W3iX*x2>1Gc{o{GG#P4Gc{s2VK+HAH)B3s3O+sx Zb97;Hba--QW(qPnHa0Lb3MC~)Peu&*^``&; diff --git a/tests/output/test_count_annotations/output_001.pdf b/tests/output/test_count_annotations/output_001.pdf index 1b0a3713144174ef98c1cccd226c06392ff7a9f4..3d50989340042ea40c0249927982e8b4901dc82e 100644 GIT binary patch delta 856 zcmX>pa8h7HHeZz(> z{qb)%HJ+^4^jk*o{(h$|*YziyIqtbM{bY`On85jT_eYjD41}Go8XL@Z^PRHw5ikG2 zs4&Agp(OqdFX!L+s8g|j^%Iveo8a{A!M|OyYPFvKoq2CgLiarrD?PvUo$^1=T4XL- zqa9SbVVdls^vl`l*Oy&CyYAr@sA99r#V?PZEUfbV^L4TWlUluR`j^y;lK&nmq+PB2 z^hqy^Z(GE+G__O_~L)qUo zw&=|%2+6SaaCQk?|EnQPs$Pq^E%DbP`L?68bXbZTOirj?Zff{F+qyz=JKI9W(3f?* zLII~Xu`j6Jct~*a2_}ieBd0owc#lq6n0r^kj(_sm<#Db@f2ns%_umQ?t6FHoK9Mzq z%~-KLvhZ@`C3e5ywBs8hl3hJ?WTgtS4}RAbN#0leI`N;c=jFKi;4R_)J}vd{gIDYJ z{&!ZI%s26{#$36En5DH1HQGE{3occ$MotuG)7h9WvP&@9EqV&yT=SZS*E1A9 z^6Zw>XHdxxow)IC$jNR`?^7Dds~gKFbgSQ!yTB_{aEJQ?pH`EQwywjIEgzG3>}3|H z9Sv~|6gY1qlEor@{%@f8HOcvmc^5tESNU++oo}7wdep?mWg64tyVFAWCKX)iHppXS zogKQ7zx&h{o|&_s`Zj3paaMTzQ#RzE+S$8{Om?`%$jAz*`eIbhF z06Js+|3rmA!%M_zj d6Qh(A3yUOkv$Ql*Gm9iU1sg(2ChK!Z0RW}hfPDY} delta 856 zcmX>pa8h7HHe)@nnd0`cNnb8GUt0LQM@fH!thd=Ok4yFUMa^!^b2`4za!cFk)l*f& z`s3ejYCT!8>9>sF{e2EwuIo?GIp(?a`NN{oYBVPW4 zQDKI0LP`7^-p;@CQKw>mW|5Nhyp@}8udG$tYB%-sKc9TR4X*iOvUC!|Q+xN~hvn9F zf5MOVi+7vPvyY4MTc`KfQ>Hh;Xz#pp>lS~BfAlf0tmAoYfzHKUiMJNs|0z5Ff1p_0 zZufZ-cRzU5MVfTRJ>W%0iTI_4>gGnkh+>dh2mxpV){LGGQr9K0*M zz86nu2%2WgaJSpEZ-$H50S@JBZd0T+!g$_Z?R|LJ;AYHMEv;+zk$0-DtlM;f`>ADz z&H|$uoR(+0W}lmES1`-Sy6q{Owo}s63k|n9_T?{>_JxmUbMF=NvXbO zepGJeA9dmXDb};uiP^f>vdIg8qnym~IFJJ36 ztSN7pB@)c)>S*&hV1;0g?RWRsi1Zq^A6;(sL8(C>D)px5Xf1oFxJg9f{kA1V6IvF> zwR{u}*bpiDd&3H!(-U?^-eZ|@$eP7y-hIcX`IqkKdNoU5k(4sCW}nx6XF8A6PuC5* z8P~c_xD)qndz0@Q_Rfk++#gS^@2u|NQ)>y5kgG6myB*%S)LFiZ?fwrZuSTOUQt?4* zF%bvP>6-gGN}A`clU%50koWR)5X<^v#kh$ojFM3%Hr6i3PA(Ep4t;X4N@)u7qtp4X zf4#gq^Y2S>-^9P~Hy5&SFtJ-0SsEA{n@nzClYp@|&u8;xbT&#(GO{$XOiHmxO*Aq| fN=>x1Og2w4v`DltO0h7pOte$5A*5uoK8F+lAE}Cx diff --git a/tests/output/test_count_annotations/output_002.pdf b/tests/output/test_count_annotations/output_002.pdf index 678cee3a2a8dabcfc553266b726f49cc60713470..e345e3bb9f6d5fea9e79a8aad32ac5f1477c7c68 100644 GIT binary patch delta 923 zcmV;M17!T06q^*VcmaQ6JJ^KW+DXz&4@rlfGm5-mbu7u~BccDkD{Qbmg^ojWXbqQF zD@&{%zuIL3(KOn9j)-qxAl~a&NEg$z*7J0}4@*cE^CR&RY?uk5`Wcwd;xACch^fgvh*&F`hAZFcr^71}z54K!&r+UxD$zdn@wxcX= z?Q(V4N1oj0!!3Vv_z{*rdeOV($pw!WN5k)S{N%5WpDY${JbyI1j24$kl*AKA;+xs^ zO&tA8Jl@R?$$SWoC0aL5I}AI&qw_y;?Uj3CN@>TO(8`X|5OF-HKA`1BQ~|>{eK8Ef zvJe)6Ie;6al4*g#!|gr13ReJAfUss9bHKS5cP0@_@=<&iFVhZZ=Pcz-i0u6qW_ngxJcV0aq}(Z=o2| z-7CiVHzmsk{Y_C`J`)kTPo1_j{SS#mJtBuuHah^h%7y^>strmImGu&GU1|eXkZ&Zq z30X#2nOz&j|}Gi?v(MhQ3> z1b7D(L9(@Cz)G?4Yzp5Upc0a(f)qi#(2&UqY&`WxrL8kQ2i&6JqBbe`vSgC$nrV1Q zSP>ZSwiMMU3CDv7;}(#SSta>U*QO=N)GTiUOy++bf-s)mLG5p$s9RJ93sgB8GCKuc zbm=Psjr1bO-GJ62aB466TR|rFqeL7HLcH>8K|MqT6GFud4ZNAc-IinJ(1)TyH(qnj zkcVF5E0Hr7R*-WmqeV_ln`%a=3xu2dvSPvORESrC3kEq_G&DO##_3`ZW2wtvJr>G= zpvw(!oBHYHnf>V(;B)=xvwsAj0S7rSG%_+WHnS!M)d40sFf=kTG&nIaS}-svATLdC zWJFK5I5Ib7HZ_w03L5Zkn;-xH delta 923 zcmV;M17!T06q^*VcmaQcO>9DL?Ih`?honQ#8AV=TJCU+uDi$#}B+91-8XK(yDdkj%$PrDw@(A65|0XGh{W*f0}9)iW@=ikc{E#Ty=i zwX9;iB*Y$J(?7Z6S@3?-R>H9M9-$z&aO?bn_a_cr}l}|`c%$srsvX&ljHQ7`0u}&rptYwGj+4S1k zwdr-UYd8gUNTk-Ma&9wygbQeWHl5MuMQ8YjgP2w4$;Z{PIk~=!Cvh}_Npv%f zZsO~IiO0LyA)fWYu|VsFX@`F2cYOXQS$OT9gw}-3`gx$ad|tbew+@u*#8p;yXt5LrNFFcWf^6*rwFec&`@b_|O(R)oaTp#irReBVMb z=DW8Z=HHYw?e#ZBd-cpj_&&AT()d3lGU*UGjMA$EkZIZn$k)Q40xGRnkQI4hz!LjL zp&PMfv_*gE(0Rkxj7qYS^a?O1p0t?p0zmRs6&c%2mAsg=q>M7Q8h8h}c;@W^-5>$S zy#Vi^A}F!a0z^(5FUIiQ0cuiA6%+;W!b71(u<_gO;q{^h=^IRxdR7}G| zWGOJ-ZAs-I2}ivM;}%e`Srz-Rs7%X{xmn%@n8JTM1TvoALFI4K+$~CjYt$JUHaiDi zirkkB8u>-Ay8*35klbGOw}MUV2Z?yn3-QvghMKXE=~RIvwsAj0S7oTIWRLbG_xiK)d40rGC43YGchtaS}-svATLdC zWJFV)9Win$hVPax8V>vQ7F*!Lo xGd3_YW@2MLAUrT(IWc50IW#pmGdX58VmUHlV`MfnG&W-~GG#L~Ghvef3L2{FvHSo4 diff --git a/tests/output/test_create_document_with_output_intent/output_001.pdf b/tests/output/test_create_document_with_output_intent/output_001.pdf index 8d4419a5384fbb44cff76f0a87e6acd480569717..77196b047bc83dd5197d765ee67f64229bce69da 100644 GIT binary patch delta 602 zcmdljvRh#W6@jR|D3wV$oq%QzAfgg#_9;>e;pa( zU-`_}oDC9_+qY;BtIV$UY`@0eynCmWSOhP#UajS^^0ra9X{^kJ1@-1iXTNN@|H1cF zrg*92DiiNa!M(HQ%{;dxefi}%=T>nAz1nt0?Q-_Z!1XidecNAO{Dwa}{H5{AQ#wms zzhqUVSxufd*RMEe6(2+$>z#&=GHWghZ*H>}nUuR`YP00U){Xqdr=r|5_6q;|lHpUb zo9A_H+1lTC?A#~aXZ*e8PQ7M!ZDQf&jQ^28zl1-%tgvH4UAaj?Gh?adPIfQ#E3+p& ztbg<|{jI}aJqwBRsrI)QM*kIh%^xm#JXmnu<*S9qg(c^;+-Z9m_^#hbq|;^fbXg~l z<=oBBSNptK>M^;_%*&i7N4qHCE|cr_CjtlmRI;rKpVG4_W3ub-Tz$#jz_Nt!DSGxl zy_!56JlJnc%hqZ5vM3@)Xdl}*v;FVYm$mzqpL<<$Os1k`PCCT$0HoUv!vFvP delta 602 zcmdljvRh|6J;O0ntIF}2PL4BN@pWOz~U zm2TdR8B=v^Yg{Y2Z+z#!K9A}9=RbWV7QsucS6X>2-EDN;bgt}$1@-1?Z@+B0|H=1N zws@)MDkJSo!M!u)%{;dxefi}%eyjL`UamW%cG>%7;QqPuzU{9s7OLo7{iQP`H|&y9 zm7%TiT+j1<%PlppvaBo#Pn-ObY2AT}Z`WQlMjn>uI(hxtsf%-79J;|@ewgwZ`Fs{{SEzT!gGGj{5Iw9c`mVDc?Z8P zn`f^2#s1@u&1DN5B^oyr@TdP6w28pJ3|(k zp5Rkla=rCncdA}lP|8aK>80{)+XPux`W{6?2d8KC2+<8}Kb5 ze9GSXPfJ-QHcjB$zhe{&%7DHaV2BTEBg zV`D?}C<6mc1%2QA6qm%3R0RzeDM&@=3HiVQ+R^*Zb0RHh4J^%m! diff --git a/tests/output/test_detect_table/input_000.pdf b/tests/output/test_detect_table/input_000.pdf index 64b8b2d15dbbd33ac00c283ab57176268fadb80c..debd474910ae1a70c3825c8c201830006ab58389 100644 GIT binary patch delta 1100 zcmZn@Y!%$#$5?Mek3znh)m+~iCQVYjefsl-^_2k`*hyHnHIa_`#-*B-?8;CSDnd6 z@9KBwvn`qRXMKO6sS%yLbQABH^t{EB=3Z>5-e~0AyDQ=?=eEOh>tBCwIyUY8`a5y=L9>k}b`;RmR)r$1VPDbNRFM)HjntRKwERU!44M>)zIvrF*k2-mbYd z@s!<@;@K}(ezDmPRQUh*8HF61jo=({;3%=ei^SUoS_mQ>m z#MgeOXR~jwpLrwc>bh53iueBY_>%9{c)R6viM?N0!5sZ^pU2@5Hsx1-A3ezDAHMg~ z&1LUvGk(R1$XeE?mpyhdpZ9p@^#_&P<4Rt${ul1w+}dm|-;~_w)o(1*b~gUA6;W{4(VKZy#3!fXiT%bZZHW;%JD8-!1-zGB4XS5sKE9j1;%OE0uh0X^ zlXG+3hDRm{f19iQBA? z?-uY&3LfW4RuY-rr0x?Prqu4lHSfYd@71bnJH*O!E;ZfMVc!__afY!+z``wCXL`Kl zPAIc{Fy&9y9EZ7%w=d~k_bq#LuI9|!WLJrIb9oj&`I#dg=;>IG8TQ*#gSKkJox zllS{j!TM`uOM}**-?R6}i^eSZSO4xvfB9*5jNxm0Y;4Rq-{S^zcTF$8ELphg;?p}N zdehGRDay05zZUr<{+w?*tCXMp|2tpAtFCWe!@|YHX=z|$WMpJ%WIlO6n-~)B9$Pe{ z>0~Q*bw=~aN$l2vW(o!%ppeJQ1!fo+8ktyNidk4+gRK&|S^ delta 1101 zcmZn_Y!lqz$5?M{XUA1sQk0sQ%T;mf?F`@iM+O3I@BfMx-s(FnCugtV=TKet~&)$3~qvPtl1mipPJL~i_?CdQb$bP+Y zFL&)+<*l_Rp5L9-SGK`5|JAq4*gdoU44Do^{?w5rmWoyHr4F1`i`b+ z>6bHW=aRNvm zyYHPZFY}?~s`mWcpZD6Qy+8VK;_L5^q}6wQlsUhb?fCw$hi|X^Z2!?B+M?p2fJ|{n z)trY0Ie%we`>*cW+xc(tO{K$u$C_UAY4NTQI_Z7Z)$rT|iMGUj&$x189F!)ms$a^) z)?d#5;nY{DFRL5e)oyxiDzf$RGB#ol5b91pC7Bewt#KTJ)( zX`$)be2V+B)aOYF91%rIORq<4mg1lKY>CBeUat-Fos#(Wgs8QLq&PJ_l8Wg2B_$N7 z(WQOGjmf+6Way!8(S&0wgA=`&8FmKlRH&cPGL7xC(nC#u--YfcORO|xd)s<+Idm4R zTcGqLC)6N8^1g&w<9(?O4=e*)=R`klou#wCt#@HnILFeZo{aYc)M7Rl<}&Hd`L|$? zY2>j_E+Ia;a_cMv9_#wV38^`_9h?;`)1{TcxoO^kxveLA+#X!IV7=ne?EcBApT%F> zP80I3@66T-nlk0to(A!WGbcImXtHRoXPoNfk+J;7Rc5XvX7A09e4G>GS*Q2}9X`Q% zXTNGhmdUn^9+Ss+9qUtECK>p21SEOQGs=zZWb)Fi@cOME>bP-C>oLi8aIs3JmePO!Yvy^X2UEloN3X7{BT5p!Sd(SqY zf9k4qg&D2AR=4kcbG;aM_vTiw#de>+JzC7Zs&)nYLh~o8mdQL95^h{Q`t(i-Pw@S{ zb7r6GxZJD%d|C0vl0&C=zWfuhys*I1e6DE5llp%qhYif{WVv%B;YLse}VriOaZj@?}nwpemVwRL@o@$hqW~X37P)RHoxUfhpDyb++ RP2(~&w>02VRdw}u0|5L<=Cc3* diff --git a/tests/output/test_detect_table/input_001.pdf b/tests/output/test_detect_table/input_001.pdf index fa3b7d9b5c48302e5e9e50a177b22f9d9236ecf9..ecc6a56ba7c6a436b110980983b8fde315517f60 100644 GIT binary patch delta 1204 zcmcaBcuR1DFJry2xt$$XaY<2XVlG$3t+z9L`!5>^w7vh+W!bdlm0ITHEq5HaV=OkT zm^0CQ<~BFaIlr2pJ~uw+KDUEq=~4xet$X)KK7Tw{J=yx3;GWj-zidaI^FP@BOY+cJ zr8T88$8s&&6NLGX7zb=S+V-kgA?~N1m(_CVc}=}*l1n;!Z4VXhs^6I?Ua~*c;!$6e zRQc4bUX!Xb#j`KpWV8Mf_RqjpT)rYrV3)?rSs}tXDg7^we%bYI*Oy=KWR`nvb(6Av zw)6CtpejcTpYuoSYty!r`K?*!vGt(aw~jcU^{>}?uYZ58aMP=lB^Q(D?e>v>$XZf& z{NBaex$i%icb=$yf9Ci1ecm~{>tCCFJ@>i!^4u5i`;_iaJ^iU+26=HcjkWd-RjxD4{-mn=4iTp@L8$Ae}9{GVSJ7@tjEQs z&P%uSIUOJTFFyFnj2G)?*``{Yj{5M|)0ugd%cr2?z%!dwmL=Yh+rbnqKEY$j#URG! zdVl`+4`;q+ev!^Ne@066$y0}QG+kBH1BCqVuQ)F-TS?U}`gW;UzQauQR`=%Cb)0se zb!MwC{kr5~Yi4hyrvb|wi;0)mb0W^Rcl{3PS>!4EX7Pj>%=%MLDvHjWuwVzW3u$8HHIPGcK_<+*uJL;Nw*9E&f^Qp{Bp@!t|3RrYo(bcqOZq zHZ<&N>zc5+_FzNmpNtz!`!WtRJ$Df;$~#(amGV-FY^nvEt{U%YDIx-5?)wE~6 zeX3AqJ+FXGQ)|jLQ}LO#jA!`R=UDBZr5=!fX-ml0(#i1_#`8DVR|~F>&VE>R`EGP4 z+oP|2E-B7mEd|^*cDr58i{Ddr(ak(?*Q=(tQ!_3+xD?+jv1Hn@gr!p2Yvs1yT~fO5 zAm2d^IW>u+`vpq)V_WrhaYcvaZn;>yPF(nn)El8U(j{xOu0~{jUGbLh`tkptXIJjE zNtI!rT$b_7m`&IA|CuL$CD&R_v&y&ovP?z(%;&TI-gTD8SDN$WX&+i`{1r%QKZ?l( zaW=->4{NDs&aR0Tj1$lJ!XMUR&v^gnW@c6{CJjpi6C)!dOCyUY0|QM3ec${Pm&B4( z1q~M~BLgEt1Gw~LQ}$>^gUJ)w)ftT@?_{?QG*mDE0fjtXE-=Hu(Ad}*Q_S21L(Ih7 z6hq9^(tNTjhjpyEp;5ANVyb0wQgTX)p>ax*fq`LiT5_V1iLs?=lChDUf(=0>v0UIH XDY2-eq9`?u%h1BygiBS`)!z*O00$Iz delta 1206 zcmca5cvoEnhD$`|* zw4cj-b-4MCBjZlLkKMnp&jrm)g5Rpb1vl0H47T~RUOx2hJG;j1pI)8s`0-o$$K1Ns zjNM&Qb6q^e^%QQXDSwoiVw>!I)^x&}T5;9b3(V&ahM5`eI(lqg{X>)ccXn`B#YyK`StGCm$r8@%b_aI ze~GGcH1RuswEo}OipO&zVkf_9S}P;4cUIi}*!lM^%zd14^`^(_1E+8vgDQR~;d zcz;>*;dm7#{$_1?`ycgs8}II`&nlQJKWDy6e7VT)buouN7k8a}zNa=x>VL!C?T%mm z=6z~=Zoc^8?4|O5R)1-J`|Z%5=C_NtSMuyRP|u)WBd+%T+Q0Wl9;ZDOP$@2W6Yw&1 z+TlHaOrQQYb?#mHZ`DojzV0=w_vf3MEbvlYZzBHG$U8}{?e0YF4W*1LU8L%DMGb!Z z`N9~t)2^vb^utWgvI%Rf^d<%Q6tSs({M1|3c4La<$D22=MgHYHwMWB7Qm54U!_?<8vt_H32B%W$GstDfbc%9avi{or{Y&rGSB=yQGZt&15aZgMxW zUf~UCX_EC~(|N9bIP8Nf^Rzt*s{#tN_gz-hmV1zru}8c0(xsFJ`+#LJn^S$6Z09^& zv(L2hTvv#RkFMN03xUT{YU??K6&5GyuHbVG-og^O{=vyZDQ?OInJ;8bzMh?a@{;bx zx}!n$Nva<^Qrjlonlt@F?2~1Sgq*b;Uu8Qi6$qN8x$9#?*Np@BWGpTR+zMwDom`Ue zgzMgakByfy-YnR7q3?UTZi>q+BcINIEUkHlxsjbhTACGZpY?mEnJ7iwS$R@BZMV#k zy7R&36r5Wx&C_+si)Yw;m~r{D@Y5`>&d!?lD$e}qRO9;3s=LKcF54`YyY27ZsTC^s z-gq1_yAs13IA=#j%=>Su(&D+L(o1)*yAjvv&fE5{>X5?ROx|m&wqAPac{?|1y7U{t zp2>wxg`b2Szb}4$!u5LK@m1a1s!n{(YN~CnZE|kz3tbzfJ$K%gyN`eUss5LKujP5q zf+NipFdCHpKkHh?O?5IMe(wGK+<{6>$gD4 zc-rjWT_5%zm~|(-Wjm|Xe}3&l^$ZX6HnDOsX;>Ip8WjomuXM8N`YaF%xqO z3^6kUgUL=D*0IKB#^xy|CW)zLrY44FX~rhT$w>yuX@+KI<|aTXLpucucwBHpFJpab#q`#4xis-I^9Mb1?ygt<@s;_G*1aZs>7TALzYiw5K|9SUI*5CKl zY?p6!_LeWv+Q<{_;=k;A$@L}I%fgE{UAzY}^iIkzmhcNda--buKVN&eTxjCzYctLH z^XA^DxtWtS_j%QC?Th>ExbEzVIrjVY6880MS~$AZ(7Q)WzAws)EMGSg+22L(1faq(KeF~w9y>+AF+fiF@C_N_-mD%SaMZS-hi zIcmB=&9XUk^>M9q@;z?*u+ zRQj6tg2v)I*>`5CBxb5`EfeDpm+AP(r*@uGSYdIJ?@B(`z%4A1{SVF^N^w&z$b2Cw z^7U-{$xU%ddyfYt=@s@y_DpKCJpUk6MQyo|vzDXO^#(7+dY3QDRyrW@cp-_6CD~!5`qg)Jh4f;wMj_wNzjKG_x77aU+T#y zbXPk$Q}(ICG;g^=Hbbo`+e}3}YZ=b?vCm=KFQpc+{Cak#`8D6FN3(yWZ~UxEc7J!!4b!SW$7s)yZF=MFx7N#hqmC~1+S_+OE>nUhO1j^%JuYV^%T?c8 zlaJY@kHW*Ww)WiK)_>Kf1T|_ z!@lFvCx83Re{%PsihbD~<;maMEO!3BmwL9aY}q*=={9HbO(119?eb}%S&xl3v`sfX zUfIa@KjG|0cJ9BM-?DHqaatOf7#SH^8d*+a7ejD1%d`71I++=pB&DXNT3Q$x8X6cI f8CsgB7?@cmS|q0$BpIX_*(ul<5>PUEEr%2UT}7#% delta 907 zcmV;619bey5yug*jRAkaqSWsB&^^qTIP^xE!fPCHc@DfJ=GO{RaR()0XodUgEodj`|m ziPbw&Rj`yTq9@a9x@*#FyQ?`_wKr1gL!O&VpWq4_zfJ4t`@D7dP9k#EI`ihitrMFs zn@z3rTyK9R`qxK+TbIjtf1UK;b-vs&jbCB@(u&^C4|aIE>I|PPeeXl*d$ZY*`Fpb) zXL{o~o_h_>_;v&w-cG!ej{;DCWDiPW@j_#U*km#BncJZ=`Uc7@6mAS=x*)jaNis}I z(_YgH(;Cy9Un+ z0*iUhRm8IuV8W?UVN4wWxlySgn1q%(^DN>qk4>fr$#l|dI2sKJTM$@(KwUsZNZBf5 zz!JVOYy`hGV8&CT3MseZl@3{Y4I4xAT_%*4CI);%8F9^q^%7{{9QPWxCP`QtiGr!c z!xaZ&yo1Se!UV{uSW~J)Q4}pf)+4yHFqzQ^TpD@?MSb&OvaFX_@3EAaOI%|XqoiTZ zGk6t=$*IJUN|44ipi&5b5xps@`GAVpz|yQZ(~#Lm0XdU&VB`qy-y+O48artWbi}*8 z7BV7=7)C@WGC7Z#wyZ=3xfDF6_b<(sG$UHvkx6o9M>&Y)l1H3Dj0&Y~O+{iK0JGBp zr@^m=3DoKJTH1|ulb-lyK4$kKoL1KS>8#$p7`u~>xZQi878@#m&H+CN>u9js?F*;- zXr;?2^*VlgrC~5=Z9E1Y@nXv)sBUW2#IK_hzp_$AOWn48B$k zAGBSj^_lxWAN(Ypj`tadUY{~|2J}7NNZxn)B<~I<`LW|3nY=f|$=&xZYmT!sbuMd; zGvb`gE^Cgnv7BBK)*PRKHN31j&I>g72WyT$3}&CB1 hVP-O6F=S>rVK6phVqs=BFl9AnH!?IeH#d{52pTC*bhZ<|06hVS_mb8Mx^0c^nTtyR)qdT1*59Bp81Z^W{AKbrph z&hlYE!4YxYszP>hc$wwnoyRkaclY4Uyz(<3zJCF~(a#XBW?`k{FmA#Ef>k^a&p^8o z7pl&Ic;UBE(t>Vy2-dQS(IqZ+5Bu@vhF#G8=HU@{G*Y`ORbzjo*2g?IIlb9nhu*>; zrq{*?o*9H~lypU^4%V_q^kjNncU^jYcP*zW%q(iyLos z6L^7t4MFfBSkeFg#N%w`5X56}tWle3mczLG4dwrkqQS&G81|UqBx}L8lK;~HFDK%$UlOAQRZ-F}8=ZgyavC46IwZ54kjc9WzOksLuuK0Z;;5Su(D zK5N%HvyY(dqsG0(+*Aagd6rF+(sI=F!i+&t5DW<$PNd8ZYgW^t(*9D6qEQX@RVoy~ z3vC6YGLs54H^2m%Ye;0Ssjkpi1uW$S*9p(JfElMjjVWCK$gLKVU=muonCA&kd1`Yr zNv4ZY?Pz}uWbBc^0-6dcf?(U60n7N_vKjm^fH@aL6$E$UCmk|z4SP%TT`sjzHU<2J zD&dAr>m|^^IUm)xHp`euWX06s;hF<6E@AS5Faa_uRzYNsHn|(4nJjP3o0?B5~P2=2GklMp*KY{A5aln*w`&+26FdR zK*1CpST%#YUkMflt(!C^+VTFVg^WxRh6xc$Y{64z94nbap(Ib~{Y$eY&4>ysSC?2G$PvvgSB1(C8nmIer7ZRI}s+3IZrOFf=kU zGC49iS}-svATLdCWJFVmVRCeMa%E-;F*r0f3MC~)Pe!Su=X3x7 delta 1063 zcmdldxKD6HEMvWQ|78P#JI`V-$}Yr_lY{5tsQqvZ38 zDoU<5gDz-gRsT$%bG*K8Zef=Ef#`~>=`J;YS?X5LSBTPI6r~<`sg0H8b&ATo<}ziy zkon9fFTG#1g!S$RiJTPK#ojS*ndIph3d=upbBmGG~Ih{U{SSSQs$qc;8y85mA@~(7rLGE+qwDkp9dA{zslS< z-k)0UU9qR%qH_NA@-q*lZ`klHk~dS=-%)QWwJ+k=!T6=}Yp$O^V;^z9YW3{{+<&A$ z9NM1vsZ4U8ik!H1yTZ(-Nyy`+@S+4943MRQVhfBajrlCgAEMdl8j zXOTje4RXH4G_U6N5WSSMvhm>b-TfbqoRvE>xkcY+1dK>w)n3&y_(@zO&+H7;1PmDJGuooN_byaF$)juKKP*o0SLc zyjz(nR<3REc^1_8jBSQPG4o0tldGaqs~b}HJh6Iul+WO~$qK{8+zdOfItlqWd5eEm zdMbH7Co%10iRDV!`n8R7Yy~15f}LFja>5M~EbSw>4D#$1 zX)iH5mDXS%xb)73%DpUA7Kc4+vp>)247uhbE4R*4;4zn)KBut4;v~_K_Dy`> zF}6?tt`xcT+M=tw_HP&JKk{0(v;Icwt73&Hx7d=%x4|l_^=`dT^9rB4aj#In6wlwM zoXsYeB-Vt?DYXYrRpE6!MO zE}OE`e7+dJ?f;o4e}DF|`=pjzd$zEszv=a?$B%sW0?8(e>92uQl1}(_)8qRO@Xd<3 zE;F4~>VLcGas9n}H$P$FV$!fMvNSL@Ha9VeGBD6o(D%(xaY-ymRnTy;GBPkSG=NKQ z7Gw8jj5SJ3GfPf3O|vvMGfYfQO-@QONj6MMHZUY}L@A(yd+^w4O0OrHwmaR$lvWLu;_ngvzY%7Hj)<-5k ze_KWvQGpb8oK%XkXAUpT*V|9G1mXz6DmeW{#J_(-*y&eD@>SC6EXleshbYfR;uR>n z$A;QtAdAC3ikjmE&p{{K7@lHd&v2Y?ZrlZ4Z=FoI!#&R3Np*iloSyRB<#e$@k6s*( z)9d3S_l%N0in=A`f=&*IUQN$;=hGXy>p7iNXT<3#&py*@=|#yny*~c!J=0C^#Of2N zF6iWd=+*RmcRszLyPlI(XCqEedG?t;!yE8^$HCTL+rj2{5|R7Ck&hq3KC$i2-!(Wc zjLuiWzkVwX`*wd>pRdCwuk*(f(ezK)ejY^MZzoT9elr@rS^Cirr61+_h4}~ZV~{^a zK@>hf6upgd{QsSJ+^ij@riK2b$xB5S*$ZJfYigjXkgU;6 z)XQv%c^I|_roi?E6q4d>ser)8rw{PT^a1p%fR99yy(E9lVUd(llrt!am(Mt6kWF18 zpRFA_t9PKxi=szEYuyrjWmUCIN}E~J3(=bL24M);F(joA)UjF)mHtgJO=k_Te}tqQ zSfdPwQdB~MVj2ji`T+`2E9@((jRaD%hN*(pd!QA=or;!t0#IfY7YGy4;>oNoSjkFL z>qRn+XAOTxqoE=%2o|Vrp;F*vUlSk|I~uZr|1{8=aij{IS@8uo34eg2!TGKhN=s7$ z{YquQG+EX|z{9zoHEvB+5nhOvsl~$-17v)H$r{82lwh-R>_gEuEkf2Sc(O2w(G-|8 zScA5|*)m!7ORVp)l(dobKb{ zP}@>KLnLk(xq|m!3)*OE?4+^K5g*Q4$cUmKv_L|IX;?|LWhH88q+lgJe{r_N8PVb{ zOw|xO%0cXQtY8F6s;IPkxu|Rbh@B1?4t}*vpuw!i(rK(4e&v(-lCKx(c}h<eb!-wo0rV>DzoVKp*1G&nRlV>w}y>IfR}LK7AM delta 1112 zcmV-e1gHCi5`+@4UIBlPn@A9b@A(yV%t|8<-{9PKHAyZxWLC~O>VdZ15e>LMGWq#i z4UK6Oh_KhYijeKgOY!yAQ`HU43A~Nh{wBoVAHnbSE5zGP-03t<`!I)Kn@+?_kYne6#d}f0cf)-Cme~uzmEh$G{8x z2k^poVfrqLekUF`Ylk3Rf@4ReT4y^f%U@ysUkj>euD&YrQqooSg6}Vy8mP<#YZR-i zb+*JZ47($fVEO`bL2x~!l+@-kd!)7%W6GThBw6|Sv0^t)q-+h zjno{9x~v6Arhss&9w4tPiG4+t7C;KtFqyOJ0JLPdQ_=!Y0LrxFHNr%+crvSUR zYL!f*MZ5^PqEeOPx*i;&d@o(xQ)6$K_V z)}ZTewoaDA66;qi1#JX9(yE{WhdHa@dtK@VTa15V3*xv2DkX&+pA`LkfK9AnuMdnU zs7xuKAp$qF*ueWAIc*fxX3|*ci1!yQWa>O8G)F?YZdgH-VO3Yqh?*7n{KeT4XGDWL z*JVS@D2IB#XE`HKP)UW^%j?n zulYHxiw#a2!J7xkoWUUJ4H{)x_1fC*qgL~CT9*@aN}QzAB~H?xO5Bxgnw2SLAGLa1 z_^S!J23>+`3diVAE4RJ=>`+EImEVKK1{lCDP-q-851)BU1 z>-B#C-gC4Ivn&M&0w_2#IWRLbH#9X`Ffb_~FHLV`L}7GgASgsSGB7eRFgP+fFf%hZ zG&Qqa2TK7%W@9&HI5uW6V>dK8GG;SlWn?vFIc73tFfn9dGdMIcJ|H}1V>e|uHfAwn eH#9jiW;0`DWHn_uW-?_kF=SygI5aVn>IfPxBMy`R diff --git a/tests/output/test_detect_table/input_005.pdf b/tests/output/test_detect_table/input_005.pdf index 5b6673b28eb64c765a757ee8fb68eab487af7762..3e4617f9c544e9701f2590e88521cd9fb6031fc6 100644 GIT binary patch delta 1175 zcmV;I1Zex95}*>WXaRrR1p>#SzUs`O}oJH;&jFxp6T43Rd1xzbDsO0t~P%-pqE6`^n85cnI!d5 z)Getl*vS#mo9PYR4e5>Dc}{258|n0%=ONQu>5+7ro{ztLX14K8oIaE4gPj}^y_w$7 z-H_hco#*7##Ym^;JP(;Z!aErJokmB0?nZ~-Nkkn+SKfb&d}6!(@YLwKh+Ia(e}9xk zzFgwVIAV63-yVOcVZX!f%P9I`H+#e5yUFmYrB8k+eX`wNng2SuUvKZpnnZU%$a}JV zA4k6uk5?-Pl84~fF>RJv4q^El%>Q%A3@glML!TkWF18pPgGet3N>7 zC(TZl)utu*%&Tgdlr}-z3pIv`24P6pb0lSstYfttD*l&ZmIW=azolXVc%!X=QdUxd z<_4%><_-#3Ypg3~tO8o{hUhN&Q0U4iR@&+*hqgbp0>rl2ui;&F<9vn<+4Fj$$&Ouw>e3>l$ zC)W2^D%L1=WOd0DE^}VPS6SHxON?O&;<^T=HG_Ww-xU3RfJJO!Zx5UrsNGaRLlqua zwSo`d3f35A-KMe76(0qC$jG9gtUyAAZFotIVN^OK-WR9rSn?1;>I`gHQkHsvZbe+?Vz`^*-XUG9f{4x zh1!2>ASJPnq84sMAMJD(#k;O=uS^;d5U=wYgLtMhcve~NqgmeD?xMXGm$a@nIBf(U zPO>?JBeob5iXA0n9L(*(2p1wsGNZZdm4JMjaqHxnEg91#4ULC?ymB=ylG z?QQqbPLH|XY%ocu4JPRegY83|>Irswj_ZHW_T#Vl)sZKcjB^sy<66=uSA1pi(Q=ZH z2XC{mzg0bDsW zVPQ34IWS^3H8V6hGBq_fHD+REG&eM2V`4QiF+LzXFgY|~VKrenFk&|~Gc-9eH8nRi pW@2SDH#A~nVl^=_K3xhvJ_>VmVRCeMa%E-;F*!6e3MC~)PezP(DdhkF delta 1175 zcmV;I1Zex95}*>WXaRrh0)eA%*}d%|?OyiK6z;iTB-&;niZVZ%{`?Lt$&@xyLAxnX z2u?1qh7$G8!y#$$2*D~i{Y{8Z|3cX7XGk}zwAFc<_hAmvCZC8`plpi`wf8`tgf5Dj zV~6KpC)*f4Vq=eR^fx!{0{e^88F$#yxjU)eNT=sK_c>i`a6o@A38(3~_{2M-)J0LZ zq`F`yM?|ltH*`0oH+JVZom6k6({rAOOs}OErPK6W{N+2dwR2+iiBuo#z+wO)+!Ox0t1NWo z5}*6wv;Dk%Aew*v1>3Kq==<&L1CMVe!>^Wp^h@bSo6Uv!N1OX#eIEr;cn3lJF3#U2 z>7T^o)yg5teQ<24(#tFdzx*}k|D~jw7W#`OPZeEcErg-h(m+)qS)-Y#mst{i7`6wd zz}5v6lHzKqfWXIx5Ae+N0razgk3^EaB+X%wlroeal*E72SDZ7*rY@1s)=r((-=NHs zqDMn(-4c9eRkch?Yp>;nXia&8Fa+!vlF|p-v04rl_e(L$ye8OxLQ)Q_QHDb)Dj`8J z4TMvD2Zg8=))m!80x4O;RKe;!(28NBq9r~6lo`bZ!bG(AFslnzveMLgkxUb>>1Z@m z>#mcb`MO(B8S+C&1!X!phVA9|iwDrxF$kN z5h$sm(zbF@*#RJSIbb;X)iQwwUfa@Xt{Z;k&V0$~MRs1&)AeR>wz6JN#7`#@>$MHF z_dtId#V(4P+a6uC(_Ivwy8L)$(g=q*$Y%^jU2JgL2);bZ z<_tzzZ_ujVV5jG7_i6nS!7QI9nB^}Bx|eo?+3VSXA8@^z;K<;B;QtIdR#qjcizaDr zyN`By%=K!6NjhyXNnaRjUusoPu+wu~hqiwo|IDwBJUM5aM?NcAu%u6}_`>AFzg0bF7< zGBspoHDNI|I5%WwGdVOeV>w|mH!)>pH8f#2F+LzXFk&<^HDqQrVKFs0H)LirIW#h3 pIbkw4F=b^nG+{R}K3xhvJ_>VmVRCeMa%E-;F*!6e3MC~)Pey}JEFS;> diff --git a/tests/output/test_detect_table/input_006.pdf b/tests/output/test_detect_table/input_006.pdf index 7b35a390146437b818eee391329c53e60cc756e2..07ee87e526d3d0d3d85e5511b30e8be863f2b97b 100644 GIT binary patch delta 1392 zcmdliyh(V2KO>{jDJZIv%QOmGP^W7k}3KP?xyp0pIzI^1ViGTjDUzsZaD^G`lJU*(dV`u#nBC3-q#<=zHQe$V=(M*WX;|D*(+=^tw5 z7k#v=zY}=yUrYVr?Veu_Cw^@DUB3BYxcB@$8nv75uRl{SeK+s>_7v|XX@w`YH}~^5 z-|sxWdMdMLY=KOK`X3$k?SELG{Wnc-N`16?0YB^KO=3+4GP4q5uYGd+u^)muUsF{>R^uxF{rU~*6MUyC&u`9} zdp7>U$@advDyxq;e3&WTI)6%;-(_ymrm4J#Ry>@jtoiYXiFW;pp8uL^ox#nu>!QP$ z@~tAB;>1h2WyKx5)$$ZpujYH*#d(wIY~|tIJ>l*Ntj8zIp8m*`5L1@gYapl_cV>0Z zbDQZ?KTOJea-}cG!BJj7$H1`OAvNGqvTLK*AC;GE|3nXH#VLhq>=e5Hal$n7f=L$l zLrc}8W-|Xic&mr|)phR!ha|1OuGQg+O8a^s*H)X7NRkT80zVevnlQqd}t)j2BN-?Zj#@u)I{!h-5*I%Mu zRmV;X-#7F6nz)|gfIYWwXKNqysfn1#5t8wvp6`gKmD}XHt@=L4S6s8|3Xk2mN9c?c zPx7V&f%6&7doP9c#BEu7IV%5x(u^D0i!&{R-^L-^bR2pA){FlDJZJa+~LCS7(`<+!G3Igx{|` zvT@-e5zgcF8d6cRyD$8y?%e}pJ^Eri? z`9iz9^?CaKu9~uO(bq+}N#-Z>e_pncGWP4d?6krEwb02^^-q}lCvA7LySGcl-^R=C z?phzaFX}%HI>OZCe@1>wc|NJ;P2i`KWvQP!=i9!YR`crl>T|k3=gt?N7yYTae-i(7 zzlwv`j$d7KBDels?&MV7;O%$!Z1)v&pOg7#+sRK+I+H)-PJSw$(A&J-cUm~B)Vun> zYNzYVHi|MZ&{WX(%};SjEJ;<+aIrEnFfufN zOHbzJh-NgKoX(-nXfe5;!`j+h!2kpl@_4zx3n0Hfb}y8r+H delta 1407 zcmajYX;{(+90%~g10+rJNJ5;pR46U~{6zt6`goh7XwQ?WO-kfY8{(A_@{BocYNk($ zXoi`?BhL;{n`gP&%2}Sv%2HDaFDiA-#3NVRv%T@fey@Jd=lgx0uhc+haFYUo*a-t6 zCIatqY03-F5h^cg*H~hgPvc{^6NL|}Tm%{V(LvOjvJyjVCb8()UO(RSgtn28wctSA zEZ(`vhn|>cWu6gp`=d+d;EaB|lcD1R*QuId0 zRrE)Tyk(+FvEeNsevC&Na%P zpo94pA)<Wv|xq}tEKuUA$f0IvLPC=lzuXG2_o2kE+1_TtvJbYby%>4h27Gx zaqF&F$<3%}Pm|qMU9WW-JCB~x9bsNDxJ`v>_V(9uJcBNRb+9UZ-Fc+>)E8E#^b7*O z|0RrOI_y61CA~8hrX_?2q&7hxoUG<3ta=tP!+jymjnT7N!6f#r$DtbI^KSSMnxUWG z8Y=2(kl^8h|BusZHZ%wx`$+hMY5sk@GGFX2BNx-Kb7AL41DhK*fnS+lO$qjprwi5^Qd)$TaT} zLx4;a>2%#jGs%rLc+$_ zw}&s)h;KNy$#2I7aFe^=p?#gdcA8L?X4i%0jedOj!m0;VmE3lgBep3d4y~|-ubV=w zCO)a{UDVnqyn(>K+*tK5+}x(_6XAzo#L^R!5@Zt^5Ga-ik^nn90-g{C0Q<~s{W)}x zh$MzN*2575KpgO2EJVPMLkL1990MT2uNH~P0r6 zx7xJlZEwTT-yWYnT4!%y6m`E*xP*B}4!mHE!xzg%@T zAGNK&9G*L;S-jo0itW_3h?QB)56|R=Y$}#2(7%?pG*EoC?ZLDi#r1#VE>r~nZzvB5 zuHL@2tnbP<#rfsMR<{m{?VWksfBnVkc`twVdX>4Z63gD~{3WF-_x-IeyY89J*>>&R z#9MYxif6xE`Nd}c{J6#cf1gpvvf21;+7-VwXZbEpez|pT_T|@A*9$gXy9ZS%9OL+U z`^zc&&RZWXS5pd~JI$Owuikj$&rPvcGoM%ep7`Sa6sGN*(_hxj`SZXc{@sjY>kaDP zt@!@AS$5vKs;8TM@BhB=Wv_)@(Z6$Vj&H@xiX1{#PnJGgB$4jHbJ!rhnAJ>AVWP+CrS(i~ z{pI{0PJNa7vbw=t?WWhJB3myn#+l3-okxwI@@&)$dStwPrSVU;Q#vAfJYu_)ew^Bz zGiS;o$J5-Gr9Mwe;D{(vT6#TVvlRc-XG|mR=cwd`~ zNY^8-trHIf#T8Bckib;qWJt;#X_ai>l2eR_G-6Wy0oMrUqg7^%^hZqV&`5i z*kc-b?2}7~kFMN03xUVFK5;^74sHi$1ifMXz6~`UuKH=l3*e236<$8mcqRN)wH`kcCl9;_WKk{)-jAxzV6Ljzd z=bink5m_c>7bP-}?QXV9ahYV`(-Dy5HP0wFvXjY6v%>4Q{@Q6G4;b2MI^S4Kf*;m!B_`T5l#pl`{##j8ickP%nyD!nI zRR8%h<3}ZrPw#vgqcitIQJ$6kwa7Q|=X}#yrF`xG-}xdgb7{)M&3jl5GjduQm>3xu zSsEEk?qKUe;_-93PEKHtL=$1>h(Hrr%Ymw9E}Hx=PE>i9$qTrifz=qA8X8+n?&lUm z(y@*^n$dhR7mpf~q2**F9_xAo1p^RJ$m8V#GYkw(4U93wjLeKM#EcD0FvLs@%rL}E z%`xpTH-d`QBUx-=fuY&Rz!bwVMn;B~=$056W6^7Bis5J@a}y*-mlP#V&gRvNHBGTd zGfguwv@o_XuuL>JP6RqHIVsH~*(5D3Da9nwPQk`9(K5xvG}+KH$tW$^B-P9~Ej7t3 nDJ{t|#VFO-z#z>omJ3{@CKi=c6s4wd85{h-+`YlF@N>UV`!3=0o$2zw|ATEU02S#d~T?9 z(9QOmJY(Cb^PYddoc*P~-k3w$f6ZRy(C(=>6|0Q)ZY$5NihVETckLEbWo?soM(wt_ z*S@LQ-0<5 z(SwZs;d?*boc6vp<7b?REYQij3J*!2|9B_6;Lh!p^{;pR7w+HO+H5Z0l-%gmZ!FWc zHvaOj|0*jCuhpAGFS9rmQE=CBDPyQk<-(mOj!Oz1HqbGPY3$|hPz~BzA9CQq$9Ifz zJMT5riGDbt673z9#SdIJ>eFBwuBBxUSP!7a+~4 z^N=;%@ci`#&EV=}D&U~JsZezGpPWAH51tlg@LEBU|H0)~Wny|6- zT*K0u>>Dg~*$3vNyNDX)^@?Y0dLy;1?NzMalxb>=HO`X7XOC^=+*07j{&cNp@U)|g zQnEf49Bq_%pYW;4fYFHSTF;|^DURL~zOua2@kujbn%;KLQSyGx9G%(wBi?VE65&yQ zCt==#B__`;_jFtl5lQk;^r+-rA>!m??HbFk(ZRds%q(NxowcF?2A;gi>IMJBk{4dQ zvB>aJPdWSFiGqb^4Ah)9YE~TDlB!yyvE%{g+x;QBE0v<|Z1m(#+bnY=>uB;h1;^G) z-_n$}>NnghI-vRUszsw!^R}h2>t??>GWX|<+iBefcdRAd&b~c*g|n)p`n!W|nAUto z`x)k08+O0tKD;;T_EfLMcAvjJTFkzxcE#`F{1e_q$0Qc~+pxO(^v;(O%YwfbGvm+sK0j{N{Rb$w#^LbG=ksU(V|u4I<^JZ~EQc96EsQJ;jE&8WEho3L zbs_N%vb#=>XOBb?nTx`6oxFwvRo-=SFlPjsnxCAgYFsAI=XwTKV`yw@Xf(NxTMS9Z zTJC5@i^-fkYD`83lMQ*SMGX}UKtLgnmkZ1=Ff=tVncT=DY-@}mV{BlGA!cG=jv;1h zZaDcO&;(4gEi5op8yT3IpqpT11azGuudpVjYEx4TcNv+Rm`;x6wT`t+HZw3!vrIBI zOiMGdFf>auN=r30Ff>U{F-u7_HnXr(ut`iwOiVPeNJ~yKNi$1KG)*%%GBQgBdfCD_ h(ZbBq$S#%(Ts9^al~fd^rg0e?7#VS?s=E5S0RTCs9IyZY diff --git a/tests/output/test_detect_table/output_001.pdf b/tests/output/test_detect_table/output_001.pdf index 3636dbfd868c26ca2abadd7e848cd58db7c42b96..389bb8e6bb822f85c6701183918f76de5e248c43 100644 GIT binary patch delta 1197 zcmZosX;IlQhp}Gr`Qy3j$=2Tl_q2xpWjpem|H1ZOl84SJttpi`mTS?TAk2TnIAGh+ zwpYapaXj9YwBH-T+-QVd#G^N&P4H&{izm@`l6)Dr)Kq{CX#|+-s|wlvwztN!;A5z z)u#%kZGG^2avNJn=aZ$+7R^Za^f|o2wt#h;p29?r#Y>sk=F8nXYK`1>hkbgpfYb?;Cw|hSFf6F+g|J3YcTTX>SyDQ6|Q*}Y3A?s+Ve2?WvS1T5;$%Y z)+;ULzp-H!zv%a+60Vc2Zn!HNvd3vncGfadbS&i6aj#|X)DXEUnx)*hbk7s5hezcM z9$#5uu#}r&XW&kS87j_E?0bX<s?XfAMDXGxKc6t8 z+ov7hl-WGw2@283&DJye%``)n&!V)>)PKRfC7CN_kY<`4;uU3GU~#oI-_d5cP}vfkFdxZvQ@{ZfV=y1fUzOv9q;ZL@ZJzOHGO zZ3?vUG3csSd?B}sE4D;*+nQS$i+{)HtKBfYp?bsoMMUVTjh9{p-j-e0|Npu9=c>w6 z7JO=NFPur|iK_ZH^W<;iDBaR~H7|TU?PffmJ%8GtqQ2mKi92B};pwmL0?8vgZ-F?; zJNK>S_|JCj$2O%sdKX^Eui;>;XUdDnY27Tq`izm&(!j*X$jH*rV)B2sE+n2HkIUq1 z>``bUwH%RXBFdcTYEE&Yt0~|@S0m0Hi)7A!Hp9v5xKY*2Ly{Ndah?2^2h~*9$xC=q zMO-F(@jcT3`Nz=I(AYA{z(7+$-#0(SC9xz`LBqw$$iT?Z0Pfw*5&Zs4&dEk;DJH2# zsix)@X~wBZmT3mbrbelTX^G}WX{i<_Ms^A|$wn3_29}n|X(=hm$)={3mS$-NW~r9R RW(LWr7RD)-lV1r+0RZWc1~UKv delta 1197 zcmZosX;IlQhp~QU&6m0A#$|7nE4bJH;^{aqe<1&>am#Gih}RZ9w+r|Vs>yYvFL)y< zy=r}9#nasyFXzZraG7oDyQpjSjpO*sXKk?;K2LktVQqDJ$Lf&mB^Q(D-JWyK?8d_F zpW0vU{BaE7QBD0@_W#2DtEV~(_#fQpy7YM@-{nu&r~JPzVygCQb(+8A zxlLj<^_MO*XieO6B}U}4PG_dXHuiM~uCb~JWo`*M@Zj>{>WXK-7=A?_P*=Mdx9O9C zx0m2a&M8MOo4=Aw3SM#~Jv%!6Bioe9pbC?S7qcE1pWjp&6y+}!H{;rj=`79%`s#%> zYY((tty!_7zAMmVspHBY2iTQtra^SIrM1H z*rVdp(9>nQ+)AYMqEO1-26pbrlD!9(E-VkYZa!b#d;5`JvfiCbk1&gAdSw;I9VnkT zbCMU&N|u$ApEIl0Ti=_%WrCpRAp=FHPR+_wTT)fIG?qTlJiFf{>QYBWp}Ly(%(q1X zyJh_?nngsts?Ee_)-s;qW1llC{;co{^USDKRd=6=pF8vXP27>!*P?dZEBPL_sIg+N zvf#~tTHcnxH;V$d-WFdUyXB(qly|!ls#T>-c6L^ zMEHe!9>sI)l8L*?K*McH&Sne-bk0M(YhLu`E|uxzU#;Tf42WzRe8#S zZ`qfH=JO3RUj9s1dw)J->y^sS3(Yh0^XBE(MSVJL>9;qrAX+eP?#gl?Dfm3A7)bR# z{k2W$k95T2+g%@aIV`TDJ$^Y59ka&VTE|agZ zN1=(-azvtuD08B#ImL;trhp4wjW~BKk~#m`3@5MSMpZKpNnVi0b@E>xR8w6iFX2TM zahdGJ_e=xiA46kPL*pm|15E{e-~1Gp#FA764HqjT10zENxOX>4@cT14o2I3iCYzb3 znVDLqB$*~#nwwgrr5dJ~S(=+!n5Gz;+9}wWC7PR<8ylJ%T38xd8l+iR8kra-TNs<9 QCL1N0rzWRNekCXc0I=-?egFUf diff --git a/tests/output/test_detect_table/output_002.pdf b/tests/output/test_detect_table/output_002.pdf index cc06d2a4463d86cd3224e6f82ef41f873a4ed8f3..72dca73a2564dd80964d6f41d718bd56e1ee3dfb 100644 GIT binary patch delta 1215 zcmZ3lv|ee$Y{vT3is`N8a%tja<_~)2++DBy<16zWt$R)O(m!2gekH0de{l8?pDkl* z^qP=4%ny&O4ebiv^&n2?u+w6_u<9n?`r^BKFRGINH&|zB-hI31l!v7Jrmp`|96*{gGIlaO4OG=e*xo=f&x#{xQ5J}C)&huvb)cY@e{`2matiSK8 z*)HGe>@8oSwUH;<#edoLlIu&ZmxUK^x_A#{=$({bEa4Y^!}WRkv?_c18xLQu3bu>>b+7%> z_q5H*pUc(E&%HTTZ1Y{p=KHn!^8DkQ|92k0dFmkd?*}s$UplPQUiUNm)PGC2-idYB zawa}d$UazF?aRAD>16R)SF!30*&6|}+?!8>X>90~>!VV};&QXor zC#SNs;gH;vBad2-@oYSq^vHO-bNUzFDUlj?B+isL7Mz}(GGofJz01UxnJ%+DD6paa ziHq0zjVY!wT3@Fp34D=Cux~vgQnAj5YokXC%Tdz}B415il!8OTSM;)oeV((rBVGGI zOYq`DGprbj76&;RaO##mi#(DnH`|AQ(#s{+3rwVhwkd3A*wxTAVN>X_2GyG68yt1n z2YQyfhz8{~hg+q*G|k~TTRt-&YL>(Y-qa(e_0re87c>^%$-Xm7B{5TlYnd2-xJ<`K zKDG0l!U~I%d{^?h25w=A?0<0XP>P#!LFNldk*{alPi~4!+Iu`GNw2UsvS(78<@pDp zDr(DxoV6UKt~Yoox_nu-;u*7660`T_M?TJJ@~lsME;UY6-cjFea6RMA62l9E@4rQz z=+H=#5UgK#;)zY#txZCbPl7(oxVPUV`ch9up}X42nX*q6rg_U1vKeYk*=8!*S<7(7 zk9`i?ekrwp<=3+_&9C`ZJ(~S<#@+6MsL0RDH&=a6dgEtRvirM(ZkX0NMthEI(;IKU zwO-yEb#$rM-oE>BnG!rv(*2I@aXB+tuKMPhe9SI=6dtCPv9;&+w*EW+IjwljIJfa$ zTT>R8xwMP_mfq!GXa3ITubbp|{CAJ@`s-{b8ulHRKKa{k{*${8RqV^|C{O<0X0h}4 zz0|XXWy{V1Nw+zZZvrW^X_rsWdThL*ZMy04%0{;T31>gDFZij_z46(SiVSadI?cycDyB^p@oKkX&&3VIV_V;Y*?gg)V|1!T@v9x4+@YIPx@}FX!mTWo5 zwzu=P@A|&-JC{Gd)_B@8S?^|jx%Do~&pK36^Q+={-(~g7FMa-#S5^Aw zeKp(VTb);}gF-h<(Osl|IeS<3rR?3SEhD#@2fcEhH`{0a11_okzOP^W-c$O+PpRmt z)#qmi*9yaXkWjnUIjSJcn_@}P9z9mC%E#DAB%?w#i^tJw95XTEOj zd*_$cn{Q71S-n|0z3Q>$ylURQYU}!M`FB75Kk_)|>4VnVf-`|H6Q?=v|6}^}zs%xe z9`@PWJPIakeXwiqGPaP3Pj)_2l1}sda@Zign01?;!X%H)OPSdE%lS7vt>UfHelXE< z+a#TM{z*X&o7h!1RxC7h&e=5M$CP+F2R)i8nczJyuR zeJO*-nt`oTqCa}I>+EgoUHDT^*vng(dEdgG9clH4t2j*x`l@@QC#&f6x*WXn=wTPL z;k|=TEEAbhLe^+rU8vDDP2siRoyZwyGFbF@ZJQVE`)Lq)&3n!F2(L4$>kPXCFBv?S z+|zaBNl221s>frg0L_+;dm>kB99(k}GQ;L%o_MpkVUDMjK@rRMe8Fc@y>m_2tRCHs zb^UnV!3&-%#os#%I6f^S}$!|rnHg2 z;pWSR%MZd2v%LCJrTg~SE>Hg&WBJY1f_~cB|4PE%$MxLxbieb?HlUkV^m&7POR33? zx8GVX*KWC#I;Bc>|K3Xm5?jpVn)@m?rV53aZ_Rpi{bFZ)8CLgLADxK7^79*H6{7lr3KnTr!u-gWXu&ImL$;auoy{&B@1sd>s~IC%

I}W&{WX(%};SjEJ;<+aIrEnFfufNdv5b| zK5M4f6w5?I15-=WRLis!6U!7M17m|^69bcE6Qd*p0}D$NI|Um2V;v{ZAG#FWHTgOp@r3!_xKSS~v|uHur!qLPZD)HE(*b2D=;RaIAiHvm0`3labT diff --git a/tests/output/test_detect_table/output_003.pdf b/tests/output/test_detect_table/output_003.pdf index 1326a30f8532c64b02493d47057ea83901436799..f3935e0d445132c39178b45b7ab72c3fbd969415 100644 GIT binary patch delta 755 zcmZvXODIH97{|MlhPjv_MK(+#3&nY#`$g9VWo0L?Ni)~njgrSKgqmzDZDeOpNl8-HQWoBu>mFxuI^Xa7|KIojwkkF&_PUJ#f=tXnM&ZfD?BP-9`21|@ z{G;Hl{Bb9<7AOfc9vEb`czyi6M!jw=Pdv@G+DrEjWx+*$dA&ULb(ap+wtp8LwRQb- z=}CUN3s<@9Ez&>ND>o|_GA~(oMhFliga8J08=Ur3`)0E`$nNx!o}3OJ355Kb?T}y7 zX8zS|czWChv6{*4@{oPANzpt%xzWgE{^O4ebIgz$3>SNP%!j)Trk=yqhEPS3`g$2f z-zPedZ~it}zSg3?%mJ2&R_CC}J98zuvSrIuTS`hgkoZ zK@UhVA^sthSlZf@S)R}-wNij$z<3;iK#WR}0LmCoB>Ef_$4r9bI>L@N$fN^UiX;Q! o0!SCT#7Xoe!D0+a>S8-)+O|28iVvqohm)>JCAZ9~s^+$qPyNQkvj6}9 delta 746 zcmZ3cv|MRJG$WIt!RA;-14hB-tG(OzaPB#^UU&w8ERHMv?M=9)};`m0zVd1PkEu^@>Wt=- zh4`&CEEEhtKp~Hp3(PPuG&M8C5CaB6BEN9GnGuGJiJ1w8n3<^=hM0u`rkJHUhIvMY z#+K-Mjf@RU!D97D&NMQ?qS?$C!#hS6P|e7CEioNvY-nVRZm}^i1t5!YfI`UF#KLHD zpMZ6&Nve^#shMetxuJovVVaqtd17jEsa2?CiLTOA?DpDvDCmxQxwBExA-xUH#nvjPS;B diff --git a/tests/output/test_detect_table/output_004.pdf b/tests/output/test_detect_table/output_004.pdf index de449d640ee67f95b0c15f050abcee8e2197cbf4..fe1fcddcea30459ada5ea8392e80b215628dbcd5 100644 GIT binary patch delta 1686 zcmaE-`c`#AG$WI_<>XjKSth$TlWQ2w>nG%dd#>KB^7@d>qFgf}eaD-&W>@5xBW1n? zUXjtS;Iq1U?1PAOb=&2d;>UU)s$QoYl6_bBPU@;;Vb!VP>6eeP*;W-=_^t2nzhmt6 zOXJnFDcn|;3RR}I_viZOzgYMD%8GLxmxJfkF1voIds1Ol?Vsn>%Vyu}yvn;$@5Pgb z7gxX3*Oc4sUATMRaGwlvbf2do2@LK%tgU|GZCbl1(*e`#`ZsXm1_f0MI zdd`I(s^34gt#U?k z!fy%Iz#j~OKlC{7A3gZ~$m6uP0;$CXZ&qA7ozq_VGyBZ{`fNwjvtPq~J{oPBZESlr! zxu@o^VROzZrk`)#T!{S3d1{YFmC=?}UswGde(A|!Iz!Qv|agl@0I_`qD12~Aghp02TC(3N}_vgLqq zgVEw04l_E${L@0uafQwB(w~%RlWifzt6J%}!J(9UDwBG97lY=_lM_U1E;?u*o2XTg zcC`GC${$8Qw&%OOG<1C#zpziWyqprr&&dD0>e>#|RL=^%sAXdO!8{Y{3z;Wh?cmfn znD+EW`=Z>amNnrYQWAw0YZ_#3V9TxFoVw}F^oadQnwh#UCx)?3wKx;WdfzoOE61=) zx8t$YiXf4qnxK-;jAk1f_gWe(TDWOx!z_z{17cIAd=@%}cUZ%xnpz2dT7 zS9JOr-S-XZ;O%v@PfHnjFL3D=r^C6z_Y%{DrWL)R&0Jt5a{hTzTks z%>4TE(|_sMrO$EQY^SK3>AHEJ!OsHAlk4}kAKmk0F>C0(?B6OgCjY6LId%T@nmtFv z7pv@Ae?9-4$qpddVSMl2_1EUfJ9natjZ-h&C^}$R!MsNnix*z7Z5|TM^7M%$;@(cmw-B> z;p9yM*7fEJ1|Xo2$IAs~7#Nxv8(@eTTUcUlh?yE2V~Cj>W9qelnOBdn*vP=t z6kRhgmW(jOj4doM#7wd1H8;X=ppgZd-g=;?jSY;=&k&fNlGy@1_qNwszI8Cfkl#ea!O)aiiu^iS&E^# zS(=fZf{mG_fuU)dk!iBAd0JAkg++>4T1s-FMOtcdl95SDiiuq;mz^C~aYn052eQLjV8( delta 1624 zcmaE>`c8F2G$WIR!Q@y*S*FhqC)Y5V*9+u_7p}f+@%E6+qFgH>eaD-&W>@5xU#h)X zyuvc>gG|Y$-iMlI-*}e)e0D7M!PjdaTdeOqzGJ$|_|cas&-Ipf^HzN^duXxO&aUXZ z#=FHUqJ#8aJZX4w^-E2;-QI<}=LIjeQugz&{5CVrTfgi0%da2jzn_`1S9rB_Q0#@1 zj2BnGtpEA0rpme8R(k4Zy)mwBGk@^cuX*kMvgWh#DoXs#%JTLtwMo18?$0iW zk(j%_<$s+v=kKz}`Rfm>umAk5GvgQgn|-{C-j`2Sx7jbrdtc}8i}+*9 zzcJ)m^ntPI!(FR7@nidi`)6-;o^tNs#>HOxn`NIpU2pimem(0|lk4%Om6|V=sug+C zeR)HkPP#g)Gi#=y2Uq5`67H)G z%oM#}IQav+h2)&~S_`+BuwIZ4dFC@Y)t1F(&g;m>*QTgG+?g>m%Erggq5c@JPnfdW z0+!iRljXa%WeRSJJ2<)3vuD|XB?qOp{5?DEV!7^kpyb3Ow=A^Ws_d8%Nl_Jv-3Rc4`_^mQvy26QXfT z%Y~Lgr+m+HEz;Evbkt?l{_wMVv+B8yda?4nQ?qUa@+Iw0w^R-Ya9w)$v}-1}!<&)= z1s_(YGV!L_PMftc@5faCXWskbRGw?vp4)bB`&1q2PV;z`O=sF}B`f${vYTZR|9eud zeCaLMk84ibukVq1xPk8yXY-EZk~vq@-YuTJWAocZbDurmqGx82$C59n8qBtMiE+l% zASnF&YsVV^}C>5IH_;Cg=f81Vf41bux&G9ue?lrxL)mr^cPM(-l{cgUU|Lw z67sNi-TD2`y=!+_rq6LJR_jXe)SmUV^*PgT=w^6wBa0ZY z8&1B%9fe|!%j9MrbP+9Hbdie~A{Bh-YUKH!flW3vHZ?Sx%qJj*WRI>u6qC8ZA&-{}%rG!CGd9E!GqyCq5Hm40!VohxHo*`xH^J0v0W;4GVX={c zsTsOvBO@bY3^8L1%gGA`g>5lan;T&`$;iUO65Rx217q{aAAu%dI2M>FFg$N;YK##` z#^wg5lO2VG8OUCmI=BT3DE-Bv~dI8YY>VSXh`RCYqT8-DGB`U}IsB zW?*8HVriLVV4P%PY?_jqYLS*~nQCd6W?_+HYGN15WoO4#T#{H+Qc;we#${q?Zo;Li I>gw+X0IzdtNdN!< diff --git a/tests/output/test_detect_table/output_005.pdf b/tests/output/test_detect_table/output_005.pdf index d995818684100909d4d4b7416591f4e2439cba40..3779c93a22976d0ce4e8a1445cc1826fb210573d 100644 GIT binary patch delta 1392 zcmX@Dep-D)8Dsq&R;J^>wpHJDy|wqv!pMsAtjfK)Vv97oQ!dZn@9b@~v^V5J9+!yI zq|>V>y6pX2;1OBe^fjyY-)w>Ze^?#Y&sV&;ZcaZQ`jb5`tS+hkD? zc&UkP4~zB9V=u&{t6L`T-X1vcW-{xTT*qdc>d+9Z1wD49wp40*X?g( z>=QGk#CsKYS&_?^v?}Lv=c?rLzRQtc-K=b%SDyG1R+VVvd;Vy=o$*}@^|1M#Ul02A zb=>pGf05^r|K?obrdLTzE*H;h_mO`n%k$4~@nZY(#fRUkT#|7MzgN!_leGKqhbu33 zDeUQS`TtIXH)f~H^ui-=EcV;h8}#l!{O+{IuSE0e!;g2L{IGhd{J(%-56h}k|GoZE zw|6i9^~3`9#1D3y_l_T2f8_DiQ;KJ53f=^~Or6#o|8Lf(|1k@W#nfMWv+{`RH79|J zT;3I*+OE$!oi$VSVS8fv6RwC1)Sxt(G=R2p^B^}SQ z47sC!)Z}YaLj7qr)(=sVjIBDU%w5?DOkZW6YzhhqU*XHV=7DLr<$Asb)#a19xOXv5 zkXBVWsIsNRczsdaheIJ%6Md4`Kg}?i@}~0u)2n(ht)_(bE=KL2CpU=xS+qd0bT6bqKeULV@yq*)O-^h6GME2cTn^Kgf>jrnXYx5oX!87@K3+IHu zja;joZ;I(UUem7FU@-F{#~woy_T1XfshdjXN8C@onQ-@k;A$r6sAqec)^9Q~ohlK; zd1)702$$mWdUMzP@&SUn+=Ov%H zXqcPo&)Bvmg|$?<((!%#E!|A_Ejx;Xubo*}G~u`HdCO)dQL}GrCM=!HkhY!KuRC5> z_{FW)TT9|zyWRPbwr^SW#JFu=QZ~ze2{W7B`D3T@#+x?+s(I^G5}zzu(kgq=)%vdM z%XP1BYfpA#ae19{OkwUzo_V3Oc4o}_x@~vH`lG6ASM&NwFKlmrIp?6kTi&Rv(r>=Z zd26>;UTH?!WtPitSRKD#$TO<8wf@Mw&RkeVQbyp}|o#bwQ>%8_AXIWL>>kIYY9h+KJ)1AAKE8E{|GF2ao-{vIk>|aaR(G=f z^qik5ZztDmIWzOSw_RM?r-#SXf2MTWMh-ceENeVJT=T6AU2yT+^YY+-%xCxh_Tfs+ODQfXN=?iKvGS9$xVX#}3>5M==ds>l z6Vb2lVWIOW}KR2JbAsa3;+foW=sG8 delta 1392 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 Yq@-k_G&x-=5|a>!O((g!a#s5N4+EPQ_y7O^ delta 2113 zcmZvadsK{R9LLS1W*Vh?lQFieZmaNK=Tf!~nWU?nBNYwRTq>Kc7&T{S+agJp-lkB7 z9ZDs)CRyER*~KDVR){2xNi}p?o2I0VJo+bvmPKv84MT{S)OySMWT{VGw_T~y___~IZPGNVQiVOA z{8iMrKoTP7FnZHj>-Q~Hu9IA0BPWSfT`^@)#vaq$VWdLI0-&?`1x9euOYnN<6pt(rnl z7YW`wIRxl#ue20*#l)NlYp>j+s7X}VssVLCg-!_d;3ae6ow;Q3t}*ic{l|ZBe>k+e zO8F>PrL--cU94L?-Zx(|YEW60s8kf3RcPk84FB1pIALK;c2mgXvDWsOl!ZlYl`E`J zx>fEAhw|Vn9{l$K;F=1WI;peOG`KCxbfl(q<0~uDx^>@^Lc+EOZ^+BG^lGBD^DA74 zORQw-r~}kle7V!sjI5~Ph#ABLvCf-MMrp;;Ajd6^x-} zq|l3|Wh-x=8at4AsxDn|O>?f?_1Ql9E29p2m&dAm*HWTNu;&DNQ+_)b+7iE@4veUp}!V&^=JAX z<7WuG9L)^x=oeJ(*bS0|>KpR{Uo@?1F@F4Vt@T{z$k~Yf%&ro~l=5ae!9sAtPtb=UD^Jon^l7!p?EvGiWp3?@FSM7VT zp6PskOrdw36%6bZ<~4G^aSC155fpuv8D;EySK5LUWxX@<^O#&)CKv7ZyeKF>=^b$8 z9L(A}yH8ZBn=bO4rQK zgo-jRi;PHf$t9Zag7qmbLjwj)v?J}$rHy?TqMf`y7OgMUbI{9q(*QY6Bmj=mYWZ7v z>`5q2Ch$!c#QGa@AAByAeUujgcoi7vrS!j&GOS+36kd+4ZgNR)6k~_O#Qb>mhO#P) zVrnc&fW6OmzjqSsK`!j-OkH}`$JR-Ly<6b@%u4e}(Ls!N)FjtJn&x9l5BJa`Vx{0Q zX=9->GBY=zPI}v6+h|?bNLk@|ms;iJZT_Miw+HFoZkt@YHL~n8A%{9YJbhw+hgPzq zc2``Xb3UtWEEaotDcHVynl8IWo0x{@Dag~walibjS(c9B914FMFDW@uF{o=y)Mr6# z0EU?`6C;!NeQ_d~tirm;p;}~*eux%vrf6&0DB7A`bF?)!244~~8N{k)5P}H@+hjO1 z4+qnkt4+#rB+y7(GlnC_jc00PGdyvy*CsRXIar?QOtK1dG5gZN$7yw&sXpZaVH9Lz z&E}S0WF0i$NMK<;7WPCofF)VDN+28HM6q{{fVa5h(xw diff --git a/tests/output/test_export_html_to_pdf/example_html_input_000.pdf b/tests/output/test_export_html_to_pdf/example_html_input_000.pdf index f251a3225a1893112f6fd6909f3a45cc524796c3..caa7402e318d0fad0d376a20eccca56382ea1181 100644 GIT binary patch delta 147 zcmZ1=xj=Hm6fO-*0}~@7BQsNjC<6mc1%2QA6qm%3R0RzeD~PjIk+Z z=4mD=CZ^^F=7y#gMivICrYV*tDQV_LNvQ^w$)~PjIkER zrpd|42FZqIDP~ED$(BY2mKH`v$rdK5DW(>triOM3HUyQ#a@pB&6_+Fyl~fd^rg0gW NTNrSus=E5S0RVHCCs_ah diff --git a/tests/output/test_export_html_to_pdf/example_html_input_001.pdf b/tests/output/test_export_html_to_pdf/example_html_input_001.pdf index 022e7e3271cf889905cee2aa2ccd724f42a550cf..1a54c667efe2362ed65c3fe899d068a3f4dbcba0 100644 GIT binary patch delta 108 zcmew%@Izoj1RJNNfr*ikk(sIC!&D=)WFzAwGo$3hWD^UEq|{`y aM1zzh!xZy0^F)hOI|Um;N+!o~NC5zN5FV@m diff --git a/tests/output/test_export_html_to_pdf/example_html_input_002.pdf b/tests/output/test_export_html_to_pdf/example_html_input_002.pdf index eb657db0246ea7918e07f80a0c9a6d7544265878..349d14f88542210fa94e8b84d5a7e4103dbce58b 100644 GIT binary patch delta 125 zcmZ3^znp)=dR7ff0}~@7BQsOuC<6mc1%2QA6qm%3R0RzeDPx# delta 125 zcmZ3^znp)=dR7e!BTEBgV-r)uC<6mc1%2QA6qm%3R0RzeDlx!yQw&UvQqn99lakXC6O+tL4N?-#49zTzQd3e45=~9*6l@48iRH4h<0>vmEGnre UN=@T3G%z(bGvQKIb@g`x0D<8v#{d8T delta 154 zcmZqL&DOM=tziqJ&uk3~BTEBgV-r)OC<6mc1%2QA6qm%3R0RzeDlx!sQvmEGnre UN=@T3G%z(bGvQKIb@g`x0BW@>UjP6A diff --git a/tests/output/test_export_html_to_pdf/example_html_input_004.pdf b/tests/output/test_export_html_to_pdf/example_html_input_004.pdf index d477840faff3d81fb028663f6cf5f13e59cae71e..af44e8d1c63ea76f9eb5125daac07cd5b4ef8857 100644 GIT binary patch delta 115 zcmZ3!lWqAo6*_CG}$sKEzLO1#30SW h(Ad<%IL#o%)HKb)%pxf<+0@8R!G@5M>D_Y}WdPzJA)){P delta 115 zcmZ3!lWqAo6*_O*uv7p*v!}@(Zn#( h$jC4$)i}k>B+bku)xyL)InmTk!G@5M>D_Y}WdNa=AZ7pn diff --git a/tests/output/test_export_html_to_pdf/example_html_input_005.pdf b/tests/output/test_export_html_to_pdf/example_html_input_005.pdf index 4ea95aec0d352ad3cb70dab12513a4f1eca6374f..7d541af335c0b8e452e58bb695a2b073a8743f04 100644 GIT binary patch delta 125 zcmca5c1vu7AE$<;fr*ikk(sGQl!1Y!g1&Elic4Zis)B}#m63swp#fZaa~WqlqqC7^ rT1t{(YN|nUs-;P4l6h)sqD6|OVXCoVQmT1MN|K#|4Iw3y9k`_cr#&PD delta 125 zcmca5c1vu7AE$VVUlc-WMP?Rm||(CU_(gBbceZ&G60`CAbtP< delta 115 zcmcb!i|x)XwuUW?YO^^lj4Ta|jZI7~r|ZvV6hm;g`^{!t&**HDY+_)VVwsX^WS(f4 hl4NO`l5AmNVwjj@Y-Da^VrXoqU_(gBbceZ&G61S-AVL5D diff --git a/tests/output/test_export_html_to_pdf/example_html_input_007.pdf b/tests/output/test_export_html_to_pdf/example_html_input_007.pdf index c747afda3133042da2f227887ebfd6c24986ba91..a152e8649094e17bc71975d0502842b62eb904ba 100644 GIT binary patch delta 127 zcmcb$nfcac<_$ZqYgihX7#SIv8yH0y7-%Z!`{t*(B$lKqXt-Dz85kKFz@;}oygr-J v+0eqk$THO;(ZV7*#WF21#lpfY$JS`#%*e>dz|1fy$;>b%(N4jJkdn#!Z%P9I+(#yw diff --git a/tests/output/test_export_html_to_pdf/example_html_input_008.pdf b/tests/output/test_export_html_to_pdf/example_html_input_008.pdf index afbd132728d863e777234a519958d36c93779b3a..8df6c78686f85d37521fd34973b814d6c45d7809 100644 GIT binary patch delta 125 zcmcaAa#du*Ob!i80}~@7BXa|bC<6mc1%2QA6qm%3R0RzeDxQa^>i%KerQq#DMOpVOBR8?L5-2kvrA>jZ3 delta 130 zcmZ21zF2(2bWTnSBTEBgV^agm$qP8e5WLO%Iolay&COCxjgrk1jZKY`%nU8fEt3+H vlG03!jZ#dKO^p)G?G$VXDv9N?v*Ri*Nh~U+gR8rLId diff --git a/tests/output/test_export_html_to_pdf/example_html_input_010.pdf b/tests/output/test_export_html_to_pdf/example_html_input_010.pdf index a8fca86fa7ba2c1bde8767fda967533290096b0e..fa7fd38fcf377eab15e39b0b4b57d3c2591d6413 100644 GIT binary patch delta 152 zcmZoZ%+`FEtziqJ?|d~&0}~@7BXdKuC<6mc1%2QA6qm%3R0RzeDvmEGnre UN=@T3G%z!^u;fxzb@g`x0QEL1QUCw| delta 152 zcmZoZ%+`FEtziqJ?|d~2BTEBgV^c%3C<6mc1%2QA6qm%3R0RzeD{6l@48iRH4h<0>vmEGnre UN=@T3G%z!^u;fxzb@g`x05d)-Pyhe` diff --git a/tests/output/test_export_html_to_pdf/example_html_input_011.pdf b/tests/output/test_export_html_to_pdf/example_html_input_011.pdf index f743d828625876262c3553d80025d6c72f8c480f..7c21c589fe7f4092b40078a183d6e6a9652e841a 100644 GIT binary patch delta 145 zcmew(_(yO93%i=7fr*ikk-4Eol!1Y!g1&Elic4Zis)B}#m63swp#fBSvle?PV{BTo zv1v+bs+nnukx80aa+;+{vT<^vk$Iw_VM?-jiiMqm4M8QbTy}O`#U+VFB^5=fXTS0BJoaJ^%m! delta 145 zcmew(_(yO93%iTuKsQS(_1C@ diff --git a/tests/output/test_export_html_to_pdf/example_html_input_012.pdf b/tests/output/test_export_html_to_pdf/example_html_input_012.pdf index 3abbb67b9bd74a3bb21301a1b127fcdec3d301dd..17594e5c3321ff2fa8bf98dade1d5290d50cf14a 100644 GIT binary patch delta 126 zcmbQpH<53HBrCh6fr*ikk@;i=RtXq;vps7mV{A%ll96$$p{a>slCgP8ijk42v7xEC sfsui+XTS0LM=tHvj+t delta 126 zcmbQpH<53HBrCgxk)?sLvFT(5RtXq;vps7mV{DpTS0O125p8x;= diff --git a/tests/output/test_export_html_to_pdf/example_html_input_013.pdf b/tests/output/test_export_html_to_pdf/example_html_input_013.pdf index 93661acdc6b8acff8d2245eafbc67e1e1ef83b66..1c1ad3bec937313c347da4a3e4006840611231d3 100644 GIT binary patch delta 145 zcmdlZut#8n0h^kofr*ikk-3p!l!1Y!g1&Elic4Zis)B}#m63swp#fBSa~NAEW2|MO zv7x!4iAh>&3Q*D{CCwt$)X>BtEiKj9%*?{ zMXIrJvPo)kqNRzYv8jcHWmTS0OVdKQ2+n{ diff --git a/tests/output/test_export_html_to_pdf/example_html_input_014.pdf b/tests/output/test_export_html_to_pdf/example_html_input_014.pdf index 6e972444ea61d702c34935a13e7578133d053070..e61072da81d3f9acdddd780015bd4117c2f2f5b3 100644 GIT binary patch delta 108 zcmcb@dxdwy2^LOE0}~@7BXc98$ro9~5WLMFSlSt#&5|q<4b#k$EX^&=6Vr^6lM+ph aO)V@;ER7S*Es{*r>=bMWDVe;BO$q>=03MbA delta 108 zcmcb@dxdwy2^LNZBTEBgV^bsJ$ro9~5WLMFSlSt#lP%0GQjAOtQd3P#49v_7EDX)e a(hL*L6H^jROf6DV>=bMWDVe;BO$q>hvmP1% diff --git a/tests/output/test_export_markdown_to_pdf/example-markdown-input-001.md.pdf b/tests/output/test_export_markdown_to_pdf/example-markdown-input-001.md.pdf index ea99d605da5858aba8d7ed5d83267d4055fd6372..2b2f493a8921514194bc6ccc42dfd8a714b3c940 100644 GIT binary patch delta 103 zcmZqEZ`0p!ON8Chz{JSN$b9lc5eXQ3lc*+>vw50XVq$WlS+ap)TCzb}T9SF1xv`N^ WvYA1mg@tiinw^3TAtjS@#H9cPZ5@UH delta 103 zcmZqEZ`0p!ON8CR$kM>r*mUwk5eXQ3lc*+>vssF{fuV6yYNDZent_>xxsgeVkzuN- Wg^{s^d2*tqrJaHeAtjS@#H9eBV;ckj diff --git a/tests/output/test_export_markdown_to_pdf/example-markdown-input-002.md.pdf b/tests/output/test_export_markdown_to_pdf/example-markdown-input-002.md.pdf index a059941239ca253a32b0d5ead1c48553230fb713..3cb4ffe116d44593d2a539f0a2967521d1d835ce 100644 GIT binary patch delta 105 zcmaFr_|$R3Q8`Xa0}~@7BXeVu$>-$65WLNA<>oLtn3xzP8>AQ|85$Uv8=9x48K