diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..7b0f8e3b5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,33 @@ +--- +name: Bug report +about: Create a report to help us improve +title: BUG +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behaviour: + +```python +# please enter a concise, complete and self-contained code sample +# that reproduces the bug +``` + +**Expected behaviour** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + - OS: [e.g. iOS] + - borb version [e.g. 22] +- input PDF (if applicable) + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 000000000..bbcbbe7d6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/README.md b/README.md index 18dbc247c..a10a8569f 100644 --- a/README.md +++ b/README.md @@ -60,11 +60,11 @@ this is the classic `Hello World` example, in `borb`: ```python from pathlib import Path -from borb.pdf.canvas.layout.page_layout.multi_column_layout import SingleColumnLayout -from borb.pdf.canvas.layout.text.paragraph import Paragraph -from borb.pdf.document.document import Document -from borb.pdf.page.page import Page -from borb.pdf.pdf import PDF +from borb.pdf import Document +from borb.pdf import Page +from borb.pdf import SingleColumnLayout +from borb.pdf import Paragraph +from borb.pdf import PDF # create an empty Document pdf = Document() diff --git a/borb/io/read/types.py b/borb/io/read/types.py index 6a59d9f07..d5e461912 100644 --- a/borb/io/read/types.py +++ b/borb/io/read/types.py @@ -153,34 +153,34 @@ def get_reference(self) -> typing.Optional["Reference"]: setattr(self, "_reference", None) return self._reference - # set_can_be_referenced - def set_can_be_referenced(self, a_flag: bool): + # set_is_inline + def set_is_inline(self, a_flag: bool): """ - This function sets whether or not this Object can be referenced. - When an object can not be referenced, it is always embedded immediately in the PDF byte stream. + This function sets whether or not this Object is written inline. + When an object is inline, it is always embedded immediately in the PDF byte stream. """ - if "_can_be_referenced" not in vars(self): - setattr(self, "_can_be_referenced", None) - self._can_be_referenced = a_flag + if "_is_inline" not in vars(self): + setattr(self, "_is_inline", None) + self._is_inline = a_flag return self - # can_be_referenced - def can_be_referenced(self) -> bool: + # is_inline + def get_is_inline(self) -> bool: """ This function returns whether or not this Object can be referenced. When an object can not be referenced, it is always embedded immediately in the PDF byte stream. """ - if "_can_be_referenced" not in vars(self): - setattr(self, "_can_be_referenced", True) - return self._can_be_referenced + if "_is_inline" not in vars(self): + setattr(self, "_is_inline", False) + return self._is_inline object.set_parent = types.MethodType(set_parent, object) object.get_parent = types.MethodType(get_parent, object) object.get_root = types.MethodType(get_root, object) object.set_reference = types.MethodType(set_reference, object) object.get_reference = types.MethodType(get_reference, object) - object.set_can_be_referenced = types.MethodType(set_can_be_referenced, object) - object.can_be_referenced = types.MethodType(can_be_referenced, object) + object.set_is_inline = types.MethodType(set_is_inline, object) + object.is_inline = types.MethodType(get_is_inline, object) object.to_json_serializable = types.MethodType(to_json_serializable, object) if isinstance(object, Image): object.__deepcopy__ = types.MethodType(deepcopy_mod, object) diff --git a/borb/io/write/ascii_art/ascii_logo.txt b/borb/io/write/ascii_art/ascii_logo.txt index 8f1965a0d..c219d40e2 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.21 +borb version 2.0.22 Joris Schellekens diff --git a/borb/io/write/conformance_level.py b/borb/io/write/conformance_level.py index 0cfcc72ba..c158f7ec3 100644 --- a/borb/io/write/conformance_level.py +++ b/borb/io/write/conformance_level.py @@ -25,6 +25,10 @@ class ConformanceLevel(enum.Enum): PDFA_3U = 19 def get_standard(self) -> int: + """ + This function returns the standard (the numeric part) of this ConformanceLevel + :return: the numeric part of this ConformanceLevel (1, 2, 3) + """ if self in [ConformanceLevel.PDFA_1A, ConformanceLevel.PDFA_1B]: return 1 if self in [ @@ -42,6 +46,10 @@ def get_standard(self) -> int: assert False def get_conformance_level(self) -> str: + """ + This function returns the conformance-level (non-numeric part) of this ConformanceLevel + :return: the non-numeric part of this ConformanceLevel (A, B, U) + """ if self in [ConformanceLevel.PDFA_1A, ConformanceLevel.PDFA_2A]: return "A" if self in [ diff --git a/borb/io/write/document/document_transformer.py b/borb/io/write/document/document_transformer.py index 64df50dc3..bd6e7bd37 100644 --- a/borb/io/write/document/document_transformer.py +++ b/borb/io/write/document/document_transformer.py @@ -61,13 +61,13 @@ def transform( random_id = HexadecimalString("%032x" % random.randrange(16 ** 32)) if "ID" not in object_to_transform["XRef"]["Trailer"]: # fmt: off - object_to_transform["XRef"]["Trailer"][Name("ID")] = List().set_can_be_referenced(False) # type: ignore [attr-defined] + object_to_transform["XRef"]["Trailer"][Name("ID")] = List().set_is_inline(True) # type: ignore [attr-defined] object_to_transform["XRef"]["Trailer"]["ID"].append(random_id) object_to_transform["XRef"]["Trailer"]["ID"].append(random_id) # fmt: on else: object_to_transform["XRef"]["Trailer"]["ID"][1] = random_id - object_to_transform["XRef"]["Trailer"]["ID"].set_can_be_referenced(False) + object_to_transform["XRef"]["Trailer"]["ID"].set_is_inline(True) # /Info self._build_empty_document_info_dictionary(object_to_transform) diff --git a/borb/io/write/object/array_transformer.py b/borb/io/write/object/array_transformer.py index 8df5f8d27..78e0c29b4 100644 --- a/borb/io/write/object/array_transformer.py +++ b/borb/io/write/object/array_transformer.py @@ -64,7 +64,7 @@ def transform( or isinstance(v, List) or isinstance(v, Stream) or isinstance(v, Image) - ) and v.can_be_referenced(): # type: ignore [union-attr] + ) and not v.is_inline(): # type: ignore [union-attr] out_value.append(self.get_reference(v, context)) queue.append(v) else: @@ -86,7 +86,12 @@ def transform( self.get_root_transformer().transform(v, context) if i != N - 1: context.destination.write(bytes(" ", "latin1")) - context.destination.write(bytes("]\n", "latin1")) + + # write newline if the object is not inline + if object_to_transform.is_inline(): + context.destination.write(bytes("]", "latin1")) + else: + context.destination.write(bytes("]\n", "latin1")) # end object if needed if started_object: diff --git a/borb/io/write/object/dictionary_transformer.py b/borb/io/write/object/dictionary_transformer.py index b31c6a351..b6d0a2a0f 100644 --- a/borb/io/write/object/dictionary_transformer.py +++ b/borb/io/write/object/dictionary_transformer.py @@ -65,7 +65,7 @@ def transform( or isinstance(v, Stream) or isinstance(v, Image) or isinstance(v, Element) - ) and v.can_be_referenced(): # type: ignore [union-attr] + ) and not v.is_inline(): # type: ignore [union-attr] out_value[k] = self.get_reference(v, context) queue.append(v) else: @@ -89,7 +89,12 @@ def transform( self.get_root_transformer().transform(v, context) if i != N - 1: context.destination.write(bytes(" ", "latin1")) - context.destination.write(bytes(">>\n", "latin1")) + + # write newline if the object is not inline + if object_to_transform.is_inline(): + context.destination.write(bytes(">>", "latin1")) + else: + context.destination.write(bytes(">>\n", "latin1")) # end object if needed if started_object: diff --git a/borb/io/write/object/stream_transformer.py b/borb/io/write/object/stream_transformer.py index 93b35ea66..c7e6c00c5 100644 --- a/borb/io/write/object/stream_transformer.py +++ b/borb/io/write/object/stream_transformer.py @@ -74,7 +74,7 @@ def transform( isinstance(v, Dictionary) or isinstance(v, List) or isinstance(v, Stream) - ) and v.can_be_referenced(): # type: ignore [union-attr] + ) and not v.is_inline(): # type: ignore [union-attr] stream_dictionary[k] = self.get_reference(v, context) queue.append(v) else: diff --git a/borb/io/write/page/page_transformer.py b/borb/io/write/page/page_transformer.py index 171750d9c..a3c3dcedc 100644 --- a/borb/io/write/page/page_transformer.py +++ b/borb/io/write/page/page_transformer.py @@ -51,7 +51,7 @@ def transform( # mark some keys as non-referencable for k in ["ArtBox", "BleedBox", "CropBox", "MediaBox", "TrimBox"]: if k in object_to_transform: - object_to_transform[k].set_can_be_referenced(False) # type: ignore [attr-defined] + object_to_transform[k].set_is_inline(True) # type: ignore [attr-defined] # delegate to super super(PageTransformer, self).transform(object_to_transform, context) diff --git a/borb/io/write/page/pages_transformer.py b/borb/io/write/page/pages_transformer.py index 0329590b2..cccc62914 100644 --- a/borb/io/write/page/pages_transformer.py +++ b/borb/io/write/page/pages_transformer.py @@ -42,7 +42,7 @@ def transform( ), "A WriteTransformerState must be defined in order to write Pages Dictionary objects." # /Kids can be written immediately - object_to_transform[Name("Kids")].set_can_be_referenced(False) # type: ignore [attr-defined] + object_to_transform[Name("Kids")].set_is_inline(True) # type: ignore [attr-defined] # queue writing of /Page objects queue: typing.List[AnyPDFType] = [] diff --git a/borb/pdf/__init__.py b/borb/pdf/__init__.py index bcf77caad..e906fdc8e 100644 --- a/borb/pdf/__init__.py +++ b/borb/pdf/__init__.py @@ -41,3 +41,51 @@ For more information, please contact borb Software Corp. at this address: joris.schellekens.1989@gmail.com """ + +# Document, Page, PDF +from .document.document import Document +from .page.page import Page +from .pdf import PDF + +# PageLayout +from .canvas.layout.page_layout.page_layout import PageLayout +from .canvas.layout.page_layout.multi_column_layout import SingleColumnLayout +from .canvas.layout.page_layout.multi_column_layout import MultiColumnLayout + +# Paragraph +from .canvas.layout.text.paragraph import Paragraph +from .canvas.layout.text.heading import Heading + +# Image +from .canvas.layout.image.image import Image +from .canvas.layout.image.chart import Chart +from .canvas.layout.image.barcode import Barcode +from .canvas.layout.image.barcode import BarcodeType + +# Shape +from .canvas.layout.shape.shape import Shape +from .canvas.layout.shape.disjoint_shape import DisjointShape + +# Table +from .canvas.layout.table.table import Table, TableCell +from .canvas.layout.table.fixed_column_width_table import FixedColumnWidthTable +from .canvas.layout.table.flexible_column_width_table import FlexibleColumnWidthTable + +# List +from .canvas.layout.list.list import List +from .canvas.layout.list.ordered_list import OrderedList +from .canvas.layout.list.unordered_list import UnorderedList +from .canvas.layout.list.roman_list import RomanNumeralOrderedList + +# Color +from .canvas.color.color import ( + Color, + RGBColor, + CMYKColor, + GrayColor, + HSVColor, + HexColor, + HSVColor, + X11Color, +) +from .canvas.color.pantone import Pantone diff --git a/borb/pdf/canvas/font/font.py b/borb/pdf/canvas/font/font.py index 8096ceee4..84bc2f042 100644 --- a/borb/pdf/canvas/font/font.py +++ b/borb/pdf/canvas/font/font.py @@ -370,7 +370,7 @@ def _copy_font_descriptor(self, font_descriptor_to_copy: Dictionary) -> Dictiona f1[Name("FontWeight")] = f0["FontWeight"] f1[Name("Flags")] = f0["Flags"] if "FontBBox" in f0 and False: # TODO - f1[Name("FontBBox")] = List().set_can_be_referenced(False) # type: ignore [attr-defined] + f1[Name("FontBBox")] = List().set_is_inline(True) # type: ignore [attr-defined] for i in range(0, len(f0["FontBBox"])): f1["FontBBox"].append(f0["FontBBox"][i]) f1[Name("ItalicAngle")] = f0["ItalicAngle"] diff --git a/borb/pdf/canvas/font/simple_font/true_type_font.py b/borb/pdf/canvas/font/simple_font/true_type_font.py index 2b129d64a..0d3f60d02 100644 --- a/borb/pdf/canvas/font/simple_font/true_type_font.py +++ b/borb/pdf/canvas/font/simple_font/true_type_font.py @@ -163,7 +163,7 @@ def _get_font_descriptor(ttf_font_file: TTFont) -> Dictionary: if cap_height is None: cap_height = bDecimal(840) - font_descriptor[Name("FontBBox")] = List().set_can_be_referenced(False) # type: ignore[attr-defined] + font_descriptor[Name("FontBBox")] = List().set_is_inline(True) # type: ignore[attr-defined] font_descriptor["FontBBox"].append(bDecimal(min_x)) font_descriptor["FontBBox"].append(bDecimal(min_y)) font_descriptor["FontBBox"].append(bDecimal(max_x)) diff --git a/borb/pdf/canvas/layout/annotation/annotation.py b/borb/pdf/canvas/layout/annotation/annotation.py index db2a78d9e..cbfd2a2a3 100644 --- a/borb/pdf/canvas/layout/annotation/annotation.py +++ b/borb/pdf/canvas/layout/annotation/annotation.py @@ -48,7 +48,7 @@ def __init__( # (Required) The annotation rectangle, defining the location of the # annotation on the page in default user space units. - self[Name("Rect")] = List().set_can_be_referenced(False) # type: ignore [attr-defined] + self[Name("Rect")] = List().set_is_inline(True) # type: ignore [attr-defined] self["Rect"].append(bDecimal(bounding_box.get_x())) self["Rect"].append(bDecimal(bounding_box.get_y())) self["Rect"].append(bDecimal(bounding_box.get_x() + bounding_box.get_width())) @@ -66,7 +66,7 @@ def __init__( # (Optional; PDF 1.4) The annotation name, a text string uniquely # identifying it among all the annotations on its page. - len_annots = len(self["Annots"]) if "Annots" in self else 0 + len_annots: int = 0 self[Name("NM")] = String("annotation-{0:03d}".format(len_annots)) # (Optional; PDF 1.1) The date and time when the annotation was most @@ -107,7 +107,7 @@ def __init__( and vertical_corner_radius is not None and border_width is not None ): - self[Name("Border")] = List().set_can_be_referenced(False) # type: ignore [attr-defined] + self[Name("Border")] = List().set_is_inline(True) # type: ignore [attr-defined] self["Border"].append(bDecimal(horizontal_corner_radius)) self["Border"].append(bDecimal(vertical_corner_radius)) self["Border"].append(bDecimal(border_width)) @@ -120,7 +120,7 @@ def __init__( # The number of array elements determines the colour space in which the # colour shall be defined if color is not None: - self[Name("C")] = List().set_can_be_referenced(False) # type: ignore [attr-defined] + self[Name("C")] = List().set_is_inline(True) # type: ignore [attr-defined] self["C"].append(bDecimal(color.to_rgb().red)) self["C"].append(bDecimal(color.to_rgb().green)) self["C"].append(bDecimal(color.to_rgb().blue)) diff --git a/borb/pdf/canvas/layout/annotation/circle_annotation.py b/borb/pdf/canvas/layout/annotation/circle_annotation.py index e8b838e61..8191d0083 100644 --- a/borb/pdf/canvas/layout/annotation/circle_annotation.py +++ b/borb/pdf/canvas/layout/annotation/circle_annotation.py @@ -54,7 +54,7 @@ def __init__( # rectangle or ellipse. The number of array elements determines the colour # space in which the colour shall be defined if fill_color is not None: - self[Name("IC")] = List().set_can_be_referenced(False) # type: ignore [attr-defined] + self[Name("IC")] = List().set_is_inline(True) # type: ignore [attr-defined] self["IC"].append(bDecimal(fill_color.to_rgb().red)) self["IC"].append(bDecimal(fill_color.to_rgb().green)) self["IC"].append(bDecimal(fill_color.to_rgb().blue)) @@ -76,7 +76,7 @@ def __init__( # less than the height of Rect, and the sum of the left and right differences # shall be less than the width of Rect. if rectangle_difference is not None: - self[Name("RD")] = List().set_can_be_referenced(False) # type: ignore [attr-defined] + self[Name("RD")] = List().set_is_inline(True) # type: ignore [attr-defined] self["RD"].append(bDecimal(rectangle_difference[0])) self["RD"].append(bDecimal(rectangle_difference[1])) self["RD"].append(bDecimal(rectangle_difference[2])) diff --git a/borb/pdf/canvas/layout/annotation/highlight_annotation.py b/borb/pdf/canvas/layout/annotation/highlight_annotation.py index b275f9601..bc9bf9a40 100644 --- a/borb/pdf/canvas/layout/annotation/highlight_annotation.py +++ b/borb/pdf/canvas/layout/annotation/highlight_annotation.py @@ -39,7 +39,7 @@ def __init__(self, bounding_box: Rectangle, color: Color = HexColor("faed27")): # underlying the annotation. The coordinates for each quadrilateral shall # be given in the order # x1 y1 x2 y2 x3 y3 x4 y4 - self[Name("QuadPoints")] = List().set_can_be_referenced(False) # type: ignore [attr-defined] + self[Name("QuadPoints")] = List().set_is_inline(True) # type: ignore [attr-defined] # x1, y1 self["QuadPoints"].append(bDecimal(bounding_box.get_x())) self["QuadPoints"].append(bDecimal(bounding_box.get_y())) @@ -62,7 +62,7 @@ def __init__(self, bounding_box: Rectangle, color: Color = HexColor("faed27")): ) # border - self[Name("Border")] = List().set_can_be_referenced(False) # type: ignore [attr-defined] + self[Name("Border")] = List().set_is_inline(True) # type: ignore [attr-defined] self["Border"].append(bDecimal(0)) self["Border"].append(bDecimal(0)) self["Border"].append(bDecimal(1)) diff --git a/borb/pdf/canvas/layout/annotation/line_annotation.py b/borb/pdf/canvas/layout/annotation/line_annotation.py index e444b383b..d11da2c2b 100644 --- a/borb/pdf/canvas/layout/annotation/line_annotation.py +++ b/borb/pdf/canvas/layout/annotation/line_annotation.py @@ -50,7 +50,7 @@ def __init__( # starting and ending coordinates of the line in default user space. # If the LL entry is present, this value shall represent the endpoints of the # leader lines rather than the endpoints of the line itself; see Figure 60. - self[Name("L")] = List().set_can_be_referenced(False) # type: ignore [attr-defined] + self[Name("L")] = List().set_is_inline(True) # type: ignore [attr-defined] self["L"].append(start_point[0]) self["L"].append(start_point[1]) self["L"].append(end_point[0]) @@ -62,7 +62,7 @@ def __init__( # defined, respectively, by the first and second pairs of coordinates, (x 1 , y 1 ) # and (x 2 , y 2 ), in the L array. Table 176 shows the possible values. Default # value: [ /None /None ]. - self[Name("LE")] = List().set_can_be_referenced(False) # type: ignore [attr-defined] + self[Name("LE")] = List().set_is_inline(True) # type: ignore [attr-defined] self["LE"].append(left_line_end_style.value) self["LE"].append(right_line_end_style) @@ -71,7 +71,7 @@ def __init__( # rectangle or ellipse. The number of array elements determines the colour # space in which the colour shall be defined if stroke_color is not None: - self[Name("IC")] = List().set_can_be_referenced(False) # type: ignore [attr-defined] + self[Name("IC")] = List().set_is_inline(True) # type: ignore [attr-defined] self["IC"].append(bDecimal(stroke_color.to_rgb().red)) self["IC"].append(bDecimal(stroke_color.to_rgb().green)) self["IC"].append(bDecimal(stroke_color.to_rgb().blue)) diff --git a/borb/pdf/canvas/layout/annotation/link_annotation.py b/borb/pdf/canvas/layout/annotation/link_annotation.py index 29d0fde0f..25a5d31a4 100644 --- a/borb/pdf/canvas/layout/annotation/link_annotation.py +++ b/borb/pdf/canvas/layout/annotation/link_annotation.py @@ -64,7 +64,7 @@ def __init__( # (Optional; not permitted if an A entry is present) A destination that shall # be displayed when the annotation is activated (see 12.3.2, # “Destinations”). - destination = List().set_can_be_referenced(False) # type: ignore [attr-defined] + destination = List().set_is_inline(True) # type: ignore [attr-defined] destination.append(bDecimal(page)) destination.append(destination_type.value) if destination_type == DestinationType.X_Y_Z: diff --git a/borb/pdf/canvas/layout/annotation/polygon_annotion.py b/borb/pdf/canvas/layout/annotation/polygon_annotion.py index 5beb30f65..2558c3245 100644 --- a/borb/pdf/canvas/layout/annotation/polygon_annotion.py +++ b/borb/pdf/canvas/layout/annotation/polygon_annotion.py @@ -54,7 +54,7 @@ def __init__( # (Required) An array of numbers (see Table 174) specifying the width and # dash pattern that shall represent the alternating horizontal and vertical # coordinates, respectively, of each vertex, in default user space. - self[Name("Vertices")] = List().set_can_be_referenced(False) # type: ignore [attr-defined] + self[Name("Vertices")] = List().set_is_inline(True) # type: ignore [attr-defined] for p in points: self["Vertices"].append(bDecimal(p[0])) self["Vertices"].append(bDecimal(p[1])) @@ -65,6 +65,6 @@ def __init__( # defined, respectively, by the first and second pairs of coordinates, (x 1 , y 1 ) # and (x 2 , y 2 ), in the L array. Table 176 shows the possible values. Default # value: [ /None /None ]. - self[Name("LE")] = List().set_can_be_referenced(False) # type: ignore [attr-defined] + self[Name("LE")] = List().set_is_inline(True) # type: ignore [attr-defined] self["LE"].append(Name("None")) self["LE"].append(Name("None")) diff --git a/borb/pdf/canvas/layout/annotation/polyline_annotation.py b/borb/pdf/canvas/layout/annotation/polyline_annotation.py index aa204ab11..d4cf080ce 100644 --- a/borb/pdf/canvas/layout/annotation/polyline_annotation.py +++ b/borb/pdf/canvas/layout/annotation/polyline_annotation.py @@ -76,7 +76,7 @@ def __init__( # (Required) An array of numbers (see Table 174) specifying the width and # dash pattern that shall represent the alternating horizontal and vertical # coordinates, respectively, of each vertex, in default user space. - self[Name("Vertices")] = List().set_can_be_referenced(False) # type: ignore [attr-defined] + self[Name("Vertices")] = List().set_is_inline(True) # type: ignore [attr-defined] for p in points: self["Vertices"].append(bDecimal(p[0])) self["Vertices"].append(bDecimal(p[1])) @@ -87,12 +87,12 @@ def __init__( # defined, respectively, by the first and second pairs of coordinates, (x 1 , y 1 ) # and (x 2 , y 2 ), in the L array. Table 176 shows the possible values. Default # value: [ /None /None ]. - self[Name("LE")] = List().set_can_be_referenced(False) # type: ignore [attr-defined] + self[Name("LE")] = List().set_is_inline(True) # type: ignore [attr-defined] self["LE"].append(left_line_end_style) self["LE"].append(right_line_end_style) if fill_color is not None: - self[Name("IC")] = List().set_can_be_referenced(False) # type: ignore [attr-defined] + self[Name("IC")] = List().set_is_inline(True) # type: ignore [attr-defined] self["IC"].append(bDecimal(fill_color.to_rgb().red)) self["IC"].append(bDecimal(fill_color.to_rgb().green)) self["IC"].append(bDecimal(fill_color.to_rgb().blue)) diff --git a/borb/pdf/canvas/layout/annotation/redact_annotation.py b/borb/pdf/canvas/layout/annotation/redact_annotation.py index 97190a5af..0ff7e634a 100644 --- a/borb/pdf/canvas/layout/annotation/redact_annotation.py +++ b/borb/pdf/canvas/layout/annotation/redact_annotation.py @@ -77,7 +77,7 @@ def __init__( # redaction region is left transparent. This entry is ignored if the RO # entry is present. if fill_color is not None: - self[Name("IC")] = List().set_can_be_referenced(False) # type: ignore [attr-defined] + self[Name("IC")] = List().set_is_inline(True) # type: ignore [attr-defined] self["IC"].append(bDecimal(fill_color.to_rgb().red)) self["IC"].append(bDecimal(fill_color.to_rgb().green)) self["IC"].append(bDecimal(fill_color.to_rgb().blue)) @@ -136,7 +136,7 @@ def __init__( # The lower-left corner of the bounding box (BBox) is set to coordinates (0, 0) in the form coordinate system. # The box’s top and right coordinates are taken from the dimensions of the annotation rectangle (the Rect # entry in the widget annotation dictionary). - self["AP"]["N"][Name("BBox")] = List().set_can_be_referenced(False) # type: ignore [attr-defined] + self["AP"]["N"][Name("BBox")] = List().set_is_inline(True) # type: ignore [attr-defined] self["AP"]["N"]["BBox"].append(bDecimal(0)) self["AP"]["N"]["BBox"].append(bDecimal(0)) self["AP"]["N"]["BBox"].append(bDecimal(100)) diff --git a/borb/pdf/canvas/layout/annotation/remote_go_to_annotation.py b/borb/pdf/canvas/layout/annotation/remote_go_to_annotation.py index 07e7e69a2..d6c44039a 100644 --- a/borb/pdf/canvas/layout/annotation/remote_go_to_annotation.py +++ b/borb/pdf/canvas/layout/annotation/remote_go_to_annotation.py @@ -38,7 +38,7 @@ def __init__(self, bounding_box: Rectangle, uri: str): # border. The dash array shall be specified in the same format as in the # line dash pattern parameter of the graphics state (see 8.4.3.6, “Line # Dash Pattern”). - self[Name("Border")] = List().set_can_be_referenced(False) + self[Name("Border")] = List().set_is_inline(True) for _ in range(0, 3): self[Name("Border")].append(bDecimal(0)) diff --git a/borb/pdf/canvas/layout/annotation/square_annotation.py b/borb/pdf/canvas/layout/annotation/square_annotation.py index 59f25e328..cb87be678 100644 --- a/borb/pdf/canvas/layout/annotation/square_annotation.py +++ b/borb/pdf/canvas/layout/annotation/square_annotation.py @@ -54,7 +54,7 @@ def __init__( # rectangle or ellipse. The number of array elements determines the colour # space in which the colour shall be defined if fill_color is not None: - self[Name("IC")] = List().set_can_be_referenced(False) # type: ignore [attr-defined] + self[Name("IC")] = List().set_is_inline(True) # type: ignore [attr-defined] self["IC"].append(bDecimal(fill_color.to_rgb().red)) self["IC"].append(bDecimal(fill_color.to_rgb().green)) self["IC"].append(bDecimal(fill_color.to_rgb().blue)) @@ -76,7 +76,7 @@ def __init__( # less than the height of Rect, and the sum of the left and right differences # shall be less than the width of Rect. if rectangle_difference is not None: - self[Name("RD")] = List().set_can_be_referenced(False) # type: ignore [attr-defined] + self[Name("RD")] = List().set_is_inline(True) # type: ignore [attr-defined] self["RD"].append(bDecimal(rectangle_difference[0])) self["RD"].append(bDecimal(rectangle_difference[1])) self["RD"].append(bDecimal(rectangle_difference[2])) diff --git a/borb/pdf/canvas/layout/annotation/squiggly_annotation.py b/borb/pdf/canvas/layout/annotation/squiggly_annotation.py index ac0af7179..b7cca07bc 100644 --- a/borb/pdf/canvas/layout/annotation/squiggly_annotation.py +++ b/borb/pdf/canvas/layout/annotation/squiggly_annotation.py @@ -70,7 +70,7 @@ def __init__( # The lower-left corner of the bounding box (BBox) is set to coordinates (0, 0) in the form coordinate system. # The box’s top and right coordinates are taken from the dimensions of the annotation rectangle (the Rect # entry in the widget annotation dictionary). - self["AP"]["N"][Name("BBox")] = List().set_can_be_referenced(False) # type: ignore [attr-defined] + self["AP"]["N"][Name("BBox")] = List().set_is_inline(True) # type: ignore [attr-defined] self["AP"]["N"]["BBox"].append(bDecimal(0)) self["AP"]["N"]["BBox"].append(bDecimal(0)) self["AP"]["N"]["BBox"].append(bDecimal(bounding_box.width)) diff --git a/borb/pdf/canvas/layout/annotation/strike_out_annotation.py b/borb/pdf/canvas/layout/annotation/strike_out_annotation.py index 66d9fc696..9b1ee9f00 100644 --- a/borb/pdf/canvas/layout/annotation/strike_out_annotation.py +++ b/borb/pdf/canvas/layout/annotation/strike_out_annotation.py @@ -64,7 +64,7 @@ def __init__( # The lower-left corner of the bounding box (BBox) is set to coordinates (0, 0) in the form coordinate system. # The box’s top and right coordinates are taken from the dimensions of the annotation rectangle (the Rect # entry in the widget annotation dictionary). - self["AP"]["N"][Name("BBox")] = List().set_can_be_referenced(False) # type: ignore [attr-defined] + self["AP"]["N"][Name("BBox")] = List().set_is_inline(True) # type: ignore [attr-defined] self["AP"]["N"]["BBox"].append(bDecimal(0)) self["AP"]["N"]["BBox"].append(bDecimal(0)) self["AP"]["N"]["BBox"].append(bDecimal(bounding_box.width)) diff --git a/borb/pdf/canvas/layout/forms/check_box.py b/borb/pdf/canvas/layout/forms/check_box.py index c3e236738..0ae97165a 100644 --- a/borb/pdf/canvas/layout/forms/check_box.py +++ b/borb/pdf/canvas/layout/forms/check_box.py @@ -41,6 +41,9 @@ def _init_widget_dictionary(self, page: Page, layout_box: Rectangle) -> None: if self._widget_dictionary is not None: return + if "XRef" not in page.get_root(): + return + # init page and font resources assert self._font_size is not None font_resource_name: Name = self._get_font_resource_name( @@ -55,7 +58,7 @@ def _init_widget_dictionary(self, page: Page, layout_box: Rectangle) -> None: widget_off_appearance: Stream = Stream() widget_off_appearance[Name("Type")] = Name("XObject") widget_off_appearance[Name("Subtype")] = Name("Form") - widget_off_appearance[Name("BBox")] = List().set_can_be_referenced(False) # type: ignore [attr-defined] + widget_off_appearance[Name("BBox")] = List().set_is_inline(True) # type: ignore [attr-defined] widget_off_appearance["BBox"].append(bDecimal(0)) widget_off_appearance["BBox"].append(bDecimal(0)) widget_off_appearance["BBox"].append(bDecimal(layout_box.width)) @@ -90,7 +93,7 @@ def _init_widget_dictionary(self, page: Page, layout_box: Rectangle) -> None: self._widget_dictionary[Name("Type")] = Name("Annot") self._widget_dictionary[Name("Subtype")] = Name("Widget") self._widget_dictionary[Name("F")] = bDecimal(4) - self._widget_dictionary[Name("Rect")] = List().set_can_be_referenced(False) # type: ignore [attr-defined] + self._widget_dictionary[Name("Rect")] = List().set_is_inline(True) # type: ignore [attr-defined] self._widget_dictionary["Rect"].append(bDecimal(layout_box.x)) self._widget_dictionary["Rect"].append( bDecimal(layout_box.y + layout_box.height - self._font_size - 2) @@ -150,13 +153,13 @@ def _do_layout(self, page: "Page", layout_box: Rectangle) -> Rectangle: self._init_widget_dictionary(page, layout_rect) # set location - assert self._widget_dictionary is not None - self._widget_dictionary["Rect"][0] = bDecimal(layout_box.x) - self._widget_dictionary["Rect"][1] = bDecimal( - layout_box.y + layout_box.height - self._font_size - ) - self._widget_dictionary["Rect"][2] = bDecimal(layout_box.x + layout_box.width) - self._widget_dictionary["Rect"][3] = bDecimal(layout_box.y + layout_box.height) + # fmt: off + if self._widget_dictionary is not None: + self._widget_dictionary["Rect"][0] = bDecimal(layout_box.x) + self._widget_dictionary["Rect"][1] = bDecimal(layout_box.y + layout_box.height - self._font_size) + self._widget_dictionary["Rect"][2] = bDecimal(layout_box.x + layout_box.width) + self._widget_dictionary["Rect"][3] = bDecimal(layout_box.y + layout_box.height) + # fmt: on # return Rectangle return layout_rect diff --git a/borb/pdf/canvas/layout/forms/drop_down_list.py b/borb/pdf/canvas/layout/forms/drop_down_list.py index fd5051120..5a2f9c3ee 100644 --- a/borb/pdf/canvas/layout/forms/drop_down_list.py +++ b/borb/pdf/canvas/layout/forms/drop_down_list.py @@ -54,6 +54,9 @@ def _init_widget_dictionary(self, page: Page, layout_box: Rectangle) -> None: if self._widget_dictionary is not None: return + if "XRef" not in page.get_root(): + return + # init page and font resources assert self._font_size is not None font_resource_name: Name = self._get_font_resource_name( @@ -68,7 +71,7 @@ def _init_widget_dictionary(self, page: Page, layout_box: Rectangle) -> None: widget_normal_appearance: Stream = Stream() widget_normal_appearance[Name("Type")] = Name("XObject") widget_normal_appearance[Name("Subtype")] = Name("Form") - widget_normal_appearance[Name("BBox")] = List().set_can_be_referenced(False) # type: ignore [attr-defined] + widget_normal_appearance[Name("BBox")] = List().set_is_inline(True) # type: ignore [attr-defined] widget_normal_appearance["BBox"].append(bDecimal(0)) widget_normal_appearance["BBox"].append(bDecimal(0)) widget_normal_appearance["BBox"].append(bDecimal(layout_box.width)) @@ -96,7 +99,7 @@ def _init_widget_dictionary(self, page: Page, layout_box: Rectangle) -> None: self._widget_dictionary[Name("Type")] = Name("Annot") self._widget_dictionary[Name("Subtype")] = Name("Widget") self._widget_dictionary[Name("F")] = bDecimal(4) - self._widget_dictionary[Name("Rect")] = List().set_can_be_referenced(False) # type: ignore [attr-defined] + self._widget_dictionary[Name("Rect")] = List().set_is_inline(True) # type: ignore [attr-defined] self._widget_dictionary["Rect"].append(bDecimal(layout_box.x)) self._widget_dictionary["Rect"].append( bDecimal(layout_box.y + layout_box.height - self._font_size - 2) @@ -162,15 +165,15 @@ def _do_layout(self, page: "Page", layout_box: Rectangle) -> Rectangle: self._init_widget_dictionary(page, layout_rect) # set location - assert self._widget_dictionary is not None - self._widget_dictionary["AP"]["N"]["BBox"][2] = bDecimal(layout_box.width) - self._widget_dictionary["AP"]["N"]["BBox"][3] = bDecimal(self._font_size) - self._widget_dictionary["Rect"][0] = bDecimal(layout_box.x) - self._widget_dictionary["Rect"][1] = bDecimal( - layout_box.y + layout_box.height - self._font_size - ) - self._widget_dictionary["Rect"][2] = bDecimal(layout_box.x + layout_box.width) - self._widget_dictionary["Rect"][3] = bDecimal(layout_box.y + layout_box.height) + # fmt: off + if self._widget_dictionary is not None: + self._widget_dictionary["AP"]["N"]["BBox"][2] = bDecimal(layout_box.width) + self._widget_dictionary["AP"]["N"]["BBox"][3] = bDecimal(self._font_size) + self._widget_dictionary["Rect"][0] = bDecimal(layout_box.x) + self._widget_dictionary["Rect"][1] = bDecimal(layout_box.y + layout_box.height - self._font_size) + self._widget_dictionary["Rect"][2] = bDecimal(layout_box.x + layout_box.width) + self._widget_dictionary["Rect"][3] = bDecimal(layout_box.y + layout_box.height) + # fmt: on # return Rectangle return layout_rect diff --git a/borb/pdf/canvas/layout/forms/push_button.py b/borb/pdf/canvas/layout/forms/push_button.py index b877a5961..07910c72e 100644 --- a/borb/pdf/canvas/layout/forms/push_button.py +++ b/borb/pdf/canvas/layout/forms/push_button.py @@ -113,7 +113,7 @@ def _init_widget_dictionary(self, page: Page) -> None: self._widget_dictionary[Name("AP")][Name("N")] = Stream() self._widget_dictionary[Name("AP")][Name("N")][Name("Type")] = Name("XObject") self._widget_dictionary[Name("AP")][Name("N")][Name("Subtype")] = Name("Form") - self._widget_dictionary[Name("AP")][Name("N")][Name("BBox")] = List().set_can_be_referenced(False) + self._widget_dictionary[Name("AP")][Name("N")][Name("BBox")] = List().set_is_inline(True) for _ in range(0, 4): self._widget_dictionary[Name("AP")][Name("N")][Name("BBox")].append(bDecimal(0)) self._widget_dictionary[Name("AP")][Name("N")][Name("DecodedBytes")] = b"/Tx BMC EMC" @@ -121,7 +121,7 @@ def _init_widget_dictionary(self, page: Page) -> None: self._widget_dictionary[Name("AP")][Name("N")][Name("Filter")] = Name("FlateDecode") self._widget_dictionary[Name("AP")][Name("N")][Name("Length")] = bDecimal(len(self._widget_dictionary[Name("AP")][Name("N")][Name("Bytes")])) self._widget_dictionary[Name("AP")][Name("N")][Name("Resources")] = Dictionary() - self._widget_dictionary[Name("AP")][Name("N")][Name("Resources")][Name("ProcSet")] = List().set_can_be_referenced(False) + self._widget_dictionary[Name("AP")][Name("N")][Name("Resources")][Name("ProcSet")] = List().set_is_inline(True) self._widget_dictionary[Name("AP")][Name("N")][Name("Resources")][Name("ProcSet")].append(Name("PDF")) self._widget_dictionary[Name("AP")][Name("N")][Name("Resources")][Name("ProcSet")].append(Name("Text")) self._widget_dictionary[Name("AP")][Name("N")][Name("Resources")][Name("Font")] = Dictionary() @@ -140,12 +140,12 @@ def _init_widget_dictionary(self, page: Page) -> None: self._widget_dictionary[Name("Ff")] = bDecimal(65536) self._widget_dictionary[Name("FT")] = Name("Btn") self._widget_dictionary[Name("MK")] = Dictionary() - self._widget_dictionary[Name("MK")][Name("BC")] = List().set_can_be_referenced(False) - self._widget_dictionary[Name("MK")][Name("BG")] = List().set_can_be_referenced(False) + self._widget_dictionary[Name("MK")][Name("BC")] = List().set_is_inline(True) + self._widget_dictionary[Name("MK")][Name("BG")] = List().set_is_inline(True) self._widget_dictionary[Name("MK")][Name("CA")] = String("") self._widget_dictionary[Name("P")] = catalog self._widget_dictionary[Name("Q")] = bDecimal(1) - self._widget_dictionary[Name("Rect")] = List().set_can_be_referenced(False) # type: ignore [attr-defined] + self._widget_dictionary[Name("Rect")] = List().set_is_inline(True) # type: ignore [attr-defined] for _ in range(0, 4): self._widget_dictionary[Name("Rect")].append(bDecimal(0)) self._widget_dictionary[Name("Subtype")] = Name("Widget") @@ -199,11 +199,11 @@ def _do_layout(self, page: "Page", layout_box: Rectangle) -> Rectangle: # set location # fmt: off - assert self._widget_dictionary is not None - self._widget_dictionary["Rect"][0] = bDecimal(text_layout_box.x) # ll_x - self._widget_dictionary["Rect"][1] = bDecimal(text_layout_box.y) # ll_y - self._widget_dictionary["Rect"][2] = bDecimal(text_layout_box.x + text_layout_box.width) # ur_x - self._widget_dictionary["Rect"][3] = bDecimal(text_layout_box.y + text_layout_box.height) # ur_y + if self._widget_dictionary is not None: + self._widget_dictionary["Rect"][0] = bDecimal(text_layout_box.x) # ll_x + self._widget_dictionary["Rect"][1] = bDecimal(text_layout_box.y) # ll_y + self._widget_dictionary["Rect"][2] = bDecimal(text_layout_box.x + text_layout_box.width) # ur_x + self._widget_dictionary["Rect"][3] = bDecimal(text_layout_box.y + text_layout_box.height) # ur_y # fmt: on # return Rectangle @@ -264,20 +264,19 @@ def __init__( self._javascript: str = javascript def _init_widget_dictionary(self, page: Page) -> None: + # call to super super(JavaScriptPushButton, self)._init_widget_dictionary(page) # build JavaScript stream object + # fmt: off javascript_stream = Stream() javascript_stream[Name("Type")] = Name("JavaScript") javascript_stream[Name("DecodedBytes")] = bytes(self._javascript, "latin1") - javascript_stream[Name("Bytes")] = zlib.compress( - javascript_stream[Name("DecodedBytes")], 9 - ) - javascript_stream[Name("Length")] = bDecimal( - len(javascript_stream[Name("Bytes")]) - ) + javascript_stream[Name("Bytes")] = zlib.compress(javascript_stream[Name("DecodedBytes")], 9) + javascript_stream[Name("Length")] = bDecimal(len(javascript_stream[Name("Bytes")])) javascript_stream[Name("Filter")] = Name("FlateDecode") + # fmt: on # modify action dictionary of PushButton (super) self._widget_dictionary[Name("AA")][Name("D")][Name("S")] = Name("JavaScript") diff --git a/borb/pdf/canvas/layout/forms/text_area.py b/borb/pdf/canvas/layout/forms/text_area.py index 68c2a6960..b59d53f57 100644 --- a/borb/pdf/canvas/layout/forms/text_area.py +++ b/borb/pdf/canvas/layout/forms/text_area.py @@ -64,6 +64,9 @@ def _init_widget_dictionary(self, page: Page, layout_box: Rectangle) -> None: if self._widget_dictionary is not None: return + if "XRef" not in page.get_root(): + return + # init page and font resources assert self._font_size is not None font_resource_name: Name = self._get_font_resource_name( @@ -78,7 +81,7 @@ def _init_widget_dictionary(self, page: Page, layout_box: Rectangle) -> None: widget_normal_appearance: Stream = Stream() widget_normal_appearance[Name("Type")] = Name("XObject") widget_normal_appearance[Name("Subtype")] = Name("Form") - widget_normal_appearance[Name("BBox")] = List().set_can_be_referenced(False) # type: ignore [attr-defined] + widget_normal_appearance[Name("BBox")] = List().set_is_inline(True) # type: ignore [attr-defined] widget_normal_appearance["BBox"].append(bDecimal(0)) widget_normal_appearance["BBox"].append(bDecimal(0)) widget_normal_appearance["BBox"].append(bDecimal(layout_box.width)) @@ -105,7 +108,7 @@ def _init_widget_dictionary(self, page: Page, layout_box: Rectangle) -> None: self._widget_dictionary[Name("Type")] = Name("Annot") self._widget_dictionary[Name("Subtype")] = Name("Widget") self._widget_dictionary[Name("F")] = bDecimal(4) - self._widget_dictionary[Name("Rect")] = List().set_can_be_referenced(False) # type: ignore [attr-defined] + self._widget_dictionary[Name("Rect")] = List().set_is_inline(True) # type: ignore [attr-defined] self._widget_dictionary["Rect"].append(bDecimal(layout_box.x)) self._widget_dictionary["Rect"].append(bDecimal(layout_box.y + layout_box.height - (self._font_size + 1) * self._number_of_lines)) self._widget_dictionary["Rect"].append(bDecimal(layout_box.x + layout_box.width)) @@ -166,19 +169,15 @@ def _do_layout_without_padding( self._init_widget_dictionary(page, layout_rect) # set location - assert self._widget_dictionary is not None - self._widget_dictionary["AP"]["N"]["BBox"][2] = bDecimal(layout_box.width) - self._widget_dictionary["AP"]["N"]["BBox"][3] = bDecimal( - self._font_size * self._number_of_lines - ) - self._widget_dictionary["Rect"][0] = bDecimal(layout_box.x) - self._widget_dictionary["Rect"][1] = bDecimal( - layout_box.y - + layout_box.height - - (self._font_size + 1) * self._number_of_lines - ) - self._widget_dictionary["Rect"][2] = bDecimal(layout_box.x + layout_box.width) - self._widget_dictionary["Rect"][3] = bDecimal(layout_box.y + layout_box.height) + # fmt: off + if self._widget_dictionary is not None: + self._widget_dictionary["AP"]["N"]["BBox"][2] = bDecimal(layout_box.width) + self._widget_dictionary["AP"]["N"]["BBox"][3] = bDecimal(self._font_size * self._number_of_lines) + self._widget_dictionary["Rect"][0] = bDecimal(layout_box.x) + self._widget_dictionary["Rect"][1] = bDecimal(layout_box.y + layout_box.height - (self._font_size + 1) * self._number_of_lines) + self._widget_dictionary["Rect"][2] = bDecimal(layout_box.x + layout_box.width) + self._widget_dictionary["Rect"][3] = bDecimal(layout_box.y + layout_box.height) + # fmt: on # return Rectangle return layout_rect diff --git a/borb/pdf/canvas/layout/forms/text_field.py b/borb/pdf/canvas/layout/forms/text_field.py index 6b21bb11c..1890c72e6 100644 --- a/borb/pdf/canvas/layout/forms/text_field.py +++ b/borb/pdf/canvas/layout/forms/text_field.py @@ -61,6 +61,9 @@ def _init_widget_dictionary(self, page: Page, layout_box: Rectangle) -> None: if self._widget_dictionary is not None: return + if "XRef" not in page.get_root(): + return + # init page and font resources assert self._font_size is not None font_resource_name: Name = self._get_font_resource_name( @@ -75,7 +78,7 @@ def _init_widget_dictionary(self, page: Page, layout_box: Rectangle) -> None: widget_normal_appearance: Stream = Stream() widget_normal_appearance[Name("Type")] = Name("XObject") widget_normal_appearance[Name("Subtype")] = Name("Form") - widget_normal_appearance[Name("BBox")] = List().set_can_be_referenced(False) # type: ignore [attr-defined] + widget_normal_appearance[Name("BBox")] = List().set_is_inline(True) # type: ignore [attr-defined] widget_normal_appearance["BBox"].append(bDecimal(0)) widget_normal_appearance["BBox"].append(bDecimal(0)) widget_normal_appearance["BBox"].append(bDecimal(layout_box.width)) @@ -103,7 +106,7 @@ def _init_widget_dictionary(self, page: Page, layout_box: Rectangle) -> None: self._widget_dictionary[Name("Type")] = Name("Annot") self._widget_dictionary[Name("Subtype")] = Name("Widget") self._widget_dictionary[Name("F")] = bDecimal(4) - self._widget_dictionary[Name("Rect")] = List().set_can_be_referenced(False) # type: ignore [attr-defined] + self._widget_dictionary[Name("Rect")] = List().set_is_inline(True) # type: ignore [attr-defined] self._widget_dictionary["Rect"].append(bDecimal(layout_box.x)) self._widget_dictionary["Rect"].append(bDecimal(layout_box.y + layout_box.height - self._font_size)) self._widget_dictionary["Rect"].append(bDecimal(layout_box.x + layout_box.width)) @@ -162,13 +165,13 @@ def _do_layout_without_padding( # set location # fmt: off - assert self._widget_dictionary is not None - self._widget_dictionary["AP"]["N"]["BBox"][2] = bDecimal(layout_box.width) - self._widget_dictionary["AP"]["N"]["BBox"][3] = bDecimal(self._font_size) - self._widget_dictionary["Rect"][0] = bDecimal(layout_box.x) - self._widget_dictionary["Rect"][1] = bDecimal(layout_box.y + layout_box.height - self._font_size) - self._widget_dictionary["Rect"][2] = bDecimal(layout_box.x + layout_box.width) - self._widget_dictionary["Rect"][3] = bDecimal(layout_box.y + layout_box.height) + if self._widget_dictionary is not None: + self._widget_dictionary["AP"]["N"]["BBox"][2] = bDecimal(layout_box.width) + self._widget_dictionary["AP"]["N"]["BBox"][3] = bDecimal(self._font_size) + self._widget_dictionary["Rect"][0] = bDecimal(layout_box.x) + self._widget_dictionary["Rect"][1] = bDecimal(layout_box.y + layout_box.height - self._font_size) + self._widget_dictionary["Rect"][2] = bDecimal(layout_box.x + layout_box.width) + self._widget_dictionary["Rect"][3] = bDecimal(layout_box.y + layout_box.height) # fmt: on # return Rectangle diff --git a/borb/pdf/canvas/layout/image/unsplash.py b/borb/pdf/canvas/layout/image/unsplash.py new file mode 100644 index 000000000..a5f8c9107 --- /dev/null +++ b/borb/pdf/canvas/layout/image/unsplash.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +This factory implementation provides access to the unsplash API for retrieving images. +This class expects `keyring.get_password("unsplash", "access_key")` to have been set. +""" + +import json +import typing +from decimal import Decimal + +import keyring as keyring +import urllib.request + +from borb.pdf.canvas.layout.image.image import Image + + +class Unsplash: + """ + This factory implementation provides access to the unsplash API for retrieving images. + This class expects `keyring.get_password("unsplash", "access_key")` to have been set. + """ + + @staticmethod + def get_image( + keywords: typing.List[str], + width: typing.Optional[Decimal], + height: typing.Optional[Decimal], + ) -> Image: + """ + This function returns the best-matching Image (in terms of its dimensions) for a given list of keywords + :param keywords: the keywords to be searched + :param width: the desired width + :param height: the desired height + :return: an Image + """ + R: typing.Optional[Decimal] = None + if width is not None and height is not None: + R = width / height + + # build keyword str + keyword_str: str = "".join([(k + "+") for k in keywords])[:-1] + + # get access_key + unsplash_access_key: typing.Optional[str] = keyring.get_password( + "unsplash", "access_key" + ) + assert ( + unsplash_access_key is not None + ), "An access key must be specified to use the unsplash API." + + # fetch json + min_delta: typing.Optional[Decimal] = None + min_image: typing.Optional[typing.Any] = None + url: str = ( + "https://api.unsplash.com/search/photos?page=1&query=%s&client_id=%s" + % (keyword_str, unsplash_access_key) + ) + with urllib.request.urlopen(url) as response: + for result in json.loads(response.read().decode())["results"]: + if "width" not in result: + continue + if "height" not in result: + continue + if "urls" not in result: + continue + if "regular" not in result["urls"]: + continue + w: Decimal = Decimal(result["width"]) + h: Decimal = Decimal(result["height"]) + r: Decimal = w / h + + delta: Decimal = round(abs(r - R), 3) + if min_delta is None or delta < min_delta: + min_image = result + + # return + return Image(min_image["urls"]["regular"], width=width, height=height) diff --git a/borb/pdf/canvas/layout/shape/disjoint_shape.py b/borb/pdf/canvas/layout/shape/disjoint_shape.py index 0bce2e4f1..5ccdefe18 100644 --- a/borb/pdf/canvas/layout/shape/disjoint_shape.py +++ b/borb/pdf/canvas/layout/shape/disjoint_shape.py @@ -5,7 +5,7 @@ This class represents a generic disjoint shape (specified by a List of lines). It has convenience methods to calculate width and height, perform scaling, etc """ - +import math from decimal import Decimal import typing @@ -59,6 +59,20 @@ def get_height(self) -> Decimal: max_y = max([max(x[0][1], x[1][1]) for x in self._lines]) return max_y - min_y + def rotate(self, angle_in_radians: float) -> "Shape": + """ + This function rotates the DisjointShape for a given angle + :param angle_in_radians: the angle + :return: this DisjointShape + """ + a: Decimal = Decimal(math.cos(angle_in_radians)) + b: Decimal = Decimal(-math.sin(angle_in_radians)) + c: Decimal = Decimal(math.sin(angle_in_radians)) + d: Decimal = Decimal(math.cos(angle_in_radians)) + self._lines = [((a*l[0][0] + c*l[0][1], b*l[0][0] + d*l[0][1]), + (a*l[1][0] + c*l[1][1], b*l[1][0] + d*l[1][1])) for l in self._lines] + return self + def scale_to_fit(self, max_width: Decimal, max_height: Decimal) -> "DisjointShape": """ This method scales this DisjointShape to fit a given max. width / height @@ -80,7 +94,7 @@ def scale_to_fit(self, max_width: Decimal, max_height: Decimal) -> "DisjointShap ] return self - def translate_to_align( + def move_to( self, lower_left_x: Decimal, lower_left_y: Decimal ) -> "DisjointShape": """ @@ -107,7 +121,7 @@ def _do_layout_without_padding( self.scale_to_fit(bounding_box.width, bounding_box.height) # translate points to fit in box - self.translate_to_align( + self.move_to( bounding_box.x, bounding_box.y + bounding_box.height - self.get_height() ) diff --git a/borb/pdf/canvas/layout/shape/gradient_colored_disjoint_shape.py b/borb/pdf/canvas/layout/shape/gradient_colored_disjoint_shape.py index ca97b5709..c9454b144 100644 --- a/borb/pdf/canvas/layout/shape/gradient_colored_disjoint_shape.py +++ b/borb/pdf/canvas/layout/shape/gradient_colored_disjoint_shape.py @@ -61,7 +61,7 @@ def _do_layout_without_padding( self.scale_to_fit(bounding_box.width, bounding_box.height) # translate points to fit in box - self.translate_to_align( + self.move_to( bounding_box.x, bounding_box.y + bounding_box.height - self.get_height() ) diff --git a/borb/pdf/canvas/layout/shape/shape.py b/borb/pdf/canvas/layout/shape/shape.py index 2312a05e8..60ef603f8 100644 --- a/borb/pdf/canvas/layout/shape/shape.py +++ b/borb/pdf/canvas/layout/shape/shape.py @@ -5,6 +5,7 @@ This class represents a generic shape (specified by a List of points). It has convenience methods to calculate width and height, perform scaling, etc """ +import math import typing from decimal import Decimal from math import sqrt @@ -110,7 +111,21 @@ def scale_up( self._points = [(x[0], x[1] * h_scale) for x in self._points] return self - def translate_to_align(self, lower_left_x: Decimal, lower_left_y: Decimal): + def rotate(self, angle_in_radians: float) -> "Shape": + """ + This function rotates the Shape for a given angle + :param angle_in_radians: the angle + :return: this Shape + """ + a: Decimal = Decimal(math.cos(angle_in_radians)) + b: Decimal = Decimal(-math.sin(angle_in_radians)) + c: Decimal = Decimal(math.sin(angle_in_radians)) + d: Decimal = Decimal(math.cos(angle_in_radians)) + self._points = [(a*x+c*y, + b*x+d*y) for x,y in self._points] + return self + + def move_to(self, lower_left_x: Decimal, lower_left_y: Decimal) -> "Shape": """ This method translates this Shape so its lower left corner aligns with the given coordinates """ @@ -119,13 +134,14 @@ def translate_to_align(self, lower_left_x: Decimal, lower_left_y: Decimal): delta_x = lower_left_x - min_x delta_y = lower_left_y - min_y self._points = [(x[0] + delta_x, x[1] + delta_y) for x in self._points] + return self def _do_layout_without_padding( self, page: Page, bounding_box: Rectangle ) -> Rectangle: # translate points to fit in box - self.translate_to_align( + self.move_to( bounding_box.x, bounding_box.y + bounding_box.height - self.get_height() ) diff --git a/borb/pdf/canvas/line_art/line_art_factory.py b/borb/pdf/canvas/line_art/line_art_factory.py index 4ff76d1f4..2a81122d7 100644 --- a/borb/pdf/canvas/line_art/line_art_factory.py +++ b/borb/pdf/canvas/line_art/line_art_factory.py @@ -20,6 +20,70 @@ class LineArtFactory: such as arrows, rectangles, triangles, regular n-gons, stars, etc """ + def EURion( + bounding_box: Rectangle, + ) -> typing.List[ + typing.Tuple[typing.Tuple[Decimal, Decimal], typing.Tuple[Decimal, Decimal]] + ]: + """ + The EURion constellation (also known as Omron rings or doughnuts) is a pattern of symbols incorporated into a number of secure documents + such as banknotes and ownership title certificates designs worldwide since about 1996. + It is added to help imaging software detect the presence of such a document in a digital image. + Such software can then block the user from reproducing banknotes to prevent counterfeiting using colour photocopiers. + According to research from 2004, the EURion constellation is used for colour photocopiers but probably not used in computer software. + It has been reported that Adobe Photoshop will not allow editing of an image of a banknote, + but in some versions this is believed to be due to a different, unknown digital watermark rather than the EURion constellation. + :return: + """ + # 269, 73 r 25 s 17 + # 85, 170 r 25 s 17 + # 237, 228 r 25 s 17 + # 475, 280 r 25 s 17 + # 263, 487 r 25 s 17 + line_segments = [] + for x, y in [(269, 73), (85, 170), (237, 228), (475, 280), (263, 487)]: + + # calculate points of a circle + circle_segments = [] + for i in range(0, 360): + px: Decimal = Decimal(math.cos(math.radians(i)) * 25 - (25 / 2) + x) + py: Decimal = Decimal(math.sin(math.radians(i)) * 25 - (25 / 2) + y) + circle_segments.append((px, py)) + + # add segments + line_segments.extend( + [ + ( + circle_segments[i], + circle_segments[(i + 1) % len(circle_segments)], + ) + for i in range(0, len(circle_segments)) + ] + ) + + # scale + min_x: Decimal = min([min(l[0][0], l[1][0]) for l in line_segments]) + max_x: Decimal = max([max(l[0][0], l[1][0]) for l in line_segments]) + w: Decimal = max_x - min_x + min_y: Decimal = min([min(l[0][1], l[1][1]) for l in line_segments]) + max_y: Decimal = max([max(l[0][1], l[1][1]) for l in line_segments]) + h: Decimal = max_y - min_y + w_scale = bounding_box.get_width() / w + h_scale = bounding_box.get_height() / h + line_segments = [ + ( + (l[0][0] * w_scale, l[0][1] * h_scale), + (l[1][0] * w_scale, l[1][1] * h_scale), + ) + for l in line_segments + ] + + # translate + # TODO + + # return + return line_segments + @staticmethod def lissajours( bounding_box: Rectangle, x_frequency: int, y_frequency: int diff --git a/borb/pdf/document/__init__.py b/borb/pdf/document/__init__.py index e69de29bb..bcf77caad 100644 --- a/borb/pdf/document/__init__.py +++ b/borb/pdf/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/pdf/document/document.py b/borb/pdf/document/document.py index e51e9e465..877917c87 100644 --- a/borb/pdf/document/document.py +++ b/borb/pdf/document/document.py @@ -201,7 +201,7 @@ def add_outline( contents to display the document’s structure to the user. This function adds an outline to this Document """ - destination = List().set_can_be_referenced(False) # type: ignore [attr-defined] + destination = List().set_is_inline(True) # type: ignore [attr-defined] destination.append(bDecimal(page_nr)) destination.append(destination_type.value) if destination_type == DestinationType.X_Y_Z: diff --git a/borb/pdf/document/name_tree.py b/borb/pdf/document/name_tree.py index dbaddc642..3bc7e39cb 100644 --- a/borb/pdf/document/name_tree.py +++ b/borb/pdf/document/name_tree.py @@ -1,3 +1,6 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + """ Some categories of objects in a PDF file can be referred to by name rather than by object reference. The correspondence between names and objects is established by the document’s name dictionary (PDF 1.2), @@ -31,8 +34,13 @@ def __init__(self, document: Dictionary, name: Name): self._document: Dictionary = document self._name: Name = name - def put(self, key: str, value: typing.Any): - + def put(self, key: str, value: typing.Any) -> "NameTree": + """ + This function adds a key/value pair in this NameTree + :param key: the key + :param value: the value + :return: self + """ assert "XRef" in self._document assert "Trailer" in self._document["XRef"] assert "Root" in self._document["XRef"]["Trailer"] @@ -70,6 +78,9 @@ def put(self, key: str, value: typing.Any): else: self._put_existing(parent, key, value) + # return + return self + def _put_new(self, parent: Dictionary, key: str, value: typing.Any): kid = Dictionary() @@ -100,14 +111,25 @@ def _put_existing(self, parent: Dictionary, key: str, value: typing.Any): # dictionary methods # - def get_keys(self) -> typing.List[String]: + def keys(self) -> typing.List[String]: + """ + This function returns the keys in this NameTree + :return: the keys in this NameTree + """ return [k for k, v in self.items()] - def get_values(self) -> typing.List[typing.Any]: + def values(self) -> typing.List[typing.Any]: + """ + This function returns the values in this NameTree + :return: the values in this NameTree + """ return [v for k, v in self.items()] def items(self) -> typing.Iterable[typing.Tuple[String, typing.Any]]: - + """ + This function returns all key/value pairs in this NameTree + :return: all key/value pairs in this NameTree + """ assert "XRef" in self._document assert "Trailer" in self._document["XRef"] assert "Root" in self._document["XRef"]["Trailer"] diff --git a/borb/pdf/page/page.py b/borb/pdf/page/page.py index ff8adf820..fa30c52ec 100644 --- a/borb/pdf/page/page.py +++ b/borb/pdf/page/page.py @@ -34,7 +34,7 @@ def __init__(self, width: Decimal = Decimal(595), height: Decimal = Decimal(842) self[Name("Type")] = Name("Page") # size: A4 portrait - self[Name("MediaBox")] = List().set_can_be_referenced(False) # type: ignore [attr-defined] + self[Name("MediaBox")] = List().set_is_inline(True) # type: ignore [attr-defined] self["MediaBox"].append(bDecimal(0)) self["MediaBox"].append(bDecimal(0)) self["MediaBox"].append(bDecimal(width)) @@ -219,6 +219,11 @@ def append_annotation(self, annotation: Annotation) -> "Page": :return: self """ + # (Optional; PDF 1.4) The annotation name, a text string uniquely + # identifying it among all the annotations on its page. + len_annots = len(self["Annots"]) if "Annots" in self else 0 + annotation[Name("NM")] = String("annotation-{0:03d}".format(len_annots)) + # (Optional except as noted below; PDF 1.3; not used in FDF files) An # indirect reference to the page object with which this annotation is # associated. diff --git a/borb/pdf/xref/rebuilt_xref.py b/borb/pdf/xref/rebuilt_xref.py index b135aca42..68448e854 100644 --- a/borb/pdf/xref/rebuilt_xref.py +++ b/borb/pdf/xref/rebuilt_xref.py @@ -54,15 +54,18 @@ def read( while i < len(bytes_in_pdf): # 0 0 obj if ( - 48 <= bytes_in_pdf[i] <= 57 # - and bytes_in_pdf[i + 1] == 32 # - and 48 <= bytes_in_pdf[i + 2] <= 57 # - and bytes_in_pdf[i + 3] == 32 # - and bytes_in_pdf[i + 4] == 111 # 'o' - and bytes_in_pdf[i + 5] == 98 # 'b' - and bytes_in_pdf[i + 6] == 106 # 'j' + 48 <= bytes_in_pdf[i] <= 57 # + and bytes_in_pdf[i + 1] == 32 # + and 48 <= bytes_in_pdf[i + 2] <= 57 # + and bytes_in_pdf[i + 3] == 32 # + and bytes_in_pdf[i + 4] == 111 # 'o' + and bytes_in_pdf[i + 5] == 98 # 'b' + and bytes_in_pdf[i + 6] == 106 # 'j' ): - logger.debug("%d %d obj at %d" % (bytes_in_pdf[i] - 48, bytes_in_pdf[i+1] - 48, i)) + logger.debug( + "%d %d obj at %d" + % (bytes_in_pdf[i] - 48, bytes_in_pdf[i + 1] - 48, i) + ) self._entries.append( Reference( object_number=bytes_in_pdf[i] - 48, @@ -75,19 +78,27 @@ def read( # 00 0 obj if ( - 48 <= bytes_in_pdf[i] <= 57 # - and 48 <= bytes_in_pdf[i+1] <= 57 # - and bytes_in_pdf[i + 2] == 32 # - and 48 <= bytes_in_pdf[i + 3] <= 57 # - and bytes_in_pdf[i + 4] == 32 # - and bytes_in_pdf[i + 5] == 111 # 'o' - and bytes_in_pdf[i + 6] == 98 # 'b' - and bytes_in_pdf[i + 7] == 106 # 'j' + 48 <= bytes_in_pdf[i] <= 57 # + and 48 <= bytes_in_pdf[i + 1] <= 57 # + and bytes_in_pdf[i + 2] == 32 # + and 48 <= bytes_in_pdf[i + 3] <= 57 # + and bytes_in_pdf[i + 4] == 32 # + and bytes_in_pdf[i + 5] == 111 # 'o' + and bytes_in_pdf[i + 6] == 98 # 'b' + and bytes_in_pdf[i + 7] == 106 # 'j' ): - logger.debug("%d %d obj at %d" % ((bytes_in_pdf[i] - 48) * 10 + (bytes_in_pdf[i+1] - 48), bytes_in_pdf[i+3] - 48, i)) + logger.debug( + "%d %d obj at %d" + % ( + (bytes_in_pdf[i] - 48) * 10 + (bytes_in_pdf[i + 1] - 48), + bytes_in_pdf[i + 3] - 48, + i, + ) + ) self._entries.append( Reference( - object_number=(bytes_in_pdf[i] - 48) * 10 + (bytes_in_pdf[i+1] - 48), + object_number=(bytes_in_pdf[i] - 48) * 10 + + (bytes_in_pdf[i + 1] - 48), generation_number=bytes_in_pdf[i + 3] - 48, byte_offset=i, ) @@ -97,18 +108,22 @@ def read( # 000 0 obj if ( - 48 <= bytes_in_pdf[i] <= 57 # - and 48 <= bytes_in_pdf[i + 1] <= 57 # - and 48 <= bytes_in_pdf[i + 2] <= 57 # - and bytes_in_pdf[i + 3] == 32 # - and 48 <= bytes_in_pdf[i + 4] <= 57 # - and bytes_in_pdf[i + 5] == 32 # - and bytes_in_pdf[i + 6] == 111 # 'o' - and bytes_in_pdf[i + 7] == 98 # 'b' - and bytes_in_pdf[i + 8] == 106 # 'j' + 48 <= bytes_in_pdf[i] <= 57 # + and 48 <= bytes_in_pdf[i + 1] <= 57 # + and 48 <= bytes_in_pdf[i + 2] <= 57 # + and bytes_in_pdf[i + 3] == 32 # + and 48 <= bytes_in_pdf[i + 4] <= 57 # + and bytes_in_pdf[i + 5] == 32 # + and bytes_in_pdf[i + 6] == 111 # 'o' + and bytes_in_pdf[i + 7] == 98 # 'b' + and bytes_in_pdf[i + 8] == 106 # 'j' ): - obj_nr: int = (bytes_in_pdf[i] - 48) * 100 + (bytes_in_pdf[i+1] - 48) * 10 + (bytes_in_pdf[i+2] - 48) - logger.debug("%d %d obj at %d" % (obj_nr, bytes_in_pdf[i+4] - 48, i)) + obj_nr: int = ( + (bytes_in_pdf[i] - 48) * 100 + + (bytes_in_pdf[i + 1] - 48) * 10 + + (bytes_in_pdf[i + 2] - 48) + ) + logger.debug("%d %d obj at %d" % (obj_nr, bytes_in_pdf[i + 4] - 48, i)) self._entries.append( Reference( object_number=obj_nr, @@ -121,9 +136,9 @@ def read( # trailer if ( - bytes_in_pdf[i] == 116 # 't' + bytes_in_pdf[i] == 116 # 't' and bytes_in_pdf[i + 1] == 114 # 'r' - and bytes_in_pdf[i + 2] == 97 # 'a' + and bytes_in_pdf[i + 2] == 97 # 'a' and bytes_in_pdf[i + 3] == 105 # 'i' and bytes_in_pdf[i + 4] == 108 # 'l' and bytes_in_pdf[i + 5] == 101 # 'e' diff --git a/borb/toolkit/export/markdown_to_pdf/read/transformer.py b/borb/toolkit/export/markdown_to_pdf/read/transformer.py index 68e8cbd20..5db6dbaff 100644 --- a/borb/toolkit/export/markdown_to_pdf/read/transformer.py +++ b/borb/toolkit/export/markdown_to_pdf/read/transformer.py @@ -64,6 +64,12 @@ def get_document(self) -> Document: def get_parent_layout_element( self, ) -> typing.Union[Document, Page, LayoutElement, PageLayout]: + """ + This function returns the parent LayoutElement object. + e.g.: In case of a Page being laid out, this is the PageLayout or Document. + In case of a TableCell being laid out, this would typically be the Table object. + :return: the parent LayoutElement object + """ return self._parent_layout_element diff --git a/release_notes.md b/release_notes.md index 3c8143825..84aed14f9 100644 --- a/release_notes.md +++ b/release_notes.md @@ -1,8 +1,13 @@ -# :mega: borb release 2.0.21 +# :mega: borb release 2.0.22 This release is a small feature release: -- `borb` can now read some broken PDF documents -- tests have been added for this use case -- more documentation has been added in general (less than 10 undocumented methods) -- border for `RemoteGoToAnnotation` has been removed \ No newline at end of file +- Test have been added corresponding to issues on GitHub. +- More documentation has been added in general. No undocumented public methods! +- Unsplash API has been added, to ensure you can build rapid prototypes for Documents by just specifying keywords for images, rather than having to look for the perfect `Image` +- Small bugfix w.r.t. annotation names +- Small improvement in writing a PDF to bytes, inline array objects no longer have trailing newline character +- Small bugfix to fix layout of `FormField` objects using `FlexibleWidthColumnTable` +- Added some imports to `borb/pdf/__init__.py` to make it easier to import `borb` objects in general +- Added the EURion symbol to the `LineArtFactory` +- Added methods to rotate `Shape` and `DisjointShape` \ No newline at end of file diff --git a/setup.py b/setup.py index 7fc060316..63b3f7ceb 100644 --- a/setup.py +++ b/setup.py @@ -29,7 +29,7 @@ setuptools.setup( name="borb", - version="2.0.21", + version="2.0.22", 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/corpus/test_copy_document_compare_size.py b/tests/corpus/test_copy_document_compare_size.py index 9d1b99bd4..3e5903ece 100644 --- a/tests/corpus/test_copy_document_compare_size.py +++ b/tests/corpus/test_copy_document_compare_size.py @@ -42,7 +42,7 @@ def __init__(self, methodName="runTest"): self.number_of_fails: int = 0 self.memory_stats_per_document: typing.Dict[str, typing.Tuple[int, int]] = {} - #@unittest.skip + @unittest.skip def test_against_entire_corpus(self): pdf_file_names = os.listdir(self.corpus_dir) pdfs = [ diff --git a/tests/corpus/test_copy_document_resize_images_compare_size.py b/tests/corpus/test_copy_document_resize_images_compare_size.py index 8e6c729da..728fd8a21 100644 --- a/tests/corpus/test_copy_document_resize_images_compare_size.py +++ b/tests/corpus/test_copy_document_resize_images_compare_size.py @@ -43,7 +43,7 @@ def __init__(self, methodName="runTest"): self.number_of_fails: int = 0 self.memory_stats_per_document: typing.Dict[str, typing.Tuple[int, int]] = {} - #@unittest.skip + @unittest.skip def test_against_entire_corpus(self): pdf_file_names = os.listdir(self.corpus_dir) pdfs = [ diff --git a/tests/corpus/test_extract_text_expect_ground_truth.py b/tests/corpus/test_extract_text_expect_ground_truth.py index ec4267563..4cbcfadb9 100644 --- a/tests/corpus/test_extract_text_expect_ground_truth.py +++ b/tests/corpus/test_extract_text_expect_ground_truth.py @@ -46,7 +46,7 @@ def __init__(self, methodName="runTest"): self.time_per_document: typing.Dict[str, float] = {} self.fails_per_document: typing.Dict[str, int] = [] - #@unittest.skip + @unittest.skip def test_against_entire_corpus(self): pdf_file_names = os.listdir(self.corpus_dir) pdfs = [ diff --git a/tests/corpus/test_open_document.py b/tests/corpus/test_open_document.py index 142d5e19a..58eaadbd6 100644 --- a/tests/corpus/test_open_document.py +++ b/tests/corpus/test_open_document.py @@ -45,7 +45,7 @@ def __init__(self, methodName="runTest"): self.time_per_document: typing.Dict[str, float] = {} self.memory_stats_per_document: typing.Dict[str, typing.Tuple[int, int]] = {} - #@unittest.skip + @unittest.skip def test_against_entire_corpus(self): pdf_file_names = os.listdir(self.corpus_dir) pdfs = [ diff --git a/tests/misc/encryption/__init__.py b/tests/misc/encryption/__init__.py new file mode 100644 index 000000000..e69de29bb 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 961639360..1232df8ee 100644 Binary files a/tests/output/test_add_all_rubber_stamp_annotations/output.pdf and b/tests/output/test_add_all_rubber_stamp_annotations/output.pdf differ diff --git a/tests/output/test_add_circle_annotation/output.pdf b/tests/output/test_add_circle_annotation/output.pdf index a68621052..168e73f76 100644 Binary files a/tests/output/test_add_circle_annotation/output.pdf and b/tests/output/test_add_circle_annotation/output.pdf differ 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 c9cb81ce6..1e07c5919 100644 Binary files a/tests/output/test_add_free_text_annotation/output_001.pdf and b/tests/output/test_add_free_text_annotation/output_001.pdf differ 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 c83ac375b..6dac051bd 100644 Binary files a/tests/output/test_add_free_text_annotation/output_002.pdf and b/tests/output/test_add_free_text_annotation/output_002.pdf differ diff --git a/tests/output/test_add_highlight_annotation/output_001.pdf b/tests/output/test_add_highlight_annotation/output_001.pdf index e8ead2cf1..0cbd45b1b 100644 Binary files a/tests/output/test_add_highlight_annotation/output_001.pdf and b/tests/output/test_add_highlight_annotation/output_001.pdf differ diff --git a/tests/output/test_add_highlight_annotation/output_002.pdf b/tests/output/test_add_highlight_annotation/output_002.pdf index b58577a3c..cf9886437 100644 Binary files a/tests/output/test_add_highlight_annotation/output_002.pdf and b/tests/output/test_add_highlight_annotation/output_002.pdf differ diff --git a/tests/output/test_add_large_amount_of_headings/output_001.pdf b/tests/output/test_add_large_amount_of_headings/output_001.pdf index bc5206c5f..d4720a559 100644 Binary files a/tests/output/test_add_large_amount_of_headings/output_001.pdf and b/tests/output/test_add_large_amount_of_headings/output_001.pdf differ diff --git a/tests/output/test_add_large_amount_of_headings/output_002.pdf b/tests/output/test_add_large_amount_of_headings/output_002.pdf index 57d50fa41..93643f749 100644 Binary files a/tests/output/test_add_large_amount_of_headings/output_002.pdf and b/tests/output/test_add_large_amount_of_headings/output_002.pdf differ diff --git a/tests/output/test_add_line_annotation/output_001.pdf b/tests/output/test_add_line_annotation/output_001.pdf index 3379aefb8..c7bbaed65 100644 Binary files a/tests/output/test_add_line_annotation/output_001.pdf and b/tests/output/test_add_line_annotation/output_001.pdf differ diff --git a/tests/output/test_add_line_annotation/output_002.pdf b/tests/output/test_add_line_annotation/output_002.pdf index fe6fc1cb9..c1b5327d3 100644 Binary files a/tests/output/test_add_line_annotation/output_002.pdf and b/tests/output/test_add_line_annotation/output_002.pdf differ diff --git a/tests/output/test_add_outline/output_001.pdf b/tests/output/test_add_outline/output_001.pdf index da603ce2c..6346ecd5c 100644 Binary files a/tests/output/test_add_outline/output_001.pdf and b/tests/output/test_add_outline/output_001.pdf differ diff --git a/tests/output/test_add_outline/output_002.pdf b/tests/output/test_add_outline/output_002.pdf index 03f84498b..5c291f2f6 100644 Binary files a/tests/output/test_add_outline/output_002.pdf and b/tests/output/test_add_outline/output_002.pdf differ 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 ff30ab6e5..661c6e586 100644 Binary files a/tests/output/test_add_polygon_annotation_using_line_art_factory/output.pdf and b/tests/output/test_add_polygon_annotation_using_line_art_factory/output.pdf differ 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 6e4a5b411..01d179f2a 100644 Binary files a/tests/output/test_add_polyline_annotation_using_line_art_factory/output.pdf and b/tests/output/test_add_polyline_annotation_using_line_art_factory/output.pdf differ diff --git a/tests/output/test_add_redact_annotation/output_001.pdf b/tests/output/test_add_redact_annotation/output_001.pdf index 07e1ea167..c7562c543 100644 Binary files a/tests/output/test_add_redact_annotation/output_001.pdf and b/tests/output/test_add_redact_annotation/output_001.pdf differ diff --git a/tests/output/test_add_redact_annotation/output_002.pdf b/tests/output/test_add_redact_annotation/output_002.pdf index 32c969c92..cab4266f6 100644 Binary files a/tests/output/test_add_redact_annotation/output_002.pdf and b/tests/output/test_add_redact_annotation/output_002.pdf differ diff --git a/tests/output/test_add_redact_annotation/output_003.pdf b/tests/output/test_add_redact_annotation/output_003.pdf index 20fb4c3ca..b8942d64f 100644 Binary files a/tests/output/test_add_redact_annotation/output_003.pdf and b/tests/output/test_add_redact_annotation/output_003.pdf differ diff --git a/tests/output/test_add_redact_annotation/output_004.pdf b/tests/output/test_add_redact_annotation/output_004.pdf index c4fda60c1..0c91ed3ed 100644 Binary files a/tests/output/test_add_redact_annotation/output_004.pdf and b/tests/output/test_add_redact_annotation/output_004.pdf differ diff --git a/tests/output/test_add_redact_annotation/output_005.pdf b/tests/output/test_add_redact_annotation/output_005.pdf index 6a3f24dec..29b81ea8f 100644 Binary files a/tests/output/test_add_redact_annotation/output_005.pdf and b/tests/output/test_add_redact_annotation/output_005.pdf differ 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 8f6b3e766..2ca3f1e96 100644 Binary files a/tests/output/test_add_remote_go_to_annotation/output_001.pdf and b/tests/output/test_add_remote_go_to_annotation/output_001.pdf differ 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 ce790f392..44d991012 100644 Binary files a/tests/output/test_add_remote_go_to_annotation/output_002.pdf and b/tests/output/test_add_remote_go_to_annotation/output_002.pdf differ diff --git a/tests/output/test_add_sound_annotation/output_001.pdf b/tests/output/test_add_sound_annotation/output_001.pdf index 2864fee96..3d04e75f2 100644 Binary files a/tests/output/test_add_sound_annotation/output_001.pdf and b/tests/output/test_add_sound_annotation/output_001.pdf differ diff --git a/tests/output/test_add_sound_annotation/output_002.pdf b/tests/output/test_add_sound_annotation/output_002.pdf index 5fc938ad8..a95d02020 100644 Binary files a/tests/output/test_add_sound_annotation/output_002.pdf and b/tests/output/test_add_sound_annotation/output_002.pdf differ diff --git a/tests/output/test_add_square_annotation/output.pdf b/tests/output/test_add_square_annotation/output.pdf index 73d422ab5..e1c1a0a24 100644 Binary files a/tests/output/test_add_square_annotation/output.pdf and b/tests/output/test_add_square_annotation/output.pdf differ 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 55bfc22ea..7494ed395 100644 Binary files a/tests/output/test_add_square_annotation_in_free_space/output_001.pdf and b/tests/output/test_add_square_annotation_in_free_space/output_001.pdf differ diff --git a/tests/output/test_add_square_annotation_in_free_space/output_002.pdf b/tests/output/test_add_square_annotation_in_free_space/output_002.pdf index b4374371f..f60dc6a9a 100644 Binary files a/tests/output/test_add_square_annotation_in_free_space/output_002.pdf and b/tests/output/test_add_square_annotation_in_free_space/output_002.pdf differ diff --git a/tests/output/test_add_squiggle_annotation/output_001.pdf b/tests/output/test_add_squiggle_annotation/output_001.pdf index 8c2c07653..dea272479 100644 Binary files a/tests/output/test_add_squiggle_annotation/output_001.pdf and b/tests/output/test_add_squiggle_annotation/output_001.pdf differ diff --git a/tests/output/test_add_squiggle_annotation/output_002.pdf b/tests/output/test_add_squiggle_annotation/output_002.pdf index 0f2d62e8d..508886f43 100644 Binary files a/tests/output/test_add_squiggle_annotation/output_002.pdf and b/tests/output/test_add_squiggle_annotation/output_002.pdf differ diff --git a/tests/output/test_add_strikeout_annotation/output_001.pdf b/tests/output/test_add_strikeout_annotation/output_001.pdf index 0b1b848b7..302d7695a 100644 Binary files a/tests/output/test_add_strikeout_annotation/output_001.pdf and b/tests/output/test_add_strikeout_annotation/output_001.pdf differ diff --git a/tests/output/test_add_strikeout_annotation/output_002.pdf b/tests/output/test_add_strikeout_annotation/output_002.pdf index 05bafb9a9..d8b90e02c 100644 Binary files a/tests/output/test_add_strikeout_annotation/output_002.pdf and b/tests/output/test_add_strikeout_annotation/output_002.pdf differ diff --git a/tests/output/test_add_super_mario_annotation/output.pdf b/tests/output/test_add_super_mario_annotation/output.pdf index d21ae71f9..cabedfb88 100644 Binary files a/tests/output/test_add_super_mario_annotation/output.pdf and b/tests/output/test_add_super_mario_annotation/output.pdf differ diff --git a/tests/output/test_add_text_annotation/output_001.pdf b/tests/output/test_add_text_annotation/output_001.pdf index bff5a0db5..08fec08dc 100644 Binary files a/tests/output/test_add_text_annotation/output_001.pdf and b/tests/output/test_add_text_annotation/output_001.pdf differ diff --git a/tests/output/test_add_text_annotation/output_002.pdf b/tests/output/test_add_text_annotation/output_002.pdf index a4563a67a..8031c4400 100644 Binary files a/tests/output/test_add_text_annotation/output_002.pdf and b/tests/output/test_add_text_annotation/output_002.pdf differ diff --git a/tests/output/test_add_underline_annotation/output_001.pdf b/tests/output/test_add_underline_annotation/output_001.pdf index 1fb25a388..6d411f610 100644 Binary files a/tests/output/test_add_underline_annotation/output_001.pdf and b/tests/output/test_add_underline_annotation/output_001.pdf differ diff --git a/tests/output/test_add_underline_annotation/output_002.pdf b/tests/output/test_add_underline_annotation/output_002.pdf index 2ea998015..94a030f24 100644 Binary files a/tests/output/test_add_underline_annotation/output_002.pdf and b/tests/output/test_add_underline_annotation/output_002.pdf differ diff --git a/tests/output/test_analogous_color_scheme/output.pdf b/tests/output/test_analogous_color_scheme/output.pdf index 7ebdedab6..f6d008783 100644 Binary files a/tests/output/test_analogous_color_scheme/output.pdf and b/tests/output/test_analogous_color_scheme/output.pdf differ diff --git a/tests/output/test_annotation_name/output.pdf b/tests/output/test_annotation_name/output.pdf new file mode 100644 index 000000000..2901f6b6d Binary files /dev/null and b/tests/output/test_annotation_name/output.pdf differ diff --git a/tests/output/test_annotation_name/output_ground_truth.png b/tests/output/test_annotation_name/output_ground_truth.png new file mode 100644 index 000000000..ca07b05e3 Binary files /dev/null and b/tests/output/test_annotation_name/output_ground_truth.png differ diff --git a/tests/output/test_append_embedded_file/output_001.pdf b/tests/output/test_append_embedded_file/output_001.pdf index 73b3a1a21..a6d04bc5a 100644 Binary files a/tests/output/test_append_embedded_file/output_001.pdf and b/tests/output/test_append_embedded_file/output_001.pdf differ diff --git a/tests/output/test_append_embedded_file/output_002.pdf b/tests/output/test_append_embedded_file/output_002.pdf index 2212ce6ab..15f41a6b3 100644 Binary files a/tests/output/test_append_embedded_file/output_002.pdf and b/tests/output/test_append_embedded_file/output_002.pdf differ diff --git a/tests/output/test_append_embedded_javascript/output_001.pdf b/tests/output/test_append_embedded_javascript/output_001.pdf index 7a97f19d2..a5bc64412 100644 Binary files a/tests/output/test_append_embedded_javascript/output_001.pdf and b/tests/output/test_append_embedded_javascript/output_001.pdf differ diff --git a/tests/output/test_apply_redaction_annotations/output_001.pdf b/tests/output/test_apply_redaction_annotations/output_001.pdf index 31ea93cdb..708865ac8 100644 Binary files a/tests/output/test_apply_redaction_annotations/output_001.pdf and b/tests/output/test_apply_redaction_annotations/output_001.pdf differ diff --git a/tests/output/test_apply_redaction_annotations/output_002.pdf b/tests/output/test_apply_redaction_annotations/output_002.pdf index add1c9e2f..558c49cbc 100644 Binary files a/tests/output/test_apply_redaction_annotations/output_002.pdf and b/tests/output/test_apply_redaction_annotations/output_002.pdf differ diff --git a/tests/output/test_apply_redaction_annotations/output_003.pdf b/tests/output/test_apply_redaction_annotations/output_003.pdf index aa9e9aab0..1d0e66608 100644 Binary files a/tests/output/test_apply_redaction_annotations/output_003.pdf and b/tests/output/test_apply_redaction_annotations/output_003.pdf differ diff --git a/tests/output/test_apply_redaction_annotations/output_004.pdf b/tests/output/test_apply_redaction_annotations/output_004.pdf index f3c5a5f05..2bf60dc12 100644 Binary files a/tests/output/test_apply_redaction_annotations/output_004.pdf and b/tests/output/test_apply_redaction_annotations/output_004.pdf differ diff --git a/tests/output/test_apply_redaction_annotations/output_005.pdf b/tests/output/test_apply_redaction_annotations/output_005.pdf index 6f64f7b71..0a2004de4 100644 Binary files a/tests/output/test_apply_redaction_annotations/output_005.pdf and b/tests/output/test_apply_redaction_annotations/output_005.pdf differ diff --git a/tests/output/test_apply_redaction_annotations/output_006.pdf b/tests/output/test_apply_redaction_annotations/output_006.pdf index 4b860e9a6..81fa52f4e 100644 Binary files a/tests/output/test_apply_redaction_annotations/output_006.pdf and b/tests/output/test_apply_redaction_annotations/output_006.pdf differ diff --git a/tests/output/test_browser_layout_inline_next_line/output.pdf b/tests/output/test_browser_layout_inline_next_line/output.pdf index 14a82a868..b64bef0a2 100644 Binary files a/tests/output/test_browser_layout_inline_next_line/output.pdf and b/tests/output/test_browser_layout_inline_next_line/output.pdf differ 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 daa41a345..a9dae1d6c 100644 Binary files a/tests/output/test_change_info_dictionary_author/output_001.pdf and b/tests/output/test_change_info_dictionary_author/output_001.pdf differ 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 a28beb4d6..5cbab19b4 100644 Binary files a/tests/output/test_change_info_dictionary_author/output_002.pdf and b/tests/output/test_change_info_dictionary_author/output_002.pdf differ diff --git a/tests/output/test_concat_documents/output_000.pdf b/tests/output/test_concat_documents/output_000.pdf index 91deee98f..8f30ae07f 100644 Binary files a/tests/output/test_concat_documents/output_000.pdf and b/tests/output/test_concat_documents/output_000.pdf differ diff --git a/tests/output/test_concat_documents/output_001.pdf b/tests/output/test_concat_documents/output_001.pdf index 607308877..4ce18434c 100644 Binary files a/tests/output/test_concat_documents/output_001.pdf and b/tests/output/test_concat_documents/output_001.pdf differ diff --git a/tests/output/test_concat_documents/output_002.pdf b/tests/output/test_concat_documents/output_002.pdf index 980b29843..100480248 100644 Binary files a/tests/output/test_concat_documents/output_002.pdf and b/tests/output/test_concat_documents/output_002.pdf differ diff --git a/tests/output/test_copy_circle_annotation/output_001.pdf b/tests/output/test_copy_circle_annotation/output_001.pdf new file mode 100644 index 000000000..1bb92b7ba Binary files /dev/null and b/tests/output/test_copy_circle_annotation/output_001.pdf differ diff --git a/tests/output/test_copy_circle_annotation/output_001_ground_truth.png b/tests/output/test_copy_circle_annotation/output_001_ground_truth.png new file mode 100644 index 000000000..d4bd68e23 Binary files /dev/null and b/tests/output/test_copy_circle_annotation/output_001_ground_truth.png differ diff --git a/tests/output/test_copy_circle_annotation/output_002.pdf b/tests/output/test_copy_circle_annotation/output_002.pdf new file mode 100644 index 000000000..e3e7dc8b5 Binary files /dev/null and b/tests/output/test_copy_circle_annotation/output_002.pdf differ diff --git a/tests/output/test_copy_circle_annotation/output_002_ground_truth.png b/tests/output/test_copy_circle_annotation/output_002_ground_truth.png new file mode 100644 index 000000000..aa1102c8b Binary files /dev/null and b/tests/output/test_copy_circle_annotation/output_002_ground_truth.png differ diff --git a/tests/output/test_copy_circle_annotation/output_003.pdf b/tests/output/test_copy_circle_annotation/output_003.pdf new file mode 100644 index 000000000..4f6fe5d78 Binary files /dev/null and b/tests/output/test_copy_circle_annotation/output_003.pdf differ diff --git a/tests/output/test_copy_circle_annotation/output_003_ground_truth.png b/tests/output/test_copy_circle_annotation/output_003_ground_truth.png new file mode 100644 index 000000000..edf2fe59b Binary files /dev/null and b/tests/output/test_copy_circle_annotation/output_003_ground_truth.png differ diff --git a/tests/output/test_copy_document_compare_size/0187_page_0_copy.pdf b/tests/output/test_copy_document_compare_size/0187_page_0_copy.pdf index fc680efd6..23b1b8c00 100644 Binary files a/tests/output/test_copy_document_compare_size/0187_page_0_copy.pdf and b/tests/output/test_copy_document_compare_size/0187_page_0_copy.pdf differ diff --git a/tests/output/test_copy_document_compare_size/0430_page_0_copy.pdf b/tests/output/test_copy_document_compare_size/0430_page_0_copy.pdf index 128ecc8d0..7bd57b3a2 100644 Binary files a/tests/output/test_copy_document_compare_size/0430_page_0_copy.pdf and b/tests/output/test_copy_document_compare_size/0430_page_0_copy.pdf differ diff --git a/tests/output/test_copy_document_compare_size/0462_page_0_copy.pdf b/tests/output/test_copy_document_compare_size/0462_page_0_copy.pdf index f81bf7953..dc0fa3919 100644 Binary files a/tests/output/test_copy_document_compare_size/0462_page_0_copy.pdf and b/tests/output/test_copy_document_compare_size/0462_page_0_copy.pdf differ diff --git a/tests/output/test_copy_document_compare_size/0495_page_0_copy.pdf b/tests/output/test_copy_document_compare_size/0495_page_0_copy.pdf index 7971be6f2..f374a22e6 100644 Binary files a/tests/output/test_copy_document_compare_size/0495_page_0_copy.pdf and b/tests/output/test_copy_document_compare_size/0495_page_0_copy.pdf differ diff --git a/tests/output/test_copy_document_compare_size/0594_page_0_copy.pdf b/tests/output/test_copy_document_compare_size/0594_page_0_copy.pdf index bd387472b..e0552cfce 100644 Binary files a/tests/output/test_copy_document_compare_size/0594_page_0_copy.pdf and b/tests/output/test_copy_document_compare_size/0594_page_0_copy.pdf differ diff --git a/tests/output/test_copy_document_compare_size/output.pdf b/tests/output/test_copy_document_compare_size/output.pdf index 29918ac91..25bdda179 100644 Binary files a/tests/output/test_copy_document_compare_size/output.pdf and b/tests/output/test_copy_document_compare_size/output.pdf differ diff --git a/tests/output/test_copy_document_resize_images_compare_size/0187_page_0_copy.pdf b/tests/output/test_copy_document_resize_images_compare_size/0187_page_0_copy.pdf index 467087dc1..6d2b55190 100644 Binary files a/tests/output/test_copy_document_resize_images_compare_size/0187_page_0_copy.pdf and b/tests/output/test_copy_document_resize_images_compare_size/0187_page_0_copy.pdf differ diff --git a/tests/output/test_copy_document_resize_images_compare_size/0430_page_0_copy.pdf b/tests/output/test_copy_document_resize_images_compare_size/0430_page_0_copy.pdf index eb20fd13e..5aacd46ef 100644 Binary files a/tests/output/test_copy_document_resize_images_compare_size/0430_page_0_copy.pdf and b/tests/output/test_copy_document_resize_images_compare_size/0430_page_0_copy.pdf differ diff --git a/tests/output/test_copy_document_resize_images_compare_size/0462_page_0_copy.pdf b/tests/output/test_copy_document_resize_images_compare_size/0462_page_0_copy.pdf index 9637ea611..577f194ef 100644 Binary files a/tests/output/test_copy_document_resize_images_compare_size/0462_page_0_copy.pdf and b/tests/output/test_copy_document_resize_images_compare_size/0462_page_0_copy.pdf differ diff --git a/tests/output/test_copy_document_resize_images_compare_size/0495_page_0_copy.pdf b/tests/output/test_copy_document_resize_images_compare_size/0495_page_0_copy.pdf index 8eacabd40..022e4f022 100644 Binary files a/tests/output/test_copy_document_resize_images_compare_size/0495_page_0_copy.pdf and b/tests/output/test_copy_document_resize_images_compare_size/0495_page_0_copy.pdf differ diff --git a/tests/output/test_copy_document_resize_images_compare_size/0594_page_0_copy.pdf b/tests/output/test_copy_document_resize_images_compare_size/0594_page_0_copy.pdf index 4d748336d..658a28a36 100644 Binary files a/tests/output/test_copy_document_resize_images_compare_size/0594_page_0_copy.pdf and b/tests/output/test_copy_document_resize_images_compare_size/0594_page_0_copy.pdf differ diff --git a/tests/output/test_copy_document_resize_images_compare_size/output.pdf b/tests/output/test_copy_document_resize_images_compare_size/output.pdf index 7b26cb621..637edd6fc 100644 Binary files a/tests/output/test_copy_document_resize_images_compare_size/output.pdf and b/tests/output/test_copy_document_resize_images_compare_size/output.pdf differ diff --git a/tests/output/test_count_annotations/output_001.pdf b/tests/output/test_count_annotations/output_001.pdf index 546e3711f..e8a6c7d8c 100644 Binary files a/tests/output/test_count_annotations/output_001.pdf and b/tests/output/test_count_annotations/output_001.pdf differ diff --git a/tests/output/test_count_annotations/output_002.pdf b/tests/output/test_count_annotations/output_002.pdf index e858abc7d..bf4acd0fb 100644 Binary files a/tests/output/test_count_annotations/output_002.pdf and b/tests/output/test_count_annotations/output_002.pdf differ 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 1a22a8bc5..48fa8d485 100644 Binary files a/tests/output/test_create_document_with_output_intent/output_001.pdf and b/tests/output/test_create_document_with_output_intent/output_001.pdf differ diff --git a/tests/output/test_detect_table/input_000.pdf b/tests/output/test_detect_table/input_000.pdf index 32748a81e..06802bc81 100644 Binary files a/tests/output/test_detect_table/input_000.pdf and b/tests/output/test_detect_table/input_000.pdf differ diff --git a/tests/output/test_detect_table/input_001.pdf b/tests/output/test_detect_table/input_001.pdf index 47f1c470b..49b8d95db 100644 Binary files a/tests/output/test_detect_table/input_001.pdf and b/tests/output/test_detect_table/input_001.pdf differ diff --git a/tests/output/test_detect_table/input_002.pdf b/tests/output/test_detect_table/input_002.pdf index fe21c790f..b714fefe7 100644 Binary files a/tests/output/test_detect_table/input_002.pdf and b/tests/output/test_detect_table/input_002.pdf differ diff --git a/tests/output/test_detect_table/input_003.pdf b/tests/output/test_detect_table/input_003.pdf index 1b67e7aa8..f733fe023 100644 Binary files a/tests/output/test_detect_table/input_003.pdf and b/tests/output/test_detect_table/input_003.pdf differ diff --git a/tests/output/test_detect_table/input_004.pdf b/tests/output/test_detect_table/input_004.pdf index 5e4674444..63dac365d 100644 Binary files a/tests/output/test_detect_table/input_004.pdf and b/tests/output/test_detect_table/input_004.pdf differ diff --git a/tests/output/test_detect_table/input_005.pdf b/tests/output/test_detect_table/input_005.pdf index 65287b0d4..8e675dfee 100644 Binary files a/tests/output/test_detect_table/input_005.pdf and b/tests/output/test_detect_table/input_005.pdf differ diff --git a/tests/output/test_detect_table/input_006.pdf b/tests/output/test_detect_table/input_006.pdf index f4483fdfd..1efe866fc 100644 Binary files a/tests/output/test_detect_table/input_006.pdf and b/tests/output/test_detect_table/input_006.pdf differ diff --git a/tests/output/test_detect_table/output_000.pdf b/tests/output/test_detect_table/output_000.pdf index 5acfae619..105796689 100644 Binary files a/tests/output/test_detect_table/output_000.pdf and b/tests/output/test_detect_table/output_000.pdf differ diff --git a/tests/output/test_detect_table/output_001.pdf b/tests/output/test_detect_table/output_001.pdf index c97db097f..0b3b84553 100644 Binary files a/tests/output/test_detect_table/output_001.pdf and b/tests/output/test_detect_table/output_001.pdf differ diff --git a/tests/output/test_detect_table/output_002.pdf b/tests/output/test_detect_table/output_002.pdf index e7cf902f6..a61bb3347 100644 Binary files a/tests/output/test_detect_table/output_002.pdf and b/tests/output/test_detect_table/output_002.pdf differ diff --git a/tests/output/test_detect_table/output_003.pdf b/tests/output/test_detect_table/output_003.pdf index 4eea05e20..6569047c5 100644 Binary files a/tests/output/test_detect_table/output_003.pdf and b/tests/output/test_detect_table/output_003.pdf differ diff --git a/tests/output/test_detect_table/output_004.pdf b/tests/output/test_detect_table/output_004.pdf index eec13df65..fc648dd7a 100644 Binary files a/tests/output/test_detect_table/output_004.pdf and b/tests/output/test_detect_table/output_004.pdf differ diff --git a/tests/output/test_detect_table/output_005.pdf b/tests/output/test_detect_table/output_005.pdf index 67e9e4a70..7e4f3f648 100644 Binary files a/tests/output/test_detect_table/output_005.pdf and b/tests/output/test_detect_table/output_005.pdf differ diff --git a/tests/output/test_detect_table/output_006.pdf b/tests/output/test_detect_table/output_006.pdf index 592456546..0f99897ab 100644 Binary files a/tests/output/test_detect_table/output_006.pdf and b/tests/output/test_detect_table/output_006.pdf differ diff --git a/tests/output/test_digit_placement_ubuntu_font/output_001.pdf b/tests/output/test_digit_placement_ubuntu_font/output_001.pdf index 947ac5b11..6547a2d0a 100644 Binary files a/tests/output/test_digit_placement_ubuntu_font/output_001.pdf and b/tests/output/test_digit_placement_ubuntu_font/output_001.pdf differ diff --git a/tests/output/test_digit_placement_ubuntu_font/output_001.png b/tests/output/test_digit_placement_ubuntu_font/output_001.png index 61ecf8b8b..a007f083c 100644 Binary files a/tests/output/test_digit_placement_ubuntu_font/output_001.png and b/tests/output/test_digit_placement_ubuntu_font/output_001.png differ diff --git a/tests/output/test_duplicate_pages/output_000.pdf b/tests/output/test_duplicate_pages/output_000.pdf new file mode 100644 index 000000000..3ba347990 Binary files /dev/null and b/tests/output/test_duplicate_pages/output_000.pdf differ diff --git a/tests/output/test_duplicate_pages/output_001.pdf b/tests/output/test_duplicate_pages/output_001.pdf new file mode 100644 index 000000000..12ca75af3 Binary files /dev/null and b/tests/output/test_duplicate_pages/output_001.pdf differ diff --git a/tests/output/test_duplicate_pages/output_002.pdf b/tests/output/test_duplicate_pages/output_002.pdf new file mode 100644 index 000000000..0e4e2a2e6 Binary files /dev/null and b/tests/output/test_duplicate_pages/output_002.pdf differ diff --git a/tests/output/test_duplicate_pages/output_003.pdf b/tests/output/test_duplicate_pages/output_003.pdf new file mode 100644 index 000000000..4b5cd17a2 Binary files /dev/null and b/tests/output/test_duplicate_pages/output_003.pdf differ diff --git a/tests/output/test_easier_imports/output.pdf b/tests/output/test_easier_imports/output.pdf new file mode 100644 index 000000000..e474f92f3 Binary files /dev/null and b/tests/output/test_easier_imports/output.pdf differ 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 7d577e707..0a3d9d02e 100644 Binary files a/tests/output/test_export_html_to_pdf/example_html_input_000.pdf and b/tests/output/test_export_html_to_pdf/example_html_input_000.pdf differ 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 194dc8475..38566f7d3 100644 Binary files a/tests/output/test_export_html_to_pdf/example_html_input_001.pdf and b/tests/output/test_export_html_to_pdf/example_html_input_001.pdf differ 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 5eef06fb9..53446939f 100644 Binary files a/tests/output/test_export_html_to_pdf/example_html_input_002.pdf and b/tests/output/test_export_html_to_pdf/example_html_input_002.pdf differ diff --git a/tests/output/test_export_html_to_pdf/example_html_input_003.pdf b/tests/output/test_export_html_to_pdf/example_html_input_003.pdf index f96140cdb..2196cc95b 100644 Binary files a/tests/output/test_export_html_to_pdf/example_html_input_003.pdf and b/tests/output/test_export_html_to_pdf/example_html_input_003.pdf differ 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 b6975571e..3345d5435 100644 Binary files a/tests/output/test_export_html_to_pdf/example_html_input_004.pdf and b/tests/output/test_export_html_to_pdf/example_html_input_004.pdf differ 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 6eafcbd91..c62222d8d 100644 Binary files a/tests/output/test_export_html_to_pdf/example_html_input_005.pdf and b/tests/output/test_export_html_to_pdf/example_html_input_005.pdf differ diff --git a/tests/output/test_export_html_to_pdf/example_html_input_006.pdf b/tests/output/test_export_html_to_pdf/example_html_input_006.pdf index f83f37b96..a8e62a6ea 100644 Binary files a/tests/output/test_export_html_to_pdf/example_html_input_006.pdf and b/tests/output/test_export_html_to_pdf/example_html_input_006.pdf differ 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 73bab1b02..efd30fdb1 100644 Binary files a/tests/output/test_export_html_to_pdf/example_html_input_007.pdf and b/tests/output/test_export_html_to_pdf/example_html_input_007.pdf differ 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 22aafaebb..b0e295967 100644 Binary files a/tests/output/test_export_html_to_pdf/example_html_input_008.pdf and b/tests/output/test_export_html_to_pdf/example_html_input_008.pdf differ diff --git a/tests/output/test_export_html_to_pdf/example_html_input_009.pdf b/tests/output/test_export_html_to_pdf/example_html_input_009.pdf index 7324086fe..374c10ce8 100644 Binary files a/tests/output/test_export_html_to_pdf/example_html_input_009.pdf and b/tests/output/test_export_html_to_pdf/example_html_input_009.pdf differ 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 db4dda788..c32a31059 100644 Binary files a/tests/output/test_export_html_to_pdf/example_html_input_010.pdf and b/tests/output/test_export_html_to_pdf/example_html_input_010.pdf differ 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 a6a30fba5..4b4d73ee2 100644 Binary files a/tests/output/test_export_html_to_pdf/example_html_input_011.pdf and b/tests/output/test_export_html_to_pdf/example_html_input_011.pdf differ 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 703bf2316..a84c5451c 100644 Binary files a/tests/output/test_export_html_to_pdf/example_html_input_012.pdf and b/tests/output/test_export_html_to_pdf/example_html_input_012.pdf differ 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 8b757610f..afd0d5529 100644 Binary files a/tests/output/test_export_html_to_pdf/example_html_input_013.pdf and b/tests/output/test_export_html_to_pdf/example_html_input_013.pdf differ 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 5a95ab928..986159958 100644 Binary files a/tests/output/test_export_html_to_pdf/example_html_input_014.pdf and b/tests/output/test_export_html_to_pdf/example_html_input_014.pdf differ 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 17b63bd43..638b47239 100644 Binary files a/tests/output/test_export_markdown_to_pdf/example-markdown-input-001.md.pdf and b/tests/output/test_export_markdown_to_pdf/example-markdown-input-001.md.pdf differ 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 069aa07aa..19b354fae 100644 Binary files a/tests/output/test_export_markdown_to_pdf/example-markdown-input-002.md.pdf and b/tests/output/test_export_markdown_to_pdf/example-markdown-input-002.md.pdf differ diff --git a/tests/output/test_export_markdown_to_pdf/example-markdown-input-003.md.pdf b/tests/output/test_export_markdown_to_pdf/example-markdown-input-003.md.pdf index 5f0b24e57..f290146e3 100644 Binary files a/tests/output/test_export_markdown_to_pdf/example-markdown-input-003.md.pdf and b/tests/output/test_export_markdown_to_pdf/example-markdown-input-003.md.pdf differ diff --git a/tests/output/test_export_markdown_to_pdf/example-markdown-input-004.md.pdf b/tests/output/test_export_markdown_to_pdf/example-markdown-input-004.md.pdf index 5241933e8..2544452af 100644 Binary files a/tests/output/test_export_markdown_to_pdf/example-markdown-input-004.md.pdf and b/tests/output/test_export_markdown_to_pdf/example-markdown-input-004.md.pdf differ diff --git a/tests/output/test_export_markdown_to_pdf/example-markdown-input-005.md.pdf b/tests/output/test_export_markdown_to_pdf/example-markdown-input-005.md.pdf index 5b269ad1b..254f301a9 100644 Binary files a/tests/output/test_export_markdown_to_pdf/example-markdown-input-005.md.pdf and b/tests/output/test_export_markdown_to_pdf/example-markdown-input-005.md.pdf differ diff --git a/tests/output/test_export_markdown_to_pdf/example-markdown-input-006.md.pdf b/tests/output/test_export_markdown_to_pdf/example-markdown-input-006.md.pdf index 12b430335..571a83604 100644 Binary files a/tests/output/test_export_markdown_to_pdf/example-markdown-input-006.md.pdf and b/tests/output/test_export_markdown_to_pdf/example-markdown-input-006.md.pdf differ diff --git a/tests/output/test_export_markdown_to_pdf/example-markdown-input-007.md.pdf b/tests/output/test_export_markdown_to_pdf/example-markdown-input-007.md.pdf index 815caeb2c..a55d6173c 100644 Binary files a/tests/output/test_export_markdown_to_pdf/example-markdown-input-007.md.pdf and b/tests/output/test_export_markdown_to_pdf/example-markdown-input-007.md.pdf differ diff --git a/tests/output/test_export_markdown_to_pdf/example-markdown-input-008.md.pdf b/tests/output/test_export_markdown_to_pdf/example-markdown-input-008.md.pdf index 7844b01eb..3f65c8b7e 100644 Binary files a/tests/output/test_export_markdown_to_pdf/example-markdown-input-008.md.pdf and b/tests/output/test_export_markdown_to_pdf/example-markdown-input-008.md.pdf differ diff --git a/tests/output/test_export_markdown_to_pdf/example-markdown-input-009.md.pdf b/tests/output/test_export_markdown_to_pdf/example-markdown-input-009.md.pdf index 0f53eea1a..566b2bc96 100644 Binary files a/tests/output/test_export_markdown_to_pdf/example-markdown-input-009.md.pdf and b/tests/output/test_export_markdown_to_pdf/example-markdown-input-009.md.pdf differ diff --git a/tests/output/test_export_markdown_to_pdf/example-markdown-input-010.md.pdf b/tests/output/test_export_markdown_to_pdf/example-markdown-input-010.md.pdf index e46886939..353dbb895 100644 Binary files a/tests/output/test_export_markdown_to_pdf/example-markdown-input-010.md.pdf and b/tests/output/test_export_markdown_to_pdf/example-markdown-input-010.md.pdf differ diff --git a/tests/output/test_export_to_mp3/output.mp3 b/tests/output/test_export_to_mp3/output.mp3 index e782a6c51..e8e8a6bbf 100644 Binary files a/tests/output/test_export_to_mp3/output.mp3 and b/tests/output/test_export_to_mp3/output.mp3 differ diff --git a/tests/output/test_extract_colors/output_001.pdf b/tests/output/test_extract_colors/output_001.pdf index de4ad6de2..761b2ec4e 100644 Binary files a/tests/output/test_extract_colors/output_001.pdf and b/tests/output/test_extract_colors/output_001.pdf differ diff --git a/tests/output/test_extract_colors/output_002.pdf b/tests/output/test_extract_colors/output_002.pdf index 4d15ea391..d8660bf7e 100644 Binary files a/tests/output/test_extract_colors/output_002.pdf and b/tests/output/test_extract_colors/output_002.pdf differ diff --git a/tests/output/test_extract_colors/output_002.png b/tests/output/test_extract_colors/output_002.png index 78183f499..ea6bb1655 100644 Binary files a/tests/output/test_extract_colors/output_002.png and b/tests/output/test_extract_colors/output_002.png differ diff --git a/tests/output/test_extract_courier_text/output_001.pdf b/tests/output/test_extract_courier_text/output_001.pdf index 0e68aa517..d1585087b 100644 Binary files a/tests/output/test_extract_courier_text/output_001.pdf and b/tests/output/test_extract_courier_text/output_001.pdf differ diff --git a/tests/output/test_extract_font_names/output_001.pdf b/tests/output/test_extract_font_names/output_001.pdf index 09b86446a..700078922 100644 Binary files a/tests/output/test_extract_font_names/output_001.pdf and b/tests/output/test_extract_font_names/output_001.pdf differ diff --git a/tests/output/test_extract_font_names/output_002.pdf b/tests/output/test_extract_font_names/output_002.pdf index 62a068d77..e79a8c31a 100644 Binary files a/tests/output/test_extract_font_names/output_002.pdf and b/tests/output/test_extract_font_names/output_002.pdf differ diff --git a/tests/output/test_extract_keywords/output_001.pdf b/tests/output/test_extract_keywords/output_001.pdf index ae1a3ab18..9e25acf20 100644 Binary files a/tests/output/test_extract_keywords/output_001.pdf and b/tests/output/test_extract_keywords/output_001.pdf differ diff --git a/tests/output/test_extract_keywords/output_002.pdf b/tests/output/test_extract_keywords/output_002.pdf index d955ddccb..bc0128432 100644 Binary files a/tests/output/test_extract_keywords/output_002.pdf and b/tests/output/test_extract_keywords/output_002.pdf differ diff --git a/tests/output/test_extract_keywords/output_003.pdf b/tests/output/test_extract_keywords/output_003.pdf index bddff2b83..0d7df5a12 100644 Binary files a/tests/output/test_extract_keywords/output_003.pdf and b/tests/output/test_extract_keywords/output_003.pdf differ diff --git a/tests/output/test_extract_red_text/output_001.pdf b/tests/output/test_extract_red_text/output_001.pdf index a40dd6aff..2b81c0e55 100644 Binary files a/tests/output/test_extract_red_text/output_001.pdf and b/tests/output/test_extract_red_text/output_001.pdf differ diff --git a/tests/output/test_extract_regex/output_001.pdf b/tests/output/test_extract_regex/output_001.pdf index 874144047..eff039d5c 100644 Binary files a/tests/output/test_extract_regex/output_001.pdf and b/tests/output/test_extract_regex/output_001.pdf differ diff --git a/tests/output/test_extract_regex/output_002.pdf b/tests/output/test_extract_regex/output_002.pdf index 938c0f403..c7ccebd50 100644 Binary files a/tests/output/test_extract_regex/output_002.pdf and b/tests/output/test_extract_regex/output_002.pdf differ diff --git a/tests/output/test_extract_text/output_001.pdf b/tests/output/test_extract_text/output_001.pdf index e89dc442c..fa0005a2b 100644 Binary files a/tests/output/test_extract_text/output_001.pdf and b/tests/output/test_extract_text/output_001.pdf differ diff --git a/tests/output/test_extract_text/output_002.pdf b/tests/output/test_extract_text/output_002.pdf index 21f305d2e..083798248 100644 Binary files a/tests/output/test_extract_text/output_002.pdf and b/tests/output/test_extract_text/output_002.pdf differ diff --git a/tests/output/test_extract_text_expect_ground_truth/output.pdf b/tests/output/test_extract_text_expect_ground_truth/output.pdf index cea51ea1f..2ce0feb0e 100644 Binary files a/tests/output/test_extract_text_expect_ground_truth/output.pdf and b/tests/output/test_extract_text_expect_ground_truth/output.pdf differ diff --git a/tests/output/test_extract_text_from_self_made_invoice/output.pdf b/tests/output/test_extract_text_from_self_made_invoice/output.pdf index 370959cf6..b0b72845b 100644 Binary files a/tests/output/test_extract_text_from_self_made_invoice/output.pdf and b/tests/output/test_extract_text_from_self_made_invoice/output.pdf differ diff --git a/tests/output/test_fix_broken_xref/output_001.pdf b/tests/output/test_fix_broken_xref/output_001.pdf index 8e0615d29..2a85159db 100644 Binary files a/tests/output/test_fix_broken_xref/output_001.pdf and b/tests/output/test_fix_broken_xref/output_001.pdf differ diff --git a/tests/output/test_fix_broken_xref/output_002.pdf b/tests/output/test_fix_broken_xref/output_002.pdf index f07488552..c89cda93c 100644 Binary files a/tests/output/test_fix_broken_xref/output_002.pdf and b/tests/output/test_fix_broken_xref/output_002.pdf differ diff --git a/tests/output/test_hello_world/output.pdf b/tests/output/test_hello_world/output.pdf new file mode 100644 index 000000000..843bf4877 Binary files /dev/null and b/tests/output/test_hello_world/output.pdf differ diff --git a/tests/output/test_inline_object_io/output_001.pdf b/tests/output/test_inline_object_io/output_001.pdf new file mode 100644 index 000000000..93ad267d1 Binary files /dev/null and b/tests/output/test_inline_object_io/output_001.pdf differ diff --git a/tests/output/test_inline_object_io/output_001.png b/tests/output/test_inline_object_io/output_001.png new file mode 100644 index 000000000..a1c8de9d1 Binary files /dev/null and b/tests/output/test_inline_object_io/output_001.png differ diff --git a/tests/output/test_margin_and_padding/output_001.pdf b/tests/output/test_margin_and_padding/output_001.pdf index 39d33d74d..238a24279 100644 Binary files a/tests/output/test_margin_and_padding/output_001.pdf and b/tests/output/test_margin_and_padding/output_001.pdf differ diff --git a/tests/output/test_margin_and_padding/output_002.pdf b/tests/output/test_margin_and_padding/output_002.pdf index 31f3d164d..a2a222140 100644 Binary files a/tests/output/test_margin_and_padding/output_002.pdf and b/tests/output/test_margin_and_padding/output_002.pdf differ diff --git a/tests/output/test_modify_image/output_001.pdf b/tests/output/test_modify_image/output_001.pdf index 8f0e8431a..67394d445 100644 Binary files a/tests/output/test_modify_image/output_001.pdf and b/tests/output/test_modify_image/output_001.pdf differ diff --git a/tests/output/test_modify_image/output_002.pdf b/tests/output/test_modify_image/output_002.pdf index 0c88cdc9c..45236c9f1 100644 Binary files a/tests/output/test_modify_image/output_002.pdf and b/tests/output/test_modify_image/output_002.pdf differ diff --git a/tests/output/test_open_document/output.pdf b/tests/output/test_open_document/output.pdf index b88c451d2..38925ced2 100644 Binary files a/tests/output/test_open_document/output.pdf and b/tests/output/test_open_document/output.pdf differ diff --git a/tests/output/test_open_encrypted_document/output.pdf b/tests/output/test_open_encrypted_document/output.pdf index 346c5c3a9..2feb4dfed 100644 Binary files a/tests/output/test_open_encrypted_document/output.pdf and b/tests/output/test_open_encrypted_document/output.pdf differ diff --git a/tests/output/test_optimize_images/output_001.pdf b/tests/output/test_optimize_images/output_001.pdf index 8706e72db..d8c66f735 100644 Binary files a/tests/output/test_optimize_images/output_001.pdf and b/tests/output/test_optimize_images/output_001.pdf differ diff --git a/tests/output/test_page_has_empty_resource_dictionary/output_001.pdf b/tests/output/test_page_has_empty_resource_dictionary/output_001.pdf index f3887e55f..aa232ed32 100644 Binary files a/tests/output/test_page_has_empty_resource_dictionary/output_001.pdf and b/tests/output/test_page_has_empty_resource_dictionary/output_001.pdf differ diff --git a/tests/output/test_redact_common_regular_expressions/output_001.pdf b/tests/output/test_redact_common_regular_expressions/output_001.pdf index da10e6dbb..5dd70ee5f 100644 Binary files a/tests/output/test_redact_common_regular_expressions/output_001.pdf and b/tests/output/test_redact_common_regular_expressions/output_001.pdf differ diff --git a/tests/output/test_redact_common_regular_expressions/output_002.pdf b/tests/output/test_redact_common_regular_expressions/output_002.pdf index 401baade0..a56895a44 100644 Binary files a/tests/output/test_redact_common_regular_expressions/output_002.pdf and b/tests/output/test_redact_common_regular_expressions/output_002.pdf differ diff --git a/tests/output/test_redact_common_regular_expressions/output_003.pdf b/tests/output/test_redact_common_regular_expressions/output_003.pdf index c4fcab2f7..a6f2f80b3 100644 Binary files a/tests/output/test_redact_common_regular_expressions/output_003.pdf and b/tests/output/test_redact_common_regular_expressions/output_003.pdf differ diff --git a/tests/output/test_remove_annotation/output_001.pdf b/tests/output/test_remove_annotation/output_001.pdf index 02f565fe5..7e58123a7 100644 Binary files a/tests/output/test_remove_annotation/output_001.pdf and b/tests/output/test_remove_annotation/output_001.pdf differ diff --git a/tests/output/test_remove_annotation/output_002.pdf b/tests/output/test_remove_annotation/output_002.pdf index b889baedd..c54678789 100644 Binary files a/tests/output/test_remove_annotation/output_002.pdf and b/tests/output/test_remove_annotation/output_002.pdf differ diff --git a/tests/output/test_remove_annotation/output_003.pdf b/tests/output/test_remove_annotation/output_003.pdf index 2e445f38b..3cf613897 100644 Binary files a/tests/output/test_remove_annotation/output_003.pdf and b/tests/output/test_remove_annotation/output_003.pdf differ diff --git a/tests/output/test_remove_page/output_001.pdf b/tests/output/test_remove_page/output_001.pdf index 3ffb28ab6..e0ec97108 100644 Binary files a/tests/output/test_remove_page/output_001.pdf and b/tests/output/test_remove_page/output_001.pdf differ diff --git a/tests/output/test_remove_page/output_002.pdf b/tests/output/test_remove_page/output_002.pdf index 7d3a87b46..7f59443de 100644 Binary files a/tests/output/test_remove_page/output_002.pdf and b/tests/output/test_remove_page/output_002.pdf differ diff --git a/tests/output/test_remove_page/output_003.pdf b/tests/output/test_remove_page/output_003.pdf index 3f619f535..31a3b8ec2 100644 Binary files a/tests/output/test_remove_page/output_003.pdf and b/tests/output/test_remove_page/output_003.pdf differ diff --git a/tests/output/test_remove_page/output_004.pdf b/tests/output/test_remove_page/output_004.pdf index 945eb3967..7aa6696c4 100644 Binary files a/tests/output/test_remove_page/output_004.pdf and b/tests/output/test_remove_page/output_004.pdf differ diff --git a/tests/output/test_rotate_page/output_001.pdf b/tests/output/test_rotate_page/output_001.pdf index 1dcc9ec51..cebec183f 100644 Binary files a/tests/output/test_rotate_page/output_001.pdf and b/tests/output/test_rotate_page/output_001.pdf differ diff --git a/tests/output/test_rotate_page/output_002.pdf b/tests/output/test_rotate_page/output_002.pdf index 3d65dbb94..c1949bdd1 100644 Binary files a/tests/output/test_rotate_page/output_002.pdf and b/tests/output/test_rotate_page/output_002.pdf differ diff --git a/tests/output/test_rotate_page/output_003.pdf b/tests/output/test_rotate_page/output_003.pdf index b92c06f2c..3534fd1f0 100644 Binary files a/tests/output/test_rotate_page/output_003.pdf and b/tests/output/test_rotate_page/output_003.pdf differ diff --git a/tests/output/test_simple_paragraph_extraction/output_000.pdf b/tests/output/test_simple_paragraph_extraction/output_000.pdf new file mode 100644 index 000000000..c213fb1d9 Binary files /dev/null and b/tests/output/test_simple_paragraph_extraction/output_000.pdf differ diff --git a/tests/output/test_simple_paragraph_extraction/output_001.pdf b/tests/output/test_simple_paragraph_extraction/output_001.pdf new file mode 100644 index 000000000..85fcbab70 Binary files /dev/null and b/tests/output/test_simple_paragraph_extraction/output_001.pdf differ diff --git a/tests/output/test_simple_paragraph_extraction/output_001_ground_truth.png b/tests/output/test_simple_paragraph_extraction/output_001_ground_truth.png new file mode 100644 index 000000000..96fbe5172 Binary files /dev/null and b/tests/output/test_simple_paragraph_extraction/output_001_ground_truth.png differ diff --git a/tests/output/test_split_complementary_color_scheme/output.pdf b/tests/output/test_split_complementary_color_scheme/output.pdf index fedb28ddc..7408d43ce 100644 Binary files a/tests/output/test_split_complementary_color_scheme/output.pdf and b/tests/output/test_split_complementary_color_scheme/output.pdf differ diff --git a/tests/output/test_tetradic_rectangle_color_scheme/output.pdf b/tests/output/test_tetradic_rectangle_color_scheme/output.pdf index bc0d167c6..5c42526e8 100644 Binary files a/tests/output/test_tetradic_rectangle_color_scheme/output.pdf and b/tests/output/test_tetradic_rectangle_color_scheme/output.pdf differ diff --git a/tests/output/test_tetradic_square_color_scheme/output.pdf b/tests/output/test_tetradic_square_color_scheme/output.pdf index 6eedf7499..55a2b30ac 100644 Binary files a/tests/output/test_tetradic_square_color_scheme/output.pdf and b/tests/output/test_tetradic_square_color_scheme/output.pdf differ diff --git a/tests/output/test_triadic_color_scheme/output.pdf b/tests/output/test_triadic_color_scheme/output.pdf index d4cfe6059..d05949963 100644 Binary files a/tests/output/test_triadic_color_scheme/output.pdf and b/tests/output/test_triadic_color_scheme/output.pdf differ diff --git a/tests/output/test_write_2_scatter_plots/output.pdf b/tests/output/test_write_2_scatter_plots/output.pdf index f60309615..ae8dddca6 100644 Binary files a/tests/output/test_write_2_scatter_plots/output.pdf and b/tests/output/test_write_2_scatter_plots/output.pdf differ diff --git a/tests/output/test_write_3d_density_chart/output.pdf b/tests/output/test_write_3d_density_chart/output.pdf index d99c43948..48dc75b32 100644 Binary files a/tests/output/test_write_3d_density_chart/output.pdf and b/tests/output/test_write_3d_density_chart/output.pdf differ diff --git a/tests/output/test_write_3d_surface_plot/output.pdf b/tests/output/test_write_3d_surface_plot/output.pdf index ba353bc05..fedd0d882 100644 Binary files a/tests/output/test_write_3d_surface_plot/output.pdf and b/tests/output/test_write_3d_surface_plot/output.pdf differ diff --git a/tests/output/test_write_all_types_of_barcode/output.pdf b/tests/output/test_write_all_types_of_barcode/output.pdf index 875391661..8837197b2 100644 Binary files a/tests/output/test_write_all_types_of_barcode/output.pdf and b/tests/output/test_write_all_types_of_barcode/output.pdf differ diff --git a/tests/output/test_write_battleship/output.pdf b/tests/output/test_write_battleship/output.pdf index 6398a43ad..67b1d8f2c 100644 Binary files a/tests/output/test_write_battleship/output.pdf and b/tests/output/test_write_battleship/output.pdf differ diff --git a/tests/output/test_write_blobs/output.pdf b/tests/output/test_write_blobs/output.pdf index 0ee033b18..8f1b6d30c 100644 Binary files a/tests/output/test_write_blobs/output.pdf and b/tests/output/test_write_blobs/output.pdf differ diff --git a/tests/output/test_write_check_box/output_001.pdf b/tests/output/test_write_check_box/output_001.pdf index 4e21868e0..cfa1c405a 100644 Binary files a/tests/output/test_write_check_box/output_001.pdf and b/tests/output/test_write_check_box/output_001.pdf differ diff --git a/tests/output/test_write_check_box/output_002.pdf b/tests/output/test_write_check_box/output_002.pdf index bdc65be14..770baf36a 100644 Binary files a/tests/output/test_write_check_box/output_002.pdf and b/tests/output/test_write_check_box/output_002.pdf differ diff --git a/tests/output/test_write_chunk_of_text/output.pdf b/tests/output/test_write_chunk_of_text/output.pdf index 816c7af7d..7d660c9de 100644 Binary files a/tests/output/test_write_chunk_of_text/output.pdf and b/tests/output/test_write_chunk_of_text/output.pdf differ diff --git a/tests/output/test_write_chunk_of_text_escaped_chars/output.pdf b/tests/output/test_write_chunk_of_text_escaped_chars/output.pdf index 7aceede56..ee716d3fa 100644 Binary files a/tests/output/test_write_chunk_of_text_escaped_chars/output.pdf and b/tests/output/test_write_chunk_of_text_escaped_chars/output.pdf differ diff --git a/tests/output/test_write_chunk_of_text_in_rainbow_colors/output.pdf b/tests/output/test_write_chunk_of_text_in_rainbow_colors/output.pdf index 9cfa09743..63c7b47ae 100644 Binary files a/tests/output/test_write_chunk_of_text_in_rainbow_colors/output.pdf and b/tests/output/test_write_chunk_of_text_in_rainbow_colors/output.pdf differ diff --git a/tests/output/test_write_chunks_of_text/output_001.pdf b/tests/output/test_write_chunks_of_text/output_001.pdf index c20559af6..03859b9f7 100644 Binary files a/tests/output/test_write_chunks_of_text/output_001.pdf and b/tests/output/test_write_chunks_of_text/output_001.pdf differ diff --git a/tests/output/test_write_chunks_of_text/output_002.pdf b/tests/output/test_write_chunks_of_text/output_002.pdf index 1cb89a2d6..667e6e791 100644 Binary files a/tests/output/test_write_chunks_of_text/output_002.pdf and b/tests/output/test_write_chunks_of_text/output_002.pdf differ diff --git a/tests/output/test_write_chunks_of_text/output_003.pdf b/tests/output/test_write_chunks_of_text/output_003.pdf index 334f4af9c..be6b6d7d8 100644 Binary files a/tests/output/test_write_chunks_of_text/output_003.pdf and b/tests/output/test_write_chunks_of_text/output_003.pdf differ diff --git a/tests/output/test_write_chunks_of_text/output_004.pdf b/tests/output/test_write_chunks_of_text/output_004.pdf index e30d3f3b4..79f6ec4ba 100644 Binary files a/tests/output/test_write_chunks_of_text/output_004.pdf and b/tests/output/test_write_chunks_of_text/output_004.pdf differ diff --git a/tests/output/test_write_chunks_of_text/output_005.pdf b/tests/output/test_write_chunks_of_text/output_005.pdf index eec382b3a..00d0d8ab0 100644 Binary files a/tests/output/test_write_chunks_of_text/output_005.pdf and b/tests/output/test_write_chunks_of_text/output_005.pdf differ diff --git a/tests/output/test_write_chunks_of_text_preserves_bounding_boxes/output.pdf b/tests/output/test_write_chunks_of_text_preserves_bounding_boxes/output.pdf index 2221f1cfc..14f5ba9e6 100644 Binary files a/tests/output/test_write_chunks_of_text_preserves_bounding_boxes/output.pdf and b/tests/output/test_write_chunks_of_text_preserves_bounding_boxes/output.pdf differ diff --git a/tests/output/test_write_code_128_barcode/output.pdf b/tests/output/test_write_code_128_barcode/output.pdf index 3efb83bc2..f359d0a21 100644 Binary files a/tests/output/test_write_code_128_barcode/output.pdf and b/tests/output/test_write_code_128_barcode/output.pdf differ diff --git a/tests/output/test_write_code_128_barcode_in_color/output.pdf b/tests/output/test_write_code_128_barcode_in_color/output.pdf index 8148044da..602c9c662 100644 Binary files a/tests/output/test_write_code_128_barcode_in_color/output.pdf and b/tests/output/test_write_code_128_barcode_in_color/output.pdf differ diff --git a/tests/output/test_write_codeblock/output.pdf b/tests/output/test_write_codeblock/output.pdf index f5d0049a5..eb34af72f 100644 Binary files a/tests/output/test_write_codeblock/output.pdf and b/tests/output/test_write_codeblock/output.pdf differ diff --git a/tests/output/test_write_dragon_curve/output.pdf b/tests/output/test_write_dragon_curve/output.pdf index 13c655428..45587429a 100644 Binary files a/tests/output/test_write_dragon_curve/output.pdf and b/tests/output/test_write_dragon_curve/output.pdf differ diff --git a/tests/output/test_write_drop_down_list/output_001.pdf b/tests/output/test_write_drop_down_list/output_001.pdf index 294d7daf2..d9b6b15bb 100644 Binary files a/tests/output/test_write_drop_down_list/output_001.pdf and b/tests/output/test_write_drop_down_list/output_001.pdf differ diff --git a/tests/output/test_write_drop_down_list/output_002.pdf b/tests/output/test_write_drop_down_list/output_002.pdf index a25980154..9bea073a3 100644 Binary files a/tests/output/test_write_drop_down_list/output_002.pdf and b/tests/output/test_write_drop_down_list/output_002.pdf differ diff --git a/tests/output/test_write_emoji/output.pdf b/tests/output/test_write_emoji/output.pdf index e9b23b693..bf04298e1 100644 Binary files a/tests/output/test_write_emoji/output.pdf and b/tests/output/test_write_emoji/output.pdf differ diff --git a/tests/output/test_write_empty_document/output.pdf b/tests/output/test_write_empty_document/output.pdf index d02e85bd7..8721806c6 100644 Binary files a/tests/output/test_write_empty_document/output.pdf and b/tests/output/test_write_empty_document/output.pdf differ diff --git a/tests/output/test_write_eurion/output_001.pdf b/tests/output/test_write_eurion/output_001.pdf new file mode 100644 index 000000000..eac7af366 Binary files /dev/null and b/tests/output/test_write_eurion/output_001.pdf differ diff --git a/tests/output/test_write_eurion/output_001_ground_truth.png b/tests/output/test_write_eurion/output_001_ground_truth.png new file mode 100644 index 000000000..dadfc0166 Binary files /dev/null and b/tests/output/test_write_eurion/output_001_ground_truth.png differ diff --git a/tests/output/test_write_eurion/output_002.pdf b/tests/output/test_write_eurion/output_002.pdf new file mode 100644 index 000000000..f5cef077f Binary files /dev/null and b/tests/output/test_write_eurion/output_002.pdf differ diff --git a/tests/output/test_write_eurion/output_002_ground_truth.png b/tests/output/test_write_eurion/output_002_ground_truth.png new file mode 100644 index 000000000..b2b17358f Binary files /dev/null and b/tests/output/test_write_eurion/output_002_ground_truth.png differ diff --git a/tests/output/test_write_fixed_column_width_table/output_001.pdf b/tests/output/test_write_fixed_column_width_table/output_001.pdf index 496595c23..68daf647d 100644 Binary files a/tests/output/test_write_fixed_column_width_table/output_001.pdf and b/tests/output/test_write_fixed_column_width_table/output_001.pdf differ diff --git a/tests/output/test_write_fixed_column_width_table/output_002.pdf b/tests/output/test_write_fixed_column_width_table/output_002.pdf index 8b879155d..0492d9534 100644 Binary files a/tests/output/test_write_fixed_column_width_table/output_002.pdf and b/tests/output/test_write_fixed_column_width_table/output_002.pdf differ diff --git a/tests/output/test_write_fixed_column_width_table/output_003.pdf b/tests/output/test_write_fixed_column_width_table/output_003.pdf index 620b893b0..7df91923f 100644 Binary files a/tests/output/test_write_fixed_column_width_table/output_003.pdf and b/tests/output/test_write_fixed_column_width_table/output_003.pdf differ diff --git a/tests/output/test_write_fixed_column_width_table/output_004.pdf b/tests/output/test_write_fixed_column_width_table/output_004.pdf index 61c57572c..83c357d61 100644 Binary files a/tests/output/test_write_fixed_column_width_table/output_004.pdf and b/tests/output/test_write_fixed_column_width_table/output_004.pdf differ diff --git a/tests/output/test_write_fixed_column_width_table/output_005.pdf b/tests/output/test_write_fixed_column_width_table/output_005.pdf index f2a5a5073..4ff54201d 100644 Binary files a/tests/output/test_write_fixed_column_width_table/output_005.pdf and b/tests/output/test_write_fixed_column_width_table/output_005.pdf differ diff --git a/tests/output/test_write_flexi_table/output_001.pdf b/tests/output/test_write_flexi_table/output_001.pdf index a2ff803c4..f0984e395 100644 Binary files a/tests/output/test_write_flexi_table/output_001.pdf and b/tests/output/test_write_flexi_table/output_001.pdf differ diff --git a/tests/output/test_write_flexi_table/output_002.pdf b/tests/output/test_write_flexi_table/output_002.pdf index e23abb5b5..1d8ba7285 100644 Binary files a/tests/output/test_write_flexi_table/output_002.pdf and b/tests/output/test_write_flexi_table/output_002.pdf differ diff --git a/tests/output/test_write_flexi_table/output_003.pdf b/tests/output/test_write_flexi_table/output_003.pdf index 2b2ec920b..be4466a99 100644 Binary files a/tests/output/test_write_flexi_table/output_003.pdf and b/tests/output/test_write_flexi_table/output_003.pdf differ diff --git a/tests/output/test_write_flexi_table/output_004.pdf b/tests/output/test_write_flexi_table/output_004.pdf index c9864f738..7d28b4bed 100644 Binary files a/tests/output/test_write_flexi_table/output_004.pdf and b/tests/output/test_write_flexi_table/output_004.pdf differ diff --git a/tests/output/test_write_flexi_table/output_005.pdf b/tests/output/test_write_flexi_table/output_005.pdf index 5b79184b1..79b214167 100644 Binary files a/tests/output/test_write_flexi_table/output_005.pdf and b/tests/output/test_write_flexi_table/output_005.pdf differ diff --git a/tests/output/test_write_flexi_table_with_preferred_width/output.pdf b/tests/output/test_write_flexi_table_with_preferred_width/output.pdf index 0b79e2f69..c8582c01e 100644 Binary files a/tests/output/test_write_flexi_table_with_preferred_width/output.pdf and b/tests/output/test_write_flexi_table_with_preferred_width/output.pdf differ diff --git a/tests/output/test_write_flowchart_line_art/output.pdf b/tests/output/test_write_flowchart_line_art/output.pdf index cb9b48ec9..5cad376c9 100644 Binary files a/tests/output/test_write_flowchart_line_art/output.pdf and b/tests/output/test_write_flowchart_line_art/output.pdf differ diff --git a/tests/output/test_write_flowchart_line_art/output_ground_truth.png b/tests/output/test_write_flowchart_line_art/output_ground_truth.png index 9952d8006..00d91c087 100644 Binary files a/tests/output/test_write_flowchart_line_art/output_ground_truth.png and b/tests/output/test_write_flowchart_line_art/output_ground_truth.png differ diff --git a/tests/output/test_write_flyer/output.pdf b/tests/output/test_write_flyer/output.pdf index d308e5a65..d18cd9569 100644 Binary files a/tests/output/test_write_flyer/output.pdf and b/tests/output/test_write_flyer/output.pdf differ diff --git a/tests/output/test_write_form_with_missing_xref/output_001.pdf b/tests/output/test_write_form_with_missing_xref/output_001.pdf new file mode 100644 index 000000000..51dc41016 Binary files /dev/null and b/tests/output/test_write_form_with_missing_xref/output_001.pdf differ diff --git a/tests/output/test_write_gradient_rectangular_maze/output_001.pdf b/tests/output/test_write_gradient_rectangular_maze/output_001.pdf index ba6432a3d..1692d9fdc 100644 Binary files a/tests/output/test_write_gradient_rectangular_maze/output_001.pdf and b/tests/output/test_write_gradient_rectangular_maze/output_001.pdf differ diff --git a/tests/output/test_write_gradient_rectangular_maze/output_002.pdf b/tests/output/test_write_gradient_rectangular_maze/output_002.pdf index df791a306..d2dab65a4 100644 Binary files a/tests/output/test_write_gradient_rectangular_maze/output_002.pdf and b/tests/output/test_write_gradient_rectangular_maze/output_002.pdf differ diff --git a/tests/output/test_write_gradient_rectangular_maze/output_003.pdf b/tests/output/test_write_gradient_rectangular_maze/output_003.pdf index e9e95de4e..44fd72783 100644 Binary files a/tests/output/test_write_gradient_rectangular_maze/output_003.pdf and b/tests/output/test_write_gradient_rectangular_maze/output_003.pdf differ diff --git a/tests/output/test_write_grayscale_image/output.pdf b/tests/output/test_write_grayscale_image/output.pdf index 5dc05e35e..4b78658e5 100644 Binary files a/tests/output/test_write_grayscale_image/output.pdf and b/tests/output/test_write_grayscale_image/output.pdf differ diff --git a/tests/output/test_write_hello_world_with_monaco_font/output_001.pdf b/tests/output/test_write_hello_world_with_monaco_font/output_001.pdf index c7e49f0f2..c671b98e0 100644 Binary files a/tests/output/test_write_hello_world_with_monaco_font/output_001.pdf and b/tests/output/test_write_hello_world_with_monaco_font/output_001.pdf differ diff --git a/tests/output/test_write_hello_world_with_simhei_font/output_001.pdf b/tests/output/test_write_hello_world_with_simhei_font/output_001.pdf index d8d096f65..d128148d8 100644 Binary files a/tests/output/test_write_hello_world_with_simhei_font/output_001.pdf and b/tests/output/test_write_hello_world_with_simhei_font/output_001.pdf differ diff --git a/tests/output/test_write_hyphenated_paragraph/output_001.pdf b/tests/output/test_write_hyphenated_paragraph/output_001.pdf index c2044abda..a6c1e8a25 100644 Binary files a/tests/output/test_write_hyphenated_paragraph/output_001.pdf and b/tests/output/test_write_hyphenated_paragraph/output_001.pdf differ diff --git a/tests/output/test_write_hyphenated_paragraph/output_002.pdf b/tests/output/test_write_hyphenated_paragraph/output_002.pdf index ba9e6396e..64e8152a5 100644 Binary files a/tests/output/test_write_hyphenated_paragraph/output_002.pdf and b/tests/output/test_write_hyphenated_paragraph/output_002.pdf differ diff --git a/tests/output/test_write_image_aligned_center/output.pdf b/tests/output/test_write_image_aligned_center/output.pdf index ae59a082d..9c9dd20dc 100644 Binary files a/tests/output/test_write_image_aligned_center/output.pdf and b/tests/output/test_write_image_aligned_center/output.pdf differ diff --git a/tests/output/test_write_image_by_url/output.pdf b/tests/output/test_write_image_by_url/output.pdf index f5cb8100c..4ea32d67b 100644 Binary files a/tests/output/test_write_image_by_url/output.pdf and b/tests/output/test_write_image_by_url/output.pdf differ diff --git a/tests/output/test_write_incomplete_table/output.pdf b/tests/output/test_write_incomplete_table/output.pdf index 8be0bf2a5..312ca8308 100644 Binary files a/tests/output/test_write_incomplete_table/output.pdf and b/tests/output/test_write_incomplete_table/output.pdf differ diff --git a/tests/output/test_write_line_of_text_justified_center/output.pdf b/tests/output/test_write_line_of_text_justified_center/output.pdf index 6efc1f1bf..04b821b35 100644 Binary files a/tests/output/test_write_line_of_text_justified_center/output.pdf and b/tests/output/test_write_line_of_text_justified_center/output.pdf differ diff --git a/tests/output/test_write_line_of_text_justified_full/output.pdf b/tests/output/test_write_line_of_text_justified_full/output.pdf index 27fc2d51a..1fc02d3b3 100644 Binary files a/tests/output/test_write_line_of_text_justified_full/output.pdf and b/tests/output/test_write_line_of_text_justified_full/output.pdf differ diff --git a/tests/output/test_write_line_of_text_justified_right/output_001.pdf b/tests/output/test_write_line_of_text_justified_right/output_001.pdf index c8e984564..e2b59a7d0 100644 Binary files a/tests/output/test_write_line_of_text_justified_right/output_001.pdf and b/tests/output/test_write_line_of_text_justified_right/output_001.pdf differ diff --git a/tests/output/test_write_line_of_text_justified_right/output_002.pdf b/tests/output/test_write_line_of_text_justified_right/output_002.pdf index 168bee43a..9b90ff1a1 100644 Binary files a/tests/output/test_write_line_of_text_justified_right/output_002.pdf and b/tests/output/test_write_line_of_text_justified_right/output_002.pdf differ diff --git a/tests/output/test_write_lissajours_line_art/output.pdf b/tests/output/test_write_lissajours_line_art/output.pdf index 0cb5fe06a..2c69d1313 100644 Binary files a/tests/output/test_write_lissajours_line_art/output.pdf and b/tests/output/test_write_lissajours_line_art/output.pdf differ diff --git a/tests/output/test_write_lissajours_line_art/output_ground_truth.png b/tests/output/test_write_lissajours_line_art/output_ground_truth.png index 0c50b35ea..6a9857fb0 100644 Binary files a/tests/output/test_write_lissajours_line_art/output_ground_truth.png and b/tests/output/test_write_lissajours_line_art/output_ground_truth.png differ diff --git a/tests/output/test_write_long_unordered_list/output.pdf b/tests/output/test_write_long_unordered_list/output.pdf index f0814bf32..e9beabda8 100644 Binary files a/tests/output/test_write_long_unordered_list/output.pdf and b/tests/output/test_write_long_unordered_list/output.pdf differ diff --git a/tests/output/test_write_multiple_pages/output.pdf b/tests/output/test_write_multiple_pages/output.pdf index 00ed80d4a..cb0319b9c 100644 Binary files a/tests/output/test_write_multiple_pages/output.pdf and b/tests/output/test_write_multiple_pages/output.pdf differ diff --git a/tests/output/test_write_nested_ordered_list/output.pdf b/tests/output/test_write_nested_ordered_list/output.pdf index 8f0278352..41b1f2531 100644 Binary files a/tests/output/test_write_nested_ordered_list/output.pdf and b/tests/output/test_write_nested_ordered_list/output.pdf differ diff --git a/tests/output/test_write_nested_unordered_list/output.pdf b/tests/output/test_write_nested_unordered_list/output.pdf index 2d1fa357d..98053234b 100644 Binary files a/tests/output/test_write_nested_unordered_list/output.pdf and b/tests/output/test_write_nested_unordered_list/output.pdf differ diff --git a/tests/output/test_write_nested_unordered_list/output.png b/tests/output/test_write_nested_unordered_list/output.png index da43a9a88..a4d6abaac 100644 Binary files a/tests/output/test_write_nested_unordered_list/output.png and b/tests/output/test_write_nested_unordered_list/output.png differ diff --git a/tests/output/test_write_ordered_list/output_001.pdf b/tests/output/test_write_ordered_list/output_001.pdf index a643580ce..1f3d91771 100644 Binary files a/tests/output/test_write_ordered_list/output_001.pdf and b/tests/output/test_write_ordered_list/output_001.pdf differ diff --git a/tests/output/test_write_ordered_list/output_002.pdf b/tests/output/test_write_ordered_list/output_002.pdf index aab9d5bac..f87577d98 100644 Binary files a/tests/output/test_write_ordered_list/output_002.pdf and b/tests/output/test_write_ordered_list/output_002.pdf differ diff --git a/tests/output/test_write_paragraph/output.pdf b/tests/output/test_write_paragraph/output.pdf index b1793e238..d395ed8df 100644 Binary files a/tests/output/test_write_paragraph/output.pdf and b/tests/output/test_write_paragraph/output.pdf differ diff --git a/tests/output/test_write_paragraph_alignment/output.pdf b/tests/output/test_write_paragraph_alignment/output.pdf index 66b4d0726..1fcac20d2 100644 Binary files a/tests/output/test_write_paragraph_alignment/output.pdf and b/tests/output/test_write_paragraph_alignment/output.pdf differ diff --git a/tests/output/test_write_paragraph_border_left/output.pdf b/tests/output/test_write_paragraph_border_left/output.pdf index e515ff7d8..e52667ed7 100644 Binary files a/tests/output/test_write_paragraph_border_left/output.pdf and b/tests/output/test_write_paragraph_border_left/output.pdf differ diff --git a/tests/output/test_write_paragraph_force_split/output.pdf b/tests/output/test_write_paragraph_force_split/output.pdf index f251aac79..f16e72326 100644 Binary files a/tests/output/test_write_paragraph_force_split/output.pdf and b/tests/output/test_write_paragraph_force_split/output.pdf differ diff --git a/tests/output/test_write_paragraph_justified_center/output_001.pdf b/tests/output/test_write_paragraph_justified_center/output_001.pdf index c807c9c96..ad95ae438 100644 Binary files a/tests/output/test_write_paragraph_justified_center/output_001.pdf and b/tests/output/test_write_paragraph_justified_center/output_001.pdf differ diff --git a/tests/output/test_write_paragraph_justified_center/output_002.pdf b/tests/output/test_write_paragraph_justified_center/output_002.pdf index d9b7fa1cb..d26995e94 100644 Binary files a/tests/output/test_write_paragraph_justified_center/output_002.pdf and b/tests/output/test_write_paragraph_justified_center/output_002.pdf differ diff --git a/tests/output/test_write_paragraph_justified_center_with_padding/output.pdf b/tests/output/test_write_paragraph_justified_center_with_padding/output.pdf index 9dfadd86d..5cb82f376 100644 Binary files a/tests/output/test_write_paragraph_justified_center_with_padding/output.pdf and b/tests/output/test_write_paragraph_justified_center_with_padding/output.pdf differ diff --git a/tests/output/test_write_paragraph_justified_center_with_padding_and_border/output.pdf b/tests/output/test_write_paragraph_justified_center_with_padding_and_border/output.pdf index 20554c9df..956b438b7 100644 Binary files a/tests/output/test_write_paragraph_justified_center_with_padding_and_border/output.pdf and b/tests/output/test_write_paragraph_justified_center_with_padding_and_border/output.pdf differ diff --git a/tests/output/test_write_paragraph_justified_center_with_padding_and_border_and_background/output.pdf b/tests/output/test_write_paragraph_justified_center_with_padding_and_border_and_background/output.pdf index 165f1f2a0..3bdf973ab 100644 Binary files a/tests/output/test_write_paragraph_justified_center_with_padding_and_border_and_background/output.pdf and b/tests/output/test_write_paragraph_justified_center_with_padding_and_border_and_background/output.pdf differ diff --git a/tests/output/test_write_paragraph_justified_full/output.pdf b/tests/output/test_write_paragraph_justified_full/output.pdf index 63068dbcf..c4dcfc7c1 100644 Binary files a/tests/output/test_write_paragraph_justified_full/output.pdf and b/tests/output/test_write_paragraph_justified_full/output.pdf differ diff --git a/tests/output/test_write_paragraph_justified_right/output.pdf b/tests/output/test_write_paragraph_justified_right/output.pdf index 540d31a6f..ddee96ef0 100644 Binary files a/tests/output/test_write_paragraph_justified_right/output.pdf and b/tests/output/test_write_paragraph_justified_right/output.pdf differ diff --git a/tests/output/test_write_paragraph_preserve_space/output.pdf b/tests/output/test_write_paragraph_preserve_space/output.pdf index 2b1850cb5..665597b8b 100644 Binary files a/tests/output/test_write_paragraph_preserve_space/output.pdf and b/tests/output/test_write_paragraph_preserve_space/output.pdf differ diff --git a/tests/output/test_write_paragraph_save_twice/output_001.pdf b/tests/output/test_write_paragraph_save_twice/output_001.pdf index 9e14ec541..0b4106137 100644 Binary files a/tests/output/test_write_paragraph_save_twice/output_001.pdf and b/tests/output/test_write_paragraph_save_twice/output_001.pdf differ diff --git a/tests/output/test_write_paragraph_save_twice/output_002.pdf b/tests/output/test_write_paragraph_save_twice/output_002.pdf index bb60b435f..afe46a23d 100644 Binary files a/tests/output/test_write_paragraph_save_twice/output_002.pdf and b/tests/output/test_write_paragraph_save_twice/output_002.pdf differ diff --git a/tests/output/test_write_paragraph_with_accented_letters/output.pdf b/tests/output/test_write_paragraph_with_accented_letters/output.pdf index d1cb8c353..d62d9c395 100644 Binary files a/tests/output/test_write_paragraph_with_accented_letters/output.pdf and b/tests/output/test_write_paragraph_with_accented_letters/output.pdf differ diff --git a/tests/output/test_write_paragraphs_using_multi_column_layout/output.pdf b/tests/output/test_write_paragraphs_using_multi_column_layout/output.pdf index 90576122d..955e26f3c 100644 Binary files a/tests/output/test_write_paragraphs_using_multi_column_layout/output.pdf and b/tests/output/test_write_paragraphs_using_multi_column_layout/output.pdf differ diff --git a/tests/output/test_write_paragraphs_using_single_column_layout/output.pdf b/tests/output/test_write_paragraphs_using_single_column_layout/output.pdf index 51f0fd019..e8e6aa618 100644 Binary files a/tests/output/test_write_paragraphs_using_single_column_layout/output.pdf and b/tests/output/test_write_paragraphs_using_single_column_layout/output.pdf differ diff --git a/tests/output/test_write_paragraphs_with_headings/output.pdf b/tests/output/test_write_paragraphs_with_headings/output.pdf index 9d807f831..38efa4653 100644 Binary files a/tests/output/test_write_paragraphs_with_headings/output.pdf and b/tests/output/test_write_paragraphs_with_headings/output.pdf differ diff --git a/tests/output/test_write_pdf_a_1b/output_001.pdf b/tests/output/test_write_pdf_a_1b/output_001.pdf index 34a595772..f01ff62c4 100644 Binary files a/tests/output/test_write_pdf_a_1b/output_001.pdf and b/tests/output/test_write_pdf_a_1b/output_001.pdf differ diff --git a/tests/output/test_write_pdf_a_1b/output_002.pdf b/tests/output/test_write_pdf_a_1b/output_002.pdf index 037d24e01..cffae4651 100644 Binary files a/tests/output/test_write_pdf_a_1b/output_002.pdf and b/tests/output/test_write_pdf_a_1b/output_002.pdf differ diff --git a/tests/output/test_write_pil_image/output.pdf b/tests/output/test_write_pil_image/output.pdf index 51a1df6b1..8f8b520fe 100644 Binary files a/tests/output/test_write_pil_image/output.pdf and b/tests/output/test_write_pil_image/output.pdf differ diff --git a/tests/output/test_write_png_image_by_url/output.pdf b/tests/output/test_write_png_image_by_url/output.pdf index 442869130..dc16adbeb 100644 Binary files a/tests/output/test_write_png_image_by_url/output.pdf and b/tests/output/test_write_png_image_by_url/output.pdf differ diff --git a/tests/output/test_write_push_button/output_001.pdf b/tests/output/test_write_push_button/output_001.pdf index 9594b3189..74c198f96 100644 Binary files a/tests/output/test_write_push_button/output_001.pdf and b/tests/output/test_write_push_button/output_001.pdf differ diff --git a/tests/output/test_write_push_button/output_002.pdf b/tests/output/test_write_push_button/output_002.pdf index f89603002..d38b06803 100644 Binary files a/tests/output/test_write_push_button/output_002.pdf and b/tests/output/test_write_push_button/output_002.pdf differ diff --git a/tests/output/test_write_push_button/output_003.pdf b/tests/output/test_write_push_button/output_003.pdf index 8d4ad7e11..126d2dd09 100644 Binary files a/tests/output/test_write_push_button/output_003.pdf and b/tests/output/test_write_push_button/output_003.pdf differ diff --git a/tests/output/test_write_radar_plot/output.pdf b/tests/output/test_write_radar_plot/output.pdf index 8b85534fd..c1e96ab6e 100644 Binary files a/tests/output/test_write_radar_plot/output.pdf and b/tests/output/test_write_radar_plot/output.pdf differ diff --git a/tests/output/test_write_rectangular_hitomezashi/output.pdf b/tests/output/test_write_rectangular_hitomezashi/output.pdf index 11f1d90b3..c47a0e8a3 100644 Binary files a/tests/output/test_write_rectangular_hitomezashi/output.pdf and b/tests/output/test_write_rectangular_hitomezashi/output.pdf differ diff --git a/tests/output/test_write_rectangular_maze/output.pdf b/tests/output/test_write_rectangular_maze/output.pdf index d4798765f..b84ee1d56 100644 Binary files a/tests/output/test_write_rectangular_maze/output.pdf and b/tests/output/test_write_rectangular_maze/output.pdf differ diff --git a/tests/output/test_write_single_line_justified_full/output_001.pdf b/tests/output/test_write_single_line_justified_full/output_001.pdf index 629f963d0..d415e22bd 100644 Binary files a/tests/output/test_write_single_line_justified_full/output_001.pdf and b/tests/output/test_write_single_line_justified_full/output_001.pdf differ diff --git a/tests/output/test_write_single_line_justified_full/output_002.pdf b/tests/output/test_write_single_line_justified_full/output_002.pdf index 291830dd9..a3d87d961 100644 Binary files a/tests/output/test_write_single_line_justified_full/output_002.pdf and b/tests/output/test_write_single_line_justified_full/output_002.pdf differ diff --git a/tests/output/test_write_table_with_col_span/output.pdf b/tests/output/test_write_table_with_col_span/output.pdf index 07f31bb28..bf6fbd1d3 100644 Binary files a/tests/output/test_write_table_with_col_span/output.pdf and b/tests/output/test_write_table_with_col_span/output.pdf differ diff --git a/tests/output/test_write_table_with_image/output.pdf b/tests/output/test_write_table_with_image/output.pdf index 87e1a0df3..686acb9ad 100644 Binary files a/tests/output/test_write_table_with_image/output.pdf and b/tests/output/test_write_table_with_image/output.pdf differ diff --git a/tests/output/test_write_table_with_non_black_paragraphs/output.pdf b/tests/output/test_write_table_with_non_black_paragraphs/output.pdf index 17db47082..9bf34619d 100644 Binary files a/tests/output/test_write_table_with_non_black_paragraphs/output.pdf and b/tests/output/test_write_table_with_non_black_paragraphs/output.pdf differ diff --git a/tests/output/test_write_table_with_rainbow_background/output.pdf b/tests/output/test_write_table_with_rainbow_background/output.pdf index 918efd322..db83e5c76 100644 Binary files a/tests/output/test_write_table_with_rainbow_background/output.pdf and b/tests/output/test_write_table_with_rainbow_background/output.pdf differ diff --git a/tests/output/test_write_table_with_row_span/output.pdf b/tests/output/test_write_table_with_row_span/output.pdf index b9f3b956f..1c27e3078 100644 Binary files a/tests/output/test_write_table_with_row_span/output.pdf and b/tests/output/test_write_table_with_row_span/output.pdf differ diff --git a/tests/output/test_write_table_with_special_characters/output.pdf b/tests/output/test_write_table_with_special_characters/output.pdf index b4b7dcf1a..e8a23afa6 100644 Binary files a/tests/output/test_write_table_with_special_characters/output.pdf and b/tests/output/test_write_table_with_special_characters/output.pdf differ diff --git a/tests/output/test_write_tents_and_trees/output.pdf b/tests/output/test_write_tents_and_trees/output.pdf index 410ed614d..fac89f048 100644 Binary files a/tests/output/test_write_tents_and_trees/output.pdf and b/tests/output/test_write_tents_and_trees/output.pdf differ diff --git a/tests/output/test_write_text_area/output_001.pdf b/tests/output/test_write_text_area/output_001.pdf index 64064a00a..0d4049d60 100644 Binary files a/tests/output/test_write_text_area/output_001.pdf and b/tests/output/test_write_text_area/output_001.pdf differ diff --git a/tests/output/test_write_text_area/output_002.pdf b/tests/output/test_write_text_area/output_002.pdf index dbe80673e..e4d426cf1 100644 Binary files a/tests/output/test_write_text_area/output_002.pdf and b/tests/output/test_write_text_area/output_002.pdf differ diff --git a/tests/output/test_write_text_field/output_001.pdf b/tests/output/test_write_text_field/output_001.pdf index 5c24182fa..ccfad017d 100644 Binary files a/tests/output/test_write_text_field/output_001.pdf and b/tests/output/test_write_text_field/output_001.pdf differ diff --git a/tests/output/test_write_text_field/output_002.pdf b/tests/output/test_write_text_field/output_002.pdf index 5d958cb5c..b8beb4f39 100644 Binary files a/tests/output/test_write_text_field/output_002.pdf and b/tests/output/test_write_text_field/output_002.pdf differ diff --git a/tests/output/test_write_unordered_list/output.pdf b/tests/output/test_write_unordered_list/output.pdf index 65864d505..316e4e4b5 100644 Binary files a/tests/output/test_write_unordered_list/output.pdf and b/tests/output/test_write_unordered_list/output.pdf differ diff --git a/tests/output/test_write_unsplash_image/output.pdf b/tests/output/test_write_unsplash_image/output.pdf new file mode 100644 index 000000000..f3211c77e Binary files /dev/null and b/tests/output/test_write_unsplash_image/output.pdf differ diff --git a/tests/output/test_write_using_low_level_instructions/output.pdf b/tests/output/test_write_using_low_level_instructions/output.pdf index 584f8bcb5..224306290 100644 Binary files a/tests/output/test_write_using_low_level_instructions/output.pdf and b/tests/output/test_write_using_low_level_instructions/output.pdf differ diff --git a/tests/output/test_write_with_truetype_font/output_001.pdf b/tests/output/test_write_with_truetype_font/output_001.pdf index 6b8d175b5..0e25c753d 100644 Binary files a/tests/output/test_write_with_truetype_font/output_001.pdf and b/tests/output/test_write_with_truetype_font/output_001.pdf differ diff --git a/tests/output/test_write_with_truetype_font/output_002.pdf b/tests/output/test_write_with_truetype_font/output_002.pdf index 7c63a3d71..f19552ed2 100644 Binary files a/tests/output/test_write_with_truetype_font/output_002.pdf and b/tests/output/test_write_with_truetype_font/output_002.pdf differ diff --git a/tests/output/test_write_with_truetype_font/output_002.png b/tests/output/test_write_with_truetype_font/output_002.png index a8b2d1b3f..779800c12 100644 Binary files a/tests/output/test_write_with_truetype_font/output_002.png and b/tests/output/test_write_with_truetype_font/output_002.png differ diff --git a/tests/output/test_write_with_truetype_font/output_003.pdf b/tests/output/test_write_with_truetype_font/output_003.pdf index fd520dafe..fce0e7e36 100644 Binary files a/tests/output/test_write_with_truetype_font/output_003.pdf and b/tests/output/test_write_with_truetype_font/output_003.pdf differ diff --git a/tests/output/test_write_with_truetype_font/output_004.pdf b/tests/output/test_write_with_truetype_font/output_004.pdf index 6290e3a9f..8c2c856c9 100644 Binary files a/tests/output/test_write_with_truetype_font/output_004.pdf and b/tests/output/test_write_with_truetype_font/output_004.pdf differ diff --git a/tests/output/test_write_xl_image/output.pdf b/tests/output/test_write_xl_image/output.pdf index fd28bb6a5..945464218 100644 Binary files a/tests/output/test_write_xl_image/output.pdf and b/tests/output/test_write_xl_image/output.pdf differ diff --git a/tests/pdf/canvas/layout/forms/test_write_form_with_missing_xref.py b/tests/pdf/canvas/layout/forms/test_write_form_with_missing_xref.py new file mode 100644 index 000000000..45c1c3635 --- /dev/null +++ b/tests/pdf/canvas/layout/forms/test_write_form_with_missing_xref.py @@ -0,0 +1,111 @@ +import typing +import unittest +from datetime import datetime +from decimal import Decimal +from pathlib import Path + +from borb.pdf.canvas.color.color import HexColor +from borb.pdf.canvas.geometry.rectangle import Rectangle +from borb.pdf.canvas.layout.forms.push_button import PushButton, JavaScriptPushButton +from borb.pdf.canvas.layout.forms.text_area import TextArea +from borb.pdf.canvas.layout.forms.text_field import TextField +from borb.pdf.canvas.layout.layout_element import Alignment +from borb.pdf.canvas.layout.page_layout.multi_column_layout import SingleColumnLayout +from borb.pdf.canvas.layout.page_layout.page_layout import PageLayout +from borb.pdf.canvas.layout.table.fixed_column_width_table import ( + FixedColumnWidthTable as Table, + FixedColumnWidthTable, +) +from borb.pdf.canvas.layout.table.flexible_column_width_table import ( + FlexibleColumnWidthTable, +) +from borb.pdf.canvas.layout.text.paragraph import Paragraph +from borb.pdf.document.document import Document +from borb.pdf.page.page import Page +from borb.pdf.pdf import PDF + + +class TestWriteFormWithMissingXRef(unittest.TestCase): + """ + This test attempts to extract the text of each PDF in the corpus + """ + + def __init__(self, methodName="runTest"): + super().__init__(methodName) + # find output dir + p: Path = Path(__file__).parent + while "output" not in [x.stem for x in p.iterdir() if x.is_dir()]: + p = p.parent + p = p / "output" + self.output_dir = Path(p, Path(__file__).stem.replace(".py", "")) + if not self.output_dir.exists(): + self.output_dir.mkdir() + + def test_write_form_using_flexiblecolumnwidthtable(self): + + # create empty document + pdf: Document = Document() + + # create empty page + page: Page = Page() + + # add page to document + pdf.append_page(page) + + # add test information + layout = SingleColumnLayout(page) + layout.add( + Table(number_of_columns=2, number_of_rows=3) + .add(Paragraph("Date", font="Helvetica-Bold")) + .add(Paragraph(datetime.now().strftime("%d/%m/%Y, %H:%M:%S"))) + .add(Paragraph("Test", font="Helvetica-Bold")) + .add(Paragraph(Path(__file__).stem)) + .add(Paragraph("Description", font="Helvetica-Bold")) + .add( + Paragraph( + """ + This test creates a PDF with a form in it. + Because of the way forms are initialized, they need an XREF to be present at layout. + This, combined with FlexibleColumnWidthTable was a problem previously, causing a KeyError. This should be fixed. + """ + ) + ) + .set_padding_on_all_cells(Decimal(2), Decimal(2), Decimal(2), Decimal(2)) + ) + + # add empty space + layout.add(Paragraph(" ")) + + # add form + layout.add( + FlexibleColumnWidthTable(number_of_columns=2, number_of_rows=9) + .add(Paragraph("User Name: ")) + .add(TextField(field_name="username")) + .add(Paragraph("ID: ")) + .add(TextField(field_name="eid")) + .add(Paragraph("Computer Name: ")) + .add(TextField(field_name="newpcname")) + .add(Paragraph("Replacing Computer: ")) + .add(TextField(field_name="oldpcname")) + .add(Paragraph("S/N: ")) + .add(TextField(field_name="oldserial")) + .add(Paragraph("Keep in Service")) + .add(TextField(field_name="service")) + .add(Paragraph("Location")) + .add(TextField(field_name="location")) + .add(Paragraph("Model: ")) + .add(TextField(field_name="model")) + .add(Paragraph("S/N: ")) + .add(TextField(field_name="serial")) + .set_padding_on_all_cells(Decimal(2), Decimal(2), Decimal(2), Decimal(2)) + .no_borders() + ) + + # write + file = self.output_dir / "output_001.pdf" + with open(file, "wb") as pdf_file_handle: + PDF.dumps(pdf_file_handle, pdf) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/pdf/canvas/layout/forms/test_write_push_button.py b/tests/pdf/canvas/layout/forms/test_write_push_button.py index e0a5db56c..f866da0ad 100644 --- a/tests/pdf/canvas/layout/forms/test_write_push_button.py +++ b/tests/pdf/canvas/layout/forms/test_write_push_button.py @@ -175,7 +175,7 @@ def test_write_javascript_push_button_using_layout_manager(self): text="Hello World!", javascript="app.alert('Hello World', 3)", horizontal_alignment=Alignment.RIGHT, - margin_top=Decimal(10) + margin_top=Decimal(10), ) ) diff --git a/tests/pdf/canvas/layout/image/test_write_unsplash_image.py b/tests/pdf/canvas/layout/image/test_write_unsplash_image.py new file mode 100644 index 000000000..681f139f6 --- /dev/null +++ b/tests/pdf/canvas/layout/image/test_write_unsplash_image.py @@ -0,0 +1,76 @@ +import unittest +from datetime import datetime +from pathlib import Path + +import keyring + +from borb.io.read.types import Decimal +from borb.pdf.canvas.layout.image.image import Image +from borb.pdf.canvas.layout.image.unsplash import Unsplash +from borb.pdf.canvas.layout.layout_element import Alignment +from borb.pdf.canvas.layout.page_layout.multi_column_layout import SingleColumnLayout +from borb.pdf.canvas.layout.table.fixed_column_width_table import ( + FixedColumnWidthTable as Table, +) +from borb.pdf.canvas.layout.text.paragraph import Paragraph +from borb.pdf.document.document import Document +from borb.pdf.page.page import Page +from borb.pdf.pdf import PDF +from tests.test_util import compare_visually_to_ground_truth + + +class TestWriteUnsplashImage(unittest.TestCase): + """ + This test creates a PDF with an unsplash Image in it + """ + + def __init__(self, methodName="runTest"): + super().__init__(methodName) + # find output dir + p: Path = Path(__file__).parent + while "output" not in [x.stem for x in p.iterdir() if x.is_dir()]: + p = p.parent + p = p / "output" + self.output_dir = Path(p, Path(__file__).stem.replace(".py", "")) + if not self.output_dir.exists(): + self.output_dir.mkdir() + + def test_write_document(self): + + # create empty document + pdf: Document = Document() + + # create empty page + page: Page = Page() + + # add page to document + pdf.append_page(page) + + # add Image + layout = SingleColumnLayout(page) + + # add test information + layout.add( + Table(number_of_columns=2, number_of_rows=3) + .add(Paragraph("Date", font="Helvetica-Bold")) + .add(Paragraph(datetime.now().strftime("%d/%m/%Y, %H:%M:%S"))) + .add(Paragraph("Test", font="Helvetica-Bold")) + .add(Paragraph(Path(__file__).stem)) + .add(Paragraph("Description", font="Helvetica-Bold")) + .add(Paragraph("This test creates a PDF with an Unsplash Image in it.")) + .set_padding_on_all_cells(Decimal(2), Decimal(2), Decimal(2), Decimal(2)) + ) + + # add image + layout.add( + Unsplash.get_image(["cherry", "blossom"], Decimal(400), Decimal(300)) + ) + + # write + file = self.output_dir / "output.pdf" + with open(file, "wb") as pdf_file_handle: + PDF.dumps(pdf_file_handle, pdf) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/pdf/canvas/layout/line_art/test_write_eurion.py b/tests/pdf/canvas/layout/line_art/test_write_eurion.py new file mode 100644 index 000000000..e7f34142c --- /dev/null +++ b/tests/pdf/canvas/layout/line_art/test_write_eurion.py @@ -0,0 +1,148 @@ +import math +import random +import unittest +from datetime import datetime +from pathlib import Path + +from borb.io.read.types import Decimal +from borb.pdf.canvas.color.color import HexColor +from borb.pdf.canvas.geometry.rectangle import Rectangle +from borb.pdf.canvas.layout.layout_element import Alignment +from borb.pdf.canvas.layout.page_layout.multi_column_layout import SingleColumnLayout +from borb.pdf.canvas.layout.shape.disjoint_shape import DisjointShape +from borb.pdf.canvas.layout.table.fixed_column_width_table import ( + FixedColumnWidthTable as Table, +) +from borb.pdf.canvas.layout.text.paragraph import Paragraph +from borb.pdf.canvas.line_art.line_art_factory import LineArtFactory +from borb.pdf.document.document import Document +from borb.pdf.page.page import Page +from borb.pdf.pdf import PDF +from tests.test_util import compare_visually_to_ground_truth + + +class TestWriteEurion(unittest.TestCase): + """ + This test creates a PDF with an eurion symbol in it + """ + + def __init__(self, methodName="runTest"): + super().__init__(methodName) + # find output dir + p: Path = Path(__file__).parent + while "output" not in [x.stem for x in p.iterdir() if x.is_dir()]: + p = p.parent + p = p / "output" + self.output_dir = Path(p, Path(__file__).stem.replace(".py", "")) + if not self.output_dir.exists(): + self.output_dir.mkdir() + + def _write_eurion( + self, + page: Page, + layout: SingleColumnLayout, + ): + w = page.get_page_info().get_width() + h = page.get_page_info().get_height() - Decimal(200) + assert w is not None + assert h is not None + layout.add( + DisjointShape( + LineArtFactory.EURion(Rectangle(0, 0, 50, 50)), + horizontal_alignment=Alignment.CENTERED, + vertical_alignment=Alignment.MIDDLE, + stroke_color=HexColor("ff0000"), + line_width=Decimal(3), + ), + ) + + def _write_eurion_rotated( + self, + page: Page, + layout: SingleColumnLayout, + ): + w = page.get_page_info().get_width() + h = page.get_page_info().get_height() - Decimal(200) + assert w is not None + assert h is not None + layout.add( + DisjointShape( + LineArtFactory.EURion(Rectangle(0, 0, 50, 50)), + horizontal_alignment=Alignment.CENTERED, + vertical_alignment=Alignment.MIDDLE, + stroke_color=HexColor("ff0000"), + line_width=Decimal(3), + ).rotate(math.radians(45)), + ) + + def test_write_document_001(self): + + # create document + pdf = Document() + + # add page + page = Page() + pdf.append_page(page) + + # add test information + layout = SingleColumnLayout(page) + layout.add( + Table(number_of_columns=2, number_of_rows=3) + .add(Paragraph("Date", font="Helvetica-Bold")) + .add(Paragraph(datetime.now().strftime("%d/%m/%Y, %H:%M:%S"))) + .add(Paragraph("Test", font="Helvetica-Bold")) + .add(Paragraph(Path(__file__).stem)) + .add(Paragraph("Description", font="Helvetica-Bold")) + .add(Paragraph("This test creates a PDF with an EURion shape in it.")) + .set_padding_on_all_cells(Decimal(2), Decimal(2), Decimal(2), Decimal(2)) + ) + + self._write_eurion(page, layout) + + # determine output location + out_file = self.output_dir / "output_001.pdf" + + # attempt to store PDF + with open(out_file, "wb") as in_file_handle: + PDF.dumps(in_file_handle, pdf) + + with open(out_file, "rb") as in_file_handle: + PDF.loads(in_file_handle) + + compare_visually_to_ground_truth(out_file) + + def test_write_document_002(self): + + # create document + pdf = Document() + + # add page + page = Page() + pdf.append_page(page) + + # add test information + layout = SingleColumnLayout(page) + layout.add( + Table(number_of_columns=2, number_of_rows=3) + .add(Paragraph("Date", font="Helvetica-Bold")) + .add(Paragraph(datetime.now().strftime("%d/%m/%Y, %H:%M:%S"))) + .add(Paragraph("Test", font="Helvetica-Bold")) + .add(Paragraph(Path(__file__).stem)) + .add(Paragraph("Description", font="Helvetica-Bold")) + .add(Paragraph("This test creates a PDF with an EURion shape in it.")) + .set_padding_on_all_cells(Decimal(2), Decimal(2), Decimal(2), Decimal(2)) + ) + + self._write_eurion_rotated(page, layout) + + # determine output location + out_file = self.output_dir / "output_002.pdf" + + # attempt to store PDF + with open(out_file, "wb") as in_file_handle: + PDF.dumps(in_file_handle, pdf) + + with open(out_file, "rb") as in_file_handle: + PDF.loads(in_file_handle) + + compare_visually_to_ground_truth(out_file) diff --git a/tests/pdf/canvas/layout/paragraph/output.pdf b/tests/pdf/canvas/layout/paragraph/output.pdf new file mode 100644 index 000000000..2b8edf212 Binary files /dev/null and b/tests/pdf/canvas/layout/paragraph/output.pdf differ diff --git a/tests/pdf/canvas/layout/paragraph/test_hello_world.py b/tests/pdf/canvas/layout/paragraph/test_hello_world.py index 1e998209b..b8385da01 100644 --- a/tests/pdf/canvas/layout/paragraph/test_hello_world.py +++ b/tests/pdf/canvas/layout/paragraph/test_hello_world.py @@ -1,3 +1,4 @@ +import unittest from pathlib import Path from borb.pdf.canvas.layout.page_layout.multi_column_layout import SingleColumnLayout @@ -6,26 +7,39 @@ from borb.pdf.page.page import Page from borb.pdf.pdf import PDF +unittest.TestLoader.sortTestMethodsUsing = None -def main(): - # create an empty Document - pdf = Document() +class TestWriteHelloWorld(unittest.TestCase): + def __init__(self, methodName="runTest"): + super().__init__(methodName) + # find output dir + p: Path = Path(__file__).parent + while "output" not in [x.stem for x in p.iterdir() if x.is_dir()]: + p = p.parent + p = p / "output" + self.output_dir = Path(p, Path(__file__).stem.replace(".py", "")) + if not self.output_dir.exists(): + self.output_dir.mkdir() - # add an empty Page - page = Page() - pdf.append_page(page) + def test_write_hello_world(self): - # use a PageLayout (SingleColumnLayout in this case) - layout = SingleColumnLayout(page) + # create an empty Document + pdf = Document() - # add a Paragraph object - layout.add(Paragraph("Hello World!")) + # add an empty Page + page = Page() + pdf.append_page(page) - # store the PDF - with open(Path("output.pdf"), "wb") as pdf_file_handle: - PDF.dumps(pdf_file_handle, pdf) + # use a PageLayout (SingleColumnLayout in this case) + layout = SingleColumnLayout(page) + # add a Paragraph object + layout.add(Paragraph("Hello World!")) -if __name__ == "__main__": - main() + # determine output location + out_file = self.output_dir / "output.pdf" + + # attempt to store PDF + with open(out_file, "wb") as out_file_handle: + PDF.dumps(out_file_handle, pdf) diff --git a/tests/pdf/document/duplicate/__init__.py b/tests/pdf/document/duplicate/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/pdf/document/duplicate/test_duplicate_pages.py b/tests/pdf/document/duplicate/test_duplicate_pages.py new file mode 100644 index 000000000..04c885f20 --- /dev/null +++ b/tests/pdf/document/duplicate/test_duplicate_pages.py @@ -0,0 +1,140 @@ +import typing +import unittest +from datetime import datetime +from decimal import Decimal +from pathlib import Path + +from borb.pdf.canvas.geometry.rectangle import Rectangle +from borb.pdf.canvas.layout.layout_element import Alignment +from borb.pdf.canvas.layout.page_layout.multi_column_layout import SingleColumnLayout +from borb.pdf.canvas.layout.table.fixed_column_width_table import ( + FixedColumnWidthTable as Table, +) +from borb.pdf.canvas.layout.text.paragraph import Paragraph +from borb.pdf.document.document import Document +from borb.pdf.page.page import Page +from borb.pdf.pdf import PDF + +unittest.TestLoader.sortTestMethodsUsing = None + + +class TestDuplicatePages(unittest.TestCase): + def __init__(self, methodName="runTest"): + super().__init__(methodName) + # find output dir + p: Path = Path(__file__).parent + while "output" not in [x.stem for x in p.iterdir() if x.is_dir()]: + p = p.parent + p = p / "output" + self.output_dir = Path(p, Path(__file__).stem.replace(".py", "")) + if not self.output_dir.exists(): + self.output_dir.mkdir() + + def test_write_document(self): + + # create document + pdf = Document() + + # add page + page = Page() + pdf.append_page(page) + + # add test information + layout = SingleColumnLayout(page) + layout.add( + Table(number_of_columns=2, number_of_rows=3) + .add(Paragraph("Date", font="Helvetica-Bold")) + .add(Paragraph(datetime.now().strftime("%d/%m/%Y, %H:%M:%S"))) + .add(Paragraph("Test", font="Helvetica-Bold")) + .add(Paragraph(Path(__file__).stem)) + .add(Paragraph("Description", font="Helvetica-Bold")) + .add( + Paragraph( + "This test creates a PDF. Subsequent tests will duplicate pages in this PDF." + ) + ) + .set_padding_on_all_cells(Decimal(2), Decimal(2), Decimal(2), Decimal(2)) + ) + + # attempt to store PDF + with open(self.output_dir / "output_000.pdf", "wb") as out_file_handle: + PDF.dumps(out_file_handle, pdf) + + def test_duplicate_pages_in_pdf(self): + + # attempt to store PDF + doc: typing.Optional[Document] = None + with open(self.output_dir / "output_000.pdf", "rb") as in_file_handle: + doc = PDF.loads(in_file_handle) + + # check + assert doc is not None + + # append duplicate page + doc.append_page(doc.get_page(0)) + + # attempt to store PDF + with open(self.output_dir / "output_001.pdf", "wb") as out_file_handle: + PDF.dumps(out_file_handle, doc) + + def test_duplicate_pages_in_pdf_and_add_content_before(self): + + # attempt to store PDF + doc: typing.Optional[Document] = None + with open(self.output_dir / "output_000.pdf", "rb") as in_file_handle: + doc = PDF.loads(in_file_handle) + + # check + assert doc is not None + + # add content + Paragraph( + """ + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. + Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. + Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. + """, + text_alignment=Alignment.JUSTIFIED, + ).layout( + doc.get_page(0), + Rectangle(Decimal(100), Decimal(100), Decimal(200), Decimal(200)), + ) + + # append duplicate page + doc.append_page(doc.get_page(0)) + + # attempt to store PDF + with open(self.output_dir / "output_002.pdf", "wb") as out_file_handle: + PDF.dumps(out_file_handle, doc) + + def test_duplicate_pages_in_pdf_and_add_content_after(self): + + # attempt to store PDF + doc: typing.Optional[Document] = None + with open(self.output_dir / "output_000.pdf", "rb") as in_file_handle: + doc = PDF.loads(in_file_handle) + + # check + assert doc is not None + + # append duplicate page + doc.append_page(doc.get_page(0)) + + # add content + Paragraph( + """ + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. + Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. + Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. + """, + text_alignment=Alignment.JUSTIFIED, + ).layout( + doc.get_page(0), + Rectangle(Decimal(100), Decimal(100), Decimal(200), Decimal(200)), + ) + + # attempt to store PDF + with open(self.output_dir / "output_003.pdf", "wb") as out_file_handle: + PDF.dumps(out_file_handle, doc) diff --git a/tests/pdf/document/easier_imports/__init__.py b/tests/pdf/document/easier_imports/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/pdf/document/easier_imports/test_easier_imports.py b/tests/pdf/document/easier_imports/test_easier_imports.py new file mode 100644 index 000000000..03fe73cba --- /dev/null +++ b/tests/pdf/document/easier_imports/test_easier_imports.py @@ -0,0 +1,48 @@ +import unittest +from pathlib import Path + +# simplified imports +from borb.pdf import Document +from borb.pdf import HexColor +from borb.pdf import Page +from borb.pdf import SingleColumnLayout +from borb.pdf import Paragraph +from borb.pdf import PDF + + +unittest.TestLoader.sortTestMethodsUsing = None + + +class TestWriteHelloWorldWithEasierImports(unittest.TestCase): + def __init__(self, methodName="runTest"): + super().__init__(methodName) + # find output dir + p: Path = Path(__file__).parent + while "output" not in [x.stem for x in p.iterdir() if x.is_dir()]: + p = p.parent + p = p / "output" + self.output_dir = Path(p, Path(__file__).stem.replace(".py", "")) + if not self.output_dir.exists(): + self.output_dir.mkdir() + + def test_write_hello_world_with_easier_imports(self): + + # create an empty Document + pdf = Document() + + # add an empty Page + page = Page() + pdf.append_page(page) + + # use a PageLayout (SingleColumnLayout in this case) + layout = SingleColumnLayout(page) + + # add a Paragraph object + layout.add(Paragraph("Hello World!", font_color=HexColor("56cbf9"))) + + # determine output location + out_file = self.output_dir / "output.pdf" + + # attempt to store PDF + with open(out_file, "wb") as out_file_handle: + PDF.dumps(out_file_handle, pdf) diff --git a/tests/pdf/document/fix_broken/test_fix_broken_xref.py b/tests/pdf/document/fix_broken/test_fix_broken_xref.py index ddbe07c3b..b99174b5d 100644 --- a/tests/pdf/document/fix_broken/test_fix_broken_xref.py +++ b/tests/pdf/document/fix_broken/test_fix_broken_xref.py @@ -4,7 +4,9 @@ from decimal import Decimal from pathlib import Path -from borb.pdf.canvas.layout.table.fixed_column_width_table import FixedColumnWidthTable as Table +from borb.pdf.canvas.layout.table.fixed_column_width_table import ( + FixedColumnWidthTable as Table, +) from borb.pdf.canvas.layout.page_layout.multi_column_layout import SingleColumnLayout from borb.pdf.canvas.layout.text.paragraph import Paragraph from borb.pdf.document.document import Document @@ -58,7 +60,6 @@ def test_create_document(self): with open(out_file, "wb") as in_file_handle: PDF.dumps(in_file_handle, pdf) - def test_break_document(self): # read input document bytes_in: bytes = b"" @@ -71,17 +72,29 @@ def test_break_document(self): while i < len(bytes_in): # 1 0 obj - if 48 <= bytes_in[i] <= 57 and bytes_in[i+1] == 32 and 48 <= bytes_in[i+2] <= 57 and bytes_in[i+3] == 32 and bytes_in[i+4] == 111 and bytes_in[i+5] == 98 and bytes_in[i+6] == 106: + if ( + 48 <= bytes_in[i] <= 57 + and bytes_in[i + 1] == 32 + and 48 <= bytes_in[i + 2] <= 57 + and bytes_in[i + 3] == 32 + and bytes_in[i + 4] == 111 + and bytes_in[i + 5] == 98 + and bytes_in[i + 6] == 106 + ): pdf_out_file_handle.write(b"\n") - pdf_out_file_handle.write(b"% These bytes were added after the document was created.\n") - pdf_out_file_handle.write(b"% This causes the XREF table to be wrong.\n") + pdf_out_file_handle.write( + b"% These bytes were added after the document was created.\n" + ) + pdf_out_file_handle.write( + b"% This causes the XREF table to be wrong.\n" + ) pdf_out_file_handle.write(b"\n") - pdf_out_file_handle.write(bytes_in[i:i+7]) + pdf_out_file_handle.write(bytes_in[i : i + 7]) i += 7 continue # regular - pdf_out_file_handle.write(bytes_in[i:i+1]) + pdf_out_file_handle.write(bytes_in[i : i + 1]) i += 1 def test_read_broken_document(self): @@ -93,13 +106,13 @@ def test_read_broken_document(self): doc = PDF.loads(pdf_in_file_handle, [l]) # read info properties - assert doc.get_document_info().get_producer() == 'borb' + assert doc.get_document_info().get_producer() == "borb" # check number of pages assert doc.get_document_info().get_number_of_pages() == 1 # check text txt: str = l.get_text_for_page(0) - assert 'test_fix_broken_xref' in txt - assert 'Description This test creates a PDF with 1 page.' in txt - assert 'Subsequent tests then screw up the XREF.' in txt \ No newline at end of file + assert "test_fix_broken_xref" in txt + assert "Description This test creates a PDF with 1 page." in txt + assert "Subsequent tests then screw up the XREF." in txt diff --git a/tests/pdf/document/test_inline_object_io.py b/tests/pdf/document/test_inline_object_io.py new file mode 100644 index 000000000..2c8a54eb6 --- /dev/null +++ b/tests/pdf/document/test_inline_object_io.py @@ -0,0 +1,125 @@ +import unittest +from datetime import datetime +from decimal import Decimal +from pathlib import Path + +import typing + +from borb.pdf.canvas.color.color import HexColor +from borb.pdf.canvas.layout.page_layout.multi_column_layout import SingleColumnLayout +from borb.pdf.canvas.layout.table.fixed_column_width_table import ( + FixedColumnWidthTable as Table, +) +from borb.pdf.canvas.layout.text.paragraph import Paragraph +from borb.pdf.document.document import Document +from borb.pdf.page.page import Page +from borb.pdf.pdf import PDF +from tests.test_util import compare_visually_to_ground_truth + +unittest.TestLoader.sortTestMethodsUsing = None + + +class TestInlineObjectIO(unittest.TestCase): + def __init__(self, methodName="runTest"): + super().__init__(methodName) + # find output dir + p: Path = Path(__file__).parent + while "output" not in [x.stem for x in p.iterdir() if x.is_dir()]: + p = p.parent + p = p / "output" + self.output_dir = Path(p, Path(__file__).stem.replace(".py", "")) + if not self.output_dir.exists(): + self.output_dir.mkdir() + + def test_write_document(self): + + # create document + pdf = Document() + + # add page + page = Page() + pdf.append_page(page) + + # add test information + layout = SingleColumnLayout(page) + layout.add( + Table(number_of_columns=2, number_of_rows=3) + .add(Paragraph("Date", font="Helvetica-Bold")) + .add(Paragraph(datetime.now().strftime("%d/%m/%Y, %H:%M:%S"))) + .add(Paragraph("Test", font="Helvetica-Bold")) + .add(Paragraph(Path(__file__).stem)) + .add(Paragraph("Description", font="Helvetica-Bold")) + .add( + Paragraph( + "This test creates a PDF with 5 pages, each page containing a Paragraph of text. Subsequent tests will check the way inline objects were persisted." + ) + ) + .set_padding_on_all_cells(Decimal(2), Decimal(2), Decimal(2), Decimal(2)) + ) + + N: int = 5 + for i in range(0, 5): + layout.add( + Paragraph( + "Page %d / %d" % (i + 1, N), + font_size=Decimal(20), + font_color=HexColor("f1cd2e"), + ) + ) + for _ in range(0, 3): + layout.add( + Paragraph( + """ + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. + Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. + Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. + """, + font_size=Decimal(10), + ) + ) + if i != N - 1: + page = Page() + pdf.append_page(page) + layout = SingleColumnLayout(page) + + # determine output location + out_file = self.output_dir / "output_001.pdf" + + # attempt to store PDF + with open(out_file, "wb") as in_file_handle: + PDF.dumps(in_file_handle, pdf) + + compare_visually_to_ground_truth(out_file) + + def test_inline_object_io(self): + + bts: typing.Optional[bytes] = None + with open(self.output_dir / "output_001.pdf", "rb") as in_file_handle: + bts = in_file_handle.read() + + i: int = 0 + dictionary_nesting: int = 0 + while i < len(bts): + + # start of dictionary + if bts[i] == ord("<") == bts[i + 1]: + dictionary_nesting += 1 + i += 2 + continue + + # end of dictionary + if bts[i] == ord(">") == bts[i + 1]: + dictionary_nesting -= 1 + i += 2 + continue + + # inline array + if dictionary_nesting > 0 and bts[i] == ord("["): + while i < len(bts) and bts[i] != ord("]"): + i += 1 + assert bts[i] == ord("]") + assert bts[i + 1] != ord("\n") + + # default + i += 1 diff --git a/tests/pdf/page/annotations/test_add_sound_annotation.py b/tests/pdf/page/annotations/test_add_sound_annotation.py index 54c091b5c..bb5de164b 100644 --- a/tests/pdf/page/annotations/test_add_sound_annotation.py +++ b/tests/pdf/page/annotations/test_add_sound_annotation.py @@ -17,7 +17,6 @@ class TestAddSoundAnnotation(unittest.TestCase): - def __init__(self, methodName="runTest"): super().__init__(methodName) # find output dir @@ -112,7 +111,8 @@ def test_add_sound_annotation_002(self): # add sound annotation page.append_annotation( SoundAnnotation( - img.get_bounding_box(), "https://commons.wikimedia.org/wiki/File:Variations_for_flute_and_piano.mp3" + img.get_bounding_box(), + "https://commons.wikimedia.org/wiki/File:Variations_for_flute_and_piano.mp3", ) ) diff --git a/tests/pdf/page/annotations/test_annotation_name.py b/tests/pdf/page/annotations/test_annotation_name.py new file mode 100644 index 000000000..f05cbfa5b --- /dev/null +++ b/tests/pdf/page/annotations/test_annotation_name.py @@ -0,0 +1,108 @@ +import typing +import unittest +from datetime import datetime +from decimal import Decimal +from pathlib import Path + +from borb.pdf.canvas.color.color import HexColor +from borb.pdf.canvas.geometry.rectangle import Rectangle +from borb.pdf.canvas.layout.annotation.circle_annotation import CircleAnnotation +from borb.pdf.canvas.layout.page_layout.multi_column_layout import SingleColumnLayout +from borb.pdf.canvas.layout.table.fixed_column_width_table import ( + FixedColumnWidthTable as Table, +) +from borb.pdf.canvas.layout.text.paragraph import Paragraph +from borb.pdf.document.document import Document +from borb.pdf.page.page import Page +from borb.pdf.pdf import PDF +from tests.test_util import compare_visually_to_ground_truth + + +class TestAddCircleAnnotation(unittest.TestCase): + def __init__(self, methodName="runTest"): + super().__init__(methodName) + # find output dir + p: Path = Path(__file__).parent + while "output" not in [x.stem for x in p.iterdir() if x.is_dir()]: + p = p.parent + p = p / "output" + self.output_dir = Path(p, Path(__file__).stem.replace(".py", "")) + if not self.output_dir.exists(): + self.output_dir.mkdir() + + def test_add_circle_annotations(self): + + # create document + pdf = Document() + + # add page + page = Page() + pdf.append_page(page) + + # add test information + layout = SingleColumnLayout(page) + layout.add( + Table(number_of_columns=2, number_of_rows=3) + .add(Paragraph("Date", font="Helvetica-Bold")) + .add(Paragraph(datetime.now().strftime("%d/%m/%Y, %H:%M:%S"))) + .add(Paragraph("Test", font="Helvetica-Bold")) + .add(Paragraph(Path(__file__).stem)) + .add(Paragraph("Description", font="Helvetica-Bold")) + .add( + Paragraph( + "This test creates a PDF with an empty Page, and nine circle annotations" + ) + ) + .set_padding_on_all_cells(Decimal(2), Decimal(2), Decimal(2), Decimal(2)) + ) + + # add annotation + w: Decimal = pdf.get_page(0).get_page_info().get_width() + h: Decimal = pdf.get_page(0).get_page_info().get_height() + for i in range(0, 3): + for j in range(0, 3): + pdf.get_page(0).append_annotation( + CircleAnnotation( + bounding_box=Rectangle( + w / Decimal(2) - Decimal(32 * 1.5) + i * 32, + h / Decimal(2) - Decimal(32 * 1.5) + j * 32, + Decimal(32), + Decimal(32), + ), + stroke_color=HexColor("0B3954"), + fill_color=HexColor("f1cd2e"), + ) + ) + + # attempt to store PDF + with open(self.output_dir / "output.pdf", "wb") as out_file_handle: + PDF.dumps(out_file_handle, pdf) + + # attempt to re-open PDF + with open(self.output_dir / "output.pdf", "rb") as in_file_handle: + doc = PDF.loads(in_file_handle) + + # compare visually + compare_visually_to_ground_truth(self.output_dir / "output.pdf") + + def test_annotation_names(self): + + # attempt to re-open PDF + doc: typing.Optional[Document] = None + with open(self.output_dir / "output.pdf", "rb") as in_file_handle: + doc = PDF.loads(in_file_handle) + + # check whether a Document was loaded + assert doc is not None + + # check names + annots = doc["XRef"]["Trailer"]["Root"]["Pages"]["Kids"][0]["Annots"] + assert str(annots[0]["NM"]) == "annotation-000" + assert str(annots[1]["NM"]) == "annotation-001" + assert str(annots[2]["NM"]) == "annotation-002" + assert str(annots[3]["NM"]) == "annotation-003" + assert str(annots[4]["NM"]) == "annotation-004" + assert str(annots[5]["NM"]) == "annotation-005" + assert str(annots[6]["NM"]) == "annotation-006" + assert str(annots[7]["NM"]) == "annotation-007" + assert str(annots[8]["NM"]) == "annotation-008" diff --git a/tests/pdf/page/annotations/test_copy_circle_annotation.py b/tests/pdf/page/annotations/test_copy_circle_annotation.py new file mode 100644 index 000000000..6ec0f4755 --- /dev/null +++ b/tests/pdf/page/annotations/test_copy_circle_annotation.py @@ -0,0 +1,137 @@ +import unittest +from datetime import datetime +from decimal import Decimal +from pathlib import Path + +from borb.io.read.types import Name, List +from borb.pdf.canvas.color.color import HexColor +from borb.pdf.canvas.geometry.rectangle import Rectangle +from borb.pdf.canvas.layout.annotation.circle_annotation import CircleAnnotation +from borb.pdf.canvas.layout.page_layout.multi_column_layout import SingleColumnLayout +from borb.pdf.canvas.layout.table.fixed_column_width_table import ( + FixedColumnWidthTable as Table, +) +from borb.pdf.canvas.layout.text.paragraph import Paragraph +from borb.pdf.document.document import Document +from borb.pdf.page.page import Page +from borb.pdf.pdf import PDF +from tests.test_util import compare_visually_to_ground_truth + + +class TestCopyCircleAnnotation(unittest.TestCase): + def __init__(self, methodName="runTest"): + super().__init__(methodName) + # find output dir + p: Path = Path(__file__).parent + while "output" not in [x.stem for x in p.iterdir() if x.is_dir()]: + p = p.parent + p = p / "output" + self.output_dir = Path(p, Path(__file__).stem.replace(".py", "")) + if not self.output_dir.exists(): + self.output_dir.mkdir() + + def test_create_document_001(self): + + # create document + pdf = Document() + + # add page + page = Page() + pdf.append_page(page) + + # add test information + layout = SingleColumnLayout(page) + layout.add( + Table(number_of_columns=2, number_of_rows=3) + .add(Paragraph("Date", font="Helvetica-Bold")) + .add(Paragraph(datetime.now().strftime("%d/%m/%Y, %H:%M:%S"))) + .add(Paragraph("Test", font="Helvetica-Bold")) + .add(Paragraph(Path(__file__).stem)) + .add(Paragraph("Description", font="Helvetica-Bold")) + .add( + Paragraph( + "This test creates a PDF with an empty Page, and a circle annotation." + ) + ) + .set_padding_on_all_cells(Decimal(2), Decimal(2), Decimal(2), Decimal(2)) + ) + + # add annotation + w: Decimal = pdf.get_page(0).get_page_info().get_width() + h: Decimal = pdf.get_page(0).get_page_info().get_height() + pdf.get_page(0).append_annotation( + CircleAnnotation( + bounding_box=Rectangle( + w / Decimal(2) - Decimal(32), + h / Decimal(2) - Decimal(32), + Decimal(64), + Decimal(64), + ), + stroke_color=HexColor("0B3954"), + fill_color=HexColor("f1cd2e"), + ) + ) + + # attempt to store PDF + with open(self.output_dir / "output_001.pdf", "wb") as out_file_handle: + PDF.dumps(out_file_handle, pdf) + + # test + compare_visually_to_ground_truth(self.output_dir / "output_001.pdf") + + def test_create_document_002(self): + # create document + pdf = Document() + + # add page + page = Page() + pdf.append_page(page) + + # add test information + layout = SingleColumnLayout(page) + layout.add( + Table(number_of_columns=2, number_of_rows=3) + .add(Paragraph("Date", font="Helvetica-Bold")) + .add(Paragraph(datetime.now().strftime("%d/%m/%Y, %H:%M:%S"))) + .add(Paragraph("Test", font="Helvetica-Bold")) + .add(Paragraph(Path(__file__).stem)) + .add(Paragraph("Description", font="Helvetica-Bold")) + .add( + Paragraph( + "This test creates an empty PDF. A later test will copy an annotation (from another document) to it." + ) + ) + .set_padding_on_all_cells(Decimal(2), Decimal(2), Decimal(2), Decimal(2)) + ) + + # attempt to store PDF + with open(self.output_dir / "output_002.pdf", "wb") as out_file_handle: + PDF.dumps(out_file_handle, pdf) + + # test + compare_visually_to_ground_truth(self.output_dir / "output_002.pdf") + + def test_copy_circle_annotation(self): + + # open document 1 + doc_in_a = None + with open(self.output_dir / "output_001.pdf", "rb") as in_file_handle: + doc_in_a = PDF.loads(in_file_handle) + + # open document 2 + doc_in_b = None + with open(self.output_dir / "output_002.pdf", "rb") as in_file_handle: + doc_in_b = PDF.loads(in_file_handle) + + # copy annotations + annots = doc_in_a.get_page(0).get_annotations() + doc_in_b.get_page(0)[Name("Annots")] = List() + for a in annots: + doc_in_b.get_page(0)["Annots"].append(a) + + # attempt to store PDF + with open(self.output_dir / "output_003.pdf", "wb") as out_file_handle: + PDF.dumps(out_file_handle, doc_in_b) + + # test + compare_visually_to_ground_truth(self.output_dir / "output_003.pdf") diff --git a/tests/toolkit/paragraph/__init__.py b/tests/toolkit/paragraph/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/toolkit/paragraph/test_simple_paragraph_extraction.py b/tests/toolkit/paragraph/test_simple_paragraph_extraction.py new file mode 100644 index 000000000..95a13fa1e --- /dev/null +++ b/tests/toolkit/paragraph/test_simple_paragraph_extraction.py @@ -0,0 +1,113 @@ +import typing +import unittest +from datetime import datetime +from pathlib import Path + +from borb.io.read.types import Decimal +from borb.pdf.canvas.color.color import HexColor +from borb.pdf.canvas.layout.annotation.square_annotation import SquareAnnotation +from borb.pdf.canvas.layout.page_layout.multi_column_layout import SingleColumnLayout +from borb.pdf.canvas.layout.table.fixed_column_width_table import ( + FixedColumnWidthTable as Table, +) +from borb.pdf.canvas.layout.text.paragraph import Paragraph +from borb.pdf.document.document import Document +from borb.pdf.page.page import Page +from borb.pdf.pdf import PDF +from borb.toolkit.text.simple_paragraph_extraction import SimpleParagraphExtraction +from tests.test_util import compare_visually_to_ground_truth + + +class TestSimpleParagraphExtraction(unittest.TestCase): + """ + This test creates a PDF with an unsplash Image in it + """ + + def __init__(self, methodName="runTest"): + super().__init__(methodName) + # find output dir + p: Path = Path(__file__).parent + while "output" not in [x.stem for x in p.iterdir() if x.is_dir()]: + p = p.parent + p = p / "output" + self.output_dir = Path(p, Path(__file__).stem.replace(".py", "")) + if not self.output_dir.exists(): + self.output_dir.mkdir() + + def test_write_document(self): + + # create empty document + pdf: Document = Document() + + # create empty page + page: Page = Page() + + # add page to document + pdf.append_page(page) + + # add Image + layout = SingleColumnLayout(page) + + # add test information + layout.add( + Table(number_of_columns=2, number_of_rows=3) + .add(Paragraph("Date", font="Helvetica-Bold")) + .add(Paragraph(datetime.now().strftime("%d/%m/%Y, %H:%M:%S"))) + .add(Paragraph("Test", font="Helvetica-Bold")) + .add(Paragraph(Path(__file__).stem)) + .add(Paragraph("Description", font="Helvetica-Bold")) + .add(Paragraph("This test creates a PDF with a Paragraph in it.")) + .set_padding_on_all_cells(Decimal(2), Decimal(2), Decimal(2), Decimal(2)) + ) + + layout.add( + Paragraph( + """ + Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, + eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. + Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, + sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. + Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, + sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. + Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? + Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, + vel illum qui dolorem eum fugiat quo voluptas nulla pariatur? + """, + font_size=Decimal(8), + ) + ) + + # write + file = self.output_dir / "output_000.pdf" + with open(file, "wb") as pdf_file_handle: + PDF.dumps(pdf_file_handle, pdf) + + def test_simple_paragraph_extraction(self): + + # read document + l: SimpleParagraphExtraction = SimpleParagraphExtraction( + maximum_multiplied_leading=Decimal(1.7) + ) + doc: typing.Optional[Document] = None + with open(self.output_dir / "output_000.pdf", "rb") as pdf_file_handle: + doc = PDF.loads(pdf_file_handle, [l]) + + assert doc is not None + + # add SquareAnnotation(s) + for p in l.get_paragraphs_for_page(0): + doc.get_page(0).append_annotation( + SquareAnnotation(p.get_bounding_box(), stroke_color=HexColor("f1cd2e")) + ) + + # write + file = self.output_dir / "output_001.pdf" + with open(file, "wb") as pdf_file_handle: + PDF.dumps(pdf_file_handle, doc) + + # compare + compare_visually_to_ground_truth(file) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/toolkit/text/test_extract_keywords.py b/tests/toolkit/text/test_extract_keywords.py index 31c043f97..202ea44f1 100644 --- a/tests/toolkit/text/test_extract_keywords.py +++ b/tests/toolkit/text/test_extract_keywords.py @@ -16,6 +16,11 @@ from borb.toolkit.text.text_rank_keyword_extraction import TextRankKeywordExtraction from borb.toolkit.text.tf_idf_keyword_extraction import TFIDFKeywordExtraction +import nltk + +nltk.download("punkt") +nltk.download("averaged_perceptron_tagger") + unittest.TestLoader.sortTestMethodsUsing = None