Exemple #1
0
async def addIdentity(pdf, annotationItem:AnnotationDetail):
    try:
        sizePapper= pdf.get_size(annotationItem.page - 1)
        xStart= annotationItem.x
        yStart= sizePapper[1] - (annotationItem.y)
        # Keep image ration at 1:1
        imageHeight = annotationItem.height * 0.8
        xEnd= xStart + imageHeight
        yEnd= yStart - (annotationItem.height * 0.8)
        imageLocation = "Member/" + annotationItem.identification.encryptedUserId + "/" + annotationItem.identification.imageFileName
        pdf.add_annotation(
            'image',
            Location(x1= xStart, y1= yEnd, x2= xEnd, y2= yStart, page= annotationItem.page - 1),
            Appearance(stroke_width= 0, image= imageLocation),
        )
        xEnd= xStart + annotationItem.width
        yStart= yStart - (annotationItem.height * 0.8)
        yEnd= yStart - (annotationItem.height * 0.2)
        textIdentification= annotationItem.identification.name + "\n" + annotationItem.identification.code
        pdf.add_annotation(
            'text',
            Location(x1= xStart, y1= yEnd, x2= xEnd, y2= yStart, page= annotationItem.page - 1),
            Appearance(fill= [0.1, 0.1, 0.1], stroke_width= 2, font_size= 8, content= textIdentification),
        )
    except Exception as e:
        #TODO print logging
        print(str(e))
Exemple #2
0
    def _add_image_annotations(self, a, appearance, y1=120, y2=160):
        # Draw a row of image annotations for each type of image, with a label
        # on top of the image type
        x = 10
        text_appearance = Appearance(
            font_size=5,
            text_baseline=constants.TEXT_BASELINE_BOTTOM,
            fill=[0, 0, 0]
        )
        a.add_annotation(
            'text',
            Location(x1=x, y1=y2, x2=(x + 20), y2=(y2 + 10), page=0),
            text_appearance.copy(content='PNG'),
        )
        for png_file in PNG_FILES[:-1]:
            a.add_annotation(
                'image',
                Location(x1=x, y1=y1, x2=(x + 40), y2=y2, page=0),
                appearance.copy(image=png_file),
            )
            x += 50
        # The last PNG file has transparency, so let's draw a rectangle behind
        # so you can see that it's transparent.
        a.add_annotation(
            'square',
            Location(x1=x, y1=y1, x2=(x + 40), y2=y2, page=0),
            self.gaudy.copy(stroke_width=0),
        )
        a.add_annotation(
            'image',
            Location(x1=x, y1=y1, x2=(x + 40), y2=y2, page=0),
            appearance.copy(image=PNG_FILES[-1]),
        )
        x += 50

        a.add_annotation(
            'text',
            Location(x1=x, y1=y2, x2=(x + 20), y2=(y2 + 10), page=0),
            text_appearance.copy(content='JPEG'),
        )
        for jpeg_file in JPEG_FILES:
            a.add_annotation(
                'image',
                Location(x1=x, y1=y1, x2=(x + 40), y2=y2, page=0),
                appearance.copy(image=jpeg_file),
            )
            x += 50

        a.add_annotation(
            'text',
            Location(x1=x, y1=y2, x2=(x + 20), y2=(y2 + 10), page=0),
            text_appearance.copy(content='GIF'),
        )
        for gif_file in GIF_FILES:
            a.add_annotation(
                'image',
                Location(x1=x, y1=y1, x2=(x + 40), y2=y2, page=0),
                appearance.copy(image=gif_file),
            )
            x += 50
    def setUp(self):
        self.gaudy = Appearance(
            stroke_color=[1, 0, 0],
            stroke_width=3,
            fill=[0, 1, 0],
            content='Latin',
            font_size=12,
            wrap_text=True,
        )

        self.transparent = self.gaudy.copy(
            fill=[0, 0, 1, 0.5],
            stroke_color=[1, 0, 0, 0.25],
        )

        self.top_left = self.gaudy.copy(
            fill=[0, 0.5, 0.75],
            content=(r"Though yet of Hamlet, our dear brother's death \\ "
                     r"The memory be green"),
            font_size=6,
            text_align='left',
            text_baseline='top',
        )
        self.top_center = self.top_left.copy(text_align='center')
        self.top_right = self.top_left.copy(text_align='right')

        self.middle_left = self.top_left.copy(text_baseline='middle')
        self.middle_center = self.middle_left.copy(text_align='center')
        self.middle_right = self.middle_left.copy(text_align='right')

        self.bottom_left = self.top_left.copy(text_baseline='bottom')
        self.bottom_center = self.bottom_left.copy(text_align='center')
        # One text annotation is transparent grey
        self.bottom_right = self.bottom_left.copy(
            text_align='right',
            fill=[0, 0, 0, 0.25],
        )

        self.texts = [
            self.top_left,
            self.top_center,
            self.top_right,
            self.middle_left,
            self.middle_center,
            self.middle_right,
            self.bottom_left,
            self.bottom_center,
            self.bottom_right,
        ]

        self.image_appearance = Appearance(stroke_width=0)
        self.transparent_image_appearance = self.image_appearance.copy(
            fill_transparency=0.5,
            stroke_transparency=0.5,
        )
Exemple #4
0
    def annotate(self, annotations, infile, outfile):
        """
        Annotates a file.

        Args:
            annotations: list of annotations (title, rgb color, page #, x1, y1, x2, y2)
            infile: full path to input file
            outfile: full path to output file
        """

        annotator = PdfAnnotator(infile)

        # List of text ranges already defined
        ranges = []

        for title, rgb, page, x1, y1, x2, y2 in annotations:
            # Highlight text
            annotator.add_annotation(
                "square", Location(x1=x1, y1=y1, x2=x2, y2=y2, page=page),
                Appearance(fill=rgb + (0.3, ),
                           stroke_color=rgb + (0.3, ),
                           stroke_width=0))

            if title:
                # Determine if title text should be in left or right margin
                if x1 < 250:
                    x1, x2 = max(5, x1 - 35), x1
                else:
                    x1, x2 = x2, x2 + 35

                # Calculate center of highlight annotation and offset
                center = y1 + ((y2 - y1) / 2)
                offset = min(max(5, len(title)), 20)

                # Set position of text annotation. Handle column layout conflicts.
                y1, y2 = self.position(ranges, page, x1 >= 250, center, offset)

                # Add title annotation next to highlight
                annotator.add_annotation(
                    "text", Location(x1=x1, y1=y1, x2=x2, y2=y2, page=page),
                    Appearance(fill=rgb + (1, ),
                               font_size=7,
                               stroke_width=1,
                               content=title))

                # Register range
                ranges.append((page, 0 if x1 < 250 else 1, y1, y2))

        annotator.write(outfile)
    def _add_explicit_image_annotation(self, a):
        """Add an image annotation using ContentStream commands instead of the
        Image type's commands. This is testing that the external XObjects API
        works, and that images can be embedded inside other, more complex
        annotations.
        """
        x1, y1, x2, y2 = 10, 310, 50, 350
        location = Location(x1=x1, y1=y1, x2=x2, y2=y2, page=0)

        content_stream = ContentStream([
            StrokeColor(1, 0, 0),
            Rect(x1, y1, x2 - x1, y2 - y1),
            Save(),
            # The image is inside an outer rectangle
            CTM(Image.get_ctm(x1 + 10, y1 + 10, x2 - 10, y2 - 10)),
            XObject('MyXObject'),
            Restore(),
            Stroke(),
        ])
        appearance = Appearance(
            appearance_stream=content_stream,
            xobjects={
                'MyXObject': Image.make_image_xobject(PNG_FILES[0]),
            },
        )

        a.add_annotation(
            'square',
            location=location,
            appearance=appearance,
        )
    def draw_bounding_poly_pdf(
        self,
        pdf: PdfReader,
        vertices: List[Dict],
        color: AnyStr,
    ):
        """Annotate a PDF document by drawing a bounding polygon of a given color

        Args:
            pdf: PDF document opened with pdfrw.PdfReader
            vertices: List of 4 vertices describing the polygon
                Each vertex should a dictionary with normalized coordinates e.g. {"x": 0.1, "y": 0.3}
            color: Name of the color e.g. "red", "teal", "skyblue"
                Full list on https://matplotlib.org/3.3.2/gallery/color/named_colors.html

        """
        if len(vertices) == 4:
            pdf_annotator = PdfAnnotator(pdf)
            pdf_annotator.set_page_dimensions(
                dimensions=(1, 1), page_number=0)  # normalize page dimensions
            pdf_annotator.add_annotation(
                annotation_type="polygon",
                location=Location(
                    points=[(vertices[i].get("x", 0.0),
                             1.0 - vertices[i].get("y", 0.0))
                            for i in range(4)],
                    page=0,
                ),
                appearance=Appearance(stroke_color=colors.to_rgba(color)),
            )
        else:
            raise ValueError(
                f"Bounding polygon does not contain 4 vertices: {vertices}")
        return pdf
Exemple #7
0
    def _add_explicit_graphics_state_annotation(self, a):
        graphics_states = {
            'BevelSquare': GraphicsState(
                line_join=constants.LINE_JOIN_BEVEL,
                line_cap=constants.LINE_CAP_SQUARE,
                stroke_transparency=0.75,
            ),
            'MiterButt': GraphicsState(
                line_join=constants.LINE_JOIN_MITER,
                line_cap=constants.LINE_CAP_BUTT,
                stroke_transparency=0.5,
            ),
            'RoundRound': GraphicsState(
                line_join=constants.LINE_JOIN_ROUND,
                line_cap=constants.LINE_CAP_ROUND,
                stroke_transparency=0.25,
            ),
        }

        # Defines the bounding box of the chevrons
        x1, y1, x2, y2 = 60, 310, 100, 350
        lines_location = Location(x1=x1, y1=y1, x2=x2, y2=y2, page=0)

        # Defines the start/end of the chevrons
        x1, midpoint, x2 = 65, 80, 95
        y1 = 315

        content_stream = ContentStream([
            Save(),
            StrokeWidth(5),

            CSGraphicsState('BevelSquare'),
            Move(x1, y1),
            Line(midpoint, y1 + 10),
            Line(x2, y1),
            Stroke(),

            CSGraphicsState('MiterButt'),
            Move(x1, y1 + 10),
            Line(midpoint, y1 + 20),
            Line(x2, y1 + 10),
            Stroke(),

            CSGraphicsState('RoundRound'),
            Move(x1, y1 + 20),
            Line(midpoint, y1 + 30),
            Line(x2, y1 + 20),
            Stroke(),

            Restore(),
        ])
        appearance = Appearance(
            appearance_stream=content_stream,
            graphics_states=graphics_states,
        )
        a.add_annotation(
            'square',
            location=lines_location,
            appearance=appearance,
        )
 def _add_rounded_rectangles(self, a):
     """Add a few rounded rectangles with different border radii."""
     y1, y2 = 360, 410
     xs = [10, 60, 110]
     rxs = [5, 10, 15]
     rys = [5, 5, 15]
     for x1, rx, ry in zip(xs, rxs, rys):
         x2 = x1 + 40
         location = Location(x1=x1, y1=y1, x2=x2, y2=y2, page=0)
         content_stream = ContentStream([
             Save(),
             StrokeColor(1, 0, 0),
             FillColor(0, 1, 0),
         ])
         add_rounded_rectangle(
             stream=content_stream,
             x=x1,
             y=y1,
             width=(x2 - x1),
             height=(y2 - y1),
             rx=rx,
             ry=ry,
         )
         content_stream.extend([
             StrokeAndFill(),
             Restore(),
         ])
         appearance = Appearance(appearance_stream=content_stream, )
         a.add_annotation('square', location, appearance)
async def addText(pdf, annotationItem: AnnotationDetail):
    try:
        sizePapper = pdf.get_size(annotationItem.page - 1)
        xStart = annotationItem.x
        yStart = sizePapper[1] - (annotationItem.y)
        if annotationItem.width == 0:
            xEnd = sizePapper[0]
        else:
            xEnd = xStart + annotationItem.width
        yEnd = yStart - annotationItem.height
        textUsed = annotationItem.text
        pdf.add_annotation(
            'text',
            Location(x1=xStart,
                     y1=yEnd,
                     x2=xEnd,
                     y2=yStart,
                     page=annotationItem.page - 1),
            Appearance(fill=[1, 0, 0],
                       stroke_width=1,
                       font_size=9,
                       content=textUsed),
        )
    except Exception as e:
        #TODO print logging
        print(str(e))
Exemple #10
0
 def annotate_text(self, text: 'parse_pdf.Text', color=BLUE):
     loc = Location(x1=text.x_min,
                    y1=self.page_height - text.y_max,
                    x2=text.x_max,
                    y2=self.page_height - text.y_min,
                    page=text.page)
     appearance = Appearance(stroke_color=color, stroke_width=1)
     self.annotations.append(('square', loc, appearance))
Exemple #11
0
def redactDocument(dirname, filename, boxes):
    a = PdfAnnotator(dirname+"/"+filename)
    for i in boxes:
        a.add_annotation('square', Location(x1=i[0]*72, y1=(790-i[1]*72), x2=i[2]*72, y2=(790-i[3]*72), page=0),
        Appearance(stroke_color=(0, 0, 0), stroke_width=13, fill=(0,0,0)),)
    resultFilename = 'Redacted'+filename
    a.write(resultFilename) 
    print("[INFO]: Process Completed.")
    return resultFilename
Exemple #12
0
def pdf_add_Annot_old(path, file, stamp):
    from pdf_annotate import PdfAnnotator, Location, Appearance
    a = PdfAnnotator(os.path.join(path, file))
    a.add_annotation(
        'square',
        Location(x1=50, y1=50, x2=100, y2=100, page=0),
        Appearance(stroke_color=(1, 0, 0), stroke_width=5),
    )
    a.write(os.path.join(
        path, 'new_w_stamp.pdf'))  # or use overwrite=True if you feel lucky
Exemple #13
0
def redactDocument(dirname, filename, boxes):
    print("Dirname: " + dirname[0:len(dirname) - 14])
    print("Filename: " + filename)
    dirname = dirname[0:len(dirname) - 14]
    a = PdfAnnotator(dirname+filename)
    for i in boxes:
        a.add_annotation('square', Location(x1=i[0]*72, y1=(790-i[1]*72), x2=i[2]*72, y2=(790-i[3]*72), page=0),
        Appearance(stroke_color=(0, 0, 0), stroke_width=13, fill=(0,0,0)),)
    a.write(dirname + filename) 
    print("[INFO]: Process Completed.")
    return dirname + filename
Exemple #14
0
 def annotate_group(self, texts: List['parse_pdf.Text'], color=BLUE):
     x1 = min(t.x_min for t in texts)
     x2 = max(t.x_max for t in texts)
     y1 = min(t.y_min for t in texts)
     y2 = min(t.y_max for t in texts)
     loc = Location(x1=x1,
                    y1=self.page_height - y2,
                    x2=x2,
                    y2=self.page_height - y1,
                    page=texts[0].page)
     appearance = Appearance(stroke_color=color, stroke_width=1)
     self.annotations.append(('square', loc, appearance))
Exemple #15
0
async def addPolyLine(pdf, annotationItem:AnnotationDetail):
    try:
        sizePapper= pdf.get_size(annotationItem.page - 1)
        # Penyesuaian titik coordinat (0,0) dan titik start line
        # karena di python leftbottom di javascript lefttop
        y = sizePapper[1] - annotationItem.y
        for idx in range(len(annotationItem.points)):
            point = annotationItem.points[idx]
            annotationItem.points[idx]= [point[0] + annotationItem.x, y - point[1]]
        pdf.add_annotation(
            'polyline',
            Location(points= annotationItem.points, page= annotationItem.page - 1),
            Appearance(stroke_color= (1, 0, 0), stroke_width= 4),
        )
    except Exception as e:
        #TODO print logging
        print(str(e))
Exemple #16
0
    def test_add_annotation_page_dimensions(self):
        # Ensure that changing a page's dimensions results in annotations being
        # placed in the proper locations.
        a = PdfAnnotator(files.SIMPLE)
        # Act like the PDF was rastered at 144 DPI (2x default user space)
        a.set_page_dimensions((1224, 1584), 0)
        a.add_annotation(
            'square',
            Location(x1=10, y1=20, x2=20, y2=30, page=0),
            Appearance(),
        )
        with write_to_temp(a) as t:
            annotations = load_annotations_from_pdf(t)

        square = annotations.pop()
        assert len(annotations) == 0
        assert square.Subtype == '/Square'
        # The outer bounding box of the square is padded outward by the stroke
        # width, and then scaled down by two.
        self.assertEqual(square.Rect, ['4.5', '9.5', '10.5', '15.5'])
    def _add_explicit_text_annotation(self, a):
        x1, y1, x2, y2 = 110, 310, 200, 350
        font_size = 4

        content_stream = ContentStream([
            Save(),
            BeginText(),
            FillColor(0, 0, 0),
            Font('MyFontyFont', font_size),
        ])
        content_stream.extend(
            get_text_commands(
                x1,
                y1,
                x2,
                y2,
                text=(r'Twas brilling and the slithy toves \n'
                      r'Did gyre and gimbel in the wabe \n'
                      r'All mimsy were the borogroves \n'
                      r'And the mome raths outgrabe \n'),
                font_size=font_size,
                wrap_text=True,
                align=constants.TEXT_ALIGN_LEFT,
                baseline=constants.TEXT_BASELINE_TOP,
                line_spacing=1.2,
            ))
        content_stream.extend([
            EndText(),
            Restore(),
        ])

        appearance = Appearance(
            appearance_stream=content_stream,
            fonts={'MyFontyFont': FreeText.make_font_object()},
        )
        a.add_annotation(
            'square',
            location=Location(x1=x1, y1=y1, x2=x2, y2=y2, page=0),
            appearance=appearance,
        )
Exemple #18
0
    pos_x1 = pdf_dim[i][2]
    pos_x2 = pdf_dim[i][3]
    pos_y1 = pdf_dim[i][4]
    pos_y2 = pdf_dim[i][5]
    for wall in geschoss.walls:

        x = (wall.x) / (dim_geschoss[i][0]) * (pos_x2 - pos_x1) + pos_x1
        y = (wall.y) / (dim_geschoss[i][1]) * (pos_y1 - pos_y2) + pos_y2
        x2 = (wall.x + wall.dx) / (dim_geschoss[i][0]) * (pos_x2 -
                                                          pos_x1) + pos_x1
        y2 = (wall.y + wall.dy) / (dim_geschoss[i][1]) * (pos_y1 -
                                                          pos_y2) + pos_y2
        a.add_annotation(
            "square",
            Location(x1=x, y1=y, x2=x2, y2=y2, page=0),
            Appearance(stroke_color=(0, 0, 0), stroke_width=2),
        )
    for room in geschoss.rooms:
        for obj in room.objects:

            x = (obj.x) / (dim_geschoss[i][0]) * (pos_x2 - pos_x1) + pos_x1
            y = (obj.y) / (dim_geschoss[i][1]) * (pos_y1 - pos_y2) + pos_y2
            r = 100
            color = (0, 1, 1)
            if obj.print_name in ["Steckdose"]:
                pic_file = "steckdose_{}.png".format(obj.anzahl)
            elif obj.print_name in ["Stromanschluss"]:
                pic_file = "stromanschluss.png"
                if obj.knx == KnxType.Rolladen:
                    pic_file = "rolladen.png"
            elif obj.print_name == "KNX":
Exemple #19
0
 def annotate_cols(self, cols: List[float], page: int):
     for col in cols:
         loc = Location(points=[[col, 0], [col, self.page_height]],
                        page=page)
         appearance = Appearance(stroke_color=RED, stroke_width=2)
         self.annotations.append(('line', loc, appearance))
Exemple #20
0
def annotatePDF(pathToPDF):
    try:
        randomNumber1 = str(randint(0, 9))
        randomNumber2 = str(randint(1000, 9999))

        a = PdfAnnotator(pathToPDF)
        #Name and adress
        a.add_annotation(
            'text',
            Location(x1=350, y1=590, x2=560, y2=650, page=0),
            Appearance(content=name + "\n" + adress + "\n" + city.upper(),
                       font_size=11,
                       fill=(0, 0, 0),
                       line_spacing=1.8),
        )
        #Edition date
        a.add_annotation(
            'text',
            Location(x1=393, y1=550, x2=570, y2=573, page=0),
            Appearance(content=beautifulDate,
                       font_size=9,
                       fill=(0, 0, 0),
                       line_spacing=1.65),
        )
        #Request number
        a.add_annotation(
            'text',
            Location(x1=1.37 * 72,
                     y1=8.23 * 72,
                     x2=3.58 * 72,
                     y2=8.40 * 72,
                     page=0),
            Appearance(content=date + '-' + randomNumber1 + '-' +
                       randomNumber2,
                       font_size=9,
                       fill=(0, 0, 0),
                       line_spacing=1.65),
        )
        #name and date of birth
        a.add_annotation(
            'text',
            Location(x1=0.73 * 72, y1=8 * 72, x2=2.1 * 72, y2=8.3 * 72,
                     page=0),
            Appearance(content=lastName.upper() + ' le : ' + birthDate,
                       font_size=9,
                       fill=(0, 0, 0),
                       line_spacing=1.5),
        )
        #PrelevementDateTime
        a.add_annotation(
            'text',
            Location(x1=1.32 * 72,
                     y1=7.43 * 72,
                     x2=3 * 72,
                     y2=7.7 * 72,
                     page=0),
            Appearance(content=date + ' . ' + hour,
                       font_size=9,
                       fill=(0, 0, 0),
                       line_spacing=1.1),
        )
        #ValidationDate1
        a.add_annotation(
            'text',
            Location(x1=5.34 * 72,
                     y1=1.75 * 72,
                     x2=5.85 * 72,
                     y2=1.93 * 72,
                     page=0),
            Appearance(content=date,
                       font_size=9,
                       fill=(0, 0, 0),
                       line_spacing=1.1),
        )
        #ValidationDate2
        a.add_annotation(
            'text',
            Location(x1=3.6 * 72,
                     y1=0.45 * 72,
                     x2=4.1 * 72,
                     y2=0.60 * 72,
                     page=0),
            Appearance(content=date,
                       font_size=9,
                       fill=(0, 0, 0),
                       line_spacing=1.1),
        )

        #Create a new file
        a.write(pathToPDF.replace('inputs', 'outputs'))
        return 'Done'
    except Exception as e:
        return e
Exemple #21
0
from pdfscrape import Scraped_PDF
import PyPDF2
import os
from pdf_annotate import PdfAnnotator, Appearance, Location

annotator = PdfAnnotator(os.getcwd()+'/trade_tickets/Company_Q2_p1.pdf')
annotator.add_annotation('square',Location(x1=300, y1=265, x2=500, y2=330, page=0),Appearance(stroke_color=(1, 0, 0), stroke_width=3),)
annotator.write('annotated.pdf')

class Annotate(object):
    def __init__(self, pdf_obj):
Exemple #22
0
#!/usr/bin/env vpython3
from pdf_annotate import PdfAnnotator, Location, Appearance

annotationtext = "some text"

a = PdfAnnotator("pdf.pdf")
a.add_annotation(
    "text",
    Location(x1=50, y1=50, x2=200, y2=100, page=0),
    Appearance(
        fill=(0, 0, 0),
        stroke_width=1,
        wrap_text=True,
        font_size=12,
        content=annotationtext,
    ),
)
a.write("pdf-a.pdf")
Exemple #23
0
    def process_drawing_stamps(self):
        try:
            os.mkdir(f'{self.file_path_drawing_to_stamp}/Stamped')
        except Exception as e:
            print(e)
            self.ui.listWidget_drawing_stamper.clear()
            self.ui.listWidget_drawing_stamper.addItem("Unable to create directory - error code below:\n")
            self.ui.listWidget_drawing_stamper.addItem(str(e))

        today = date.today()
        today_date = today.strftime("%d/%m/%y")

        drawing_status = ""
        if self.ui.radioButton_status_a.isChecked() == True:
            drawing_status = "A"
        elif self.ui.radioButton_status_b.isChecked() == True:
            drawing_status = "B"
        elif self.ui.radioButton_status_c.isChecked() == True:
            drawing_status = "C"
        else:
            drawing_status = "Unknown"

        self.ui.listWidget_drawing_stamper.clear()
        self.ui.listWidget_drawing_stamper.addItem("Adding annotations:\n")
        for drawing in self.list_of_drawingstostamp:
            try:
                full_drawing_path = self.file_path_drawing_to_stamp + '/' + drawing
                self.ui.listWidget_drawing_stamper.addItem(drawing)
                QtCore.QCoreApplication.processEvents()
                full_path_drawing_stamp = self.file_path_drawing_to_stamp + "/Blank_Stamp.png"
                a = PdfAnnotator(full_drawing_path)
                a.add_annotation(
                    'image',
                    Location(x1=50, y1=50, x2=400, y2=400, page=0),
                    Appearance(image=full_path_drawing_stamp)
                )
            except Exception as e:
                print("Unable to add image")

            try:
                a.add_annotation(
                    'text',
                    Location(x1=120, y1=320, x2=300, y2=332, page=0),
                    Appearance(stroke_color=(1, 1, 1), stroke_width=5, content=self.ui.lineEdit_drawing_stamper_jobnumber.text(), fill=(0.705, 0.094, 0.125, 1))
                ) #https://doc.instantreality.org/tools/color_calculator/
                a.add_annotation(
                    'text',
                    Location(x1=130, y1=305, x2=300, y2=317, page=0),
                    Appearance(stroke_color=(1, 1, 1), stroke_width=5, content=self.ui.lineEdit_drawing_stamper_date.text(), fill=(0.705, 0.094, 0.125, 1))
                )
                a.add_annotation(
                    'text',
                    Location(x1=75, y1=276, x2=300, y2=288, page=0),
                    Appearance(stroke_color=(1, 1, 1), stroke_width=5, content=self.ui.lineEdit_drawing_stamper_reviewerinitials.text(), fill=(0.705, 0.094, 0.125, 1))
                )
                a.add_annotation(
                    'text',
                    Location(x1=200, y1=276, x2=320, y2=288, page=0),
                    Appearance(stroke_color=(1, 1, 1), stroke_width=5, content=f"Status {drawing_status}", fill=(0.705, 0.094, 0.125, 1))
                )
                a.add_annotation(
                    'text',
                    Location(x1=330, y1=276, x2=400, y2=288, page=0),
                    Appearance(stroke_color=(1, 1, 1), stroke_width=5, content=today_date, fill=(0.705, 0.094, 0.125, 1))
                )

                # Put an X in the box noting the status
                if drawing_status == "A":
                    a.add_annotation(
                        'text',
                        Location(x1=117, y1=203, x2=300, y2=215, page=0),
                        Appearance(stroke_color=(1, 1, 1), stroke_width=5,
                                   content="X", fill=(0.705, 0.094, 0.125, 1))
                    )
                if drawing_status == "B":
                    a.add_annotation(
                        'text',
                        Location(x1=117, y1=189, x2=300, y2=201, page=0),
                        Appearance(stroke_color=(1, 1, 1), stroke_width=5,
                                   content="X", fill=(0.705, 0.094, 0.125, 1))
                    )
                if drawing_status == "C":
                    a.add_annotation(
                        'text',
                        Location(x1=117, y1=174, x2=300, y2=186, page=0),
                        Appearance(stroke_color=(1, 1, 1), stroke_width=5,
                                   content="X", fill=(0.705, 0.094, 0.125, 1))
                    )

            except Exception as e:
                print(e)
                self.ui.listWidget_drawing_stamper.addItem("Unable to add annotation - error code below:\n")
                self.ui.listWidget_drawing_stamper.addItem(str(e))
                self.ui.listWidget_drawing_stamper.addItem("Check - is this file a PDF?")


            try:
                #Write the resultant file
                a.write(f'{self.file_path_drawing_to_stamp}/Stamped/{drawing}')
            except Exception as e:
                print(e)
                self.ui.listWidget_drawing_stamper.addItem("Unable to save file - error code below:\n")
                self.ui.listWidget_drawing_stamper.addItem(str(e))
                self.ui.listWidget_drawing_stamper.addItem("Check - do these files already exist?")
                return

        #Display success message
        self.ui.listWidget_drawing_stamper.clear()
        self.ui.listWidget_drawing_stamper.addItem("Stamps added successfully!")

        return
    def scrape_pdf(self):
        pdfFileObject = open(os.getcwd() + "/" + self.path, 'rb')
        pdf_info = list(
            filter(
                lambda x: any(c.isalnum() for c in x),
                PyPDF2.PdfFileReader(pdfFileObject).getPage(
                    0).extractText().split('\n')))
        for i, x in enumerate(pdf_info):
            pdf_info[i] = x.strip()

        annotator = PdfAnnotator(os.getcwd() + self.path)
        annotated = False

        self.company_name = pdf_info[1]

        if pdf_info.index('Trans Type') == pdf_info.index('Quantity') - 2:
            self.transaction_type = pdf_info[pdf_info.index('Trans Type') + 1]
        else:
            self.transaction_type = None
            annotator.add_annotation(
                'square',
                Location(x1=80, y1=435, x2=140, y2=490, page=0),
                Appearance(stroke_color=(1, 0, 0), stroke_width=3),
            )
            annotated = True

        if pdf_info.index('Quantity') == pdf_info.index('PPS') - 2:
            self.quantity = int(pdf_info[pdf_info.index('Quantity') +
                                         1].replace(',', ''))
        else:
            self.quantity = None
            annotator.add_annotation(
                'square',
                Location(x1=160, y1=435, x2=220, y2=490, page=0),
                Appearance(stroke_color=(1, 0, 0), stroke_width=3),
            )
            annotated = True

        if pdf_info.index('PPS') == pdf_info.index('Security') - 2:
            self.price_per_share = int(
                pdf_info[pdf_info.index('PPS') +
                         1][1:len(pdf_info[pdf_info.index('PPS') + 1]) - 3])
        else:
            self.price_per_share = None
            annotator.add_annotation(
                'square',
                Location(x1=225, y1=435, x2=285, y2=490, page=0),
                Appearance(stroke_color=(1, 0, 0), stroke_width=3),
            )
            annotated = True

        if len(pdf_info[3]) > 14:
            self.date_of_order = pdf_info[3][15:]
        else:
            print("date of order missing")
            self.date_of_order = None
            annotator.add_annotation(
                'square',
                Location(x1=150, y1=570, x2=280, y2=590, page=0),
                Appearance(stroke_color=(1, 0, 0), stroke_width=3),
            )
            annotated = True

        if len(pdf_info[4]) > 10:
            self.custodian = pdf_info[4][11:]
        else:
            self.custodian = None
            annotator.add_annotation(
                'square',
                Location(x1=130, y1=540, x2=280, y2=565, page=0),
                Appearance(stroke_color=(1, 0, 0), stroke_width=3),
            )
            annotated = True

        if pdf_info.index('Security') == pdf_info.index('Type of Order') - 2:
            self.security = pdf_info[pdf_info.index('Security') + 1]
        else:
            self.security = None
            annotator.add_annotation(
                'square',
                Location(x1=295, y1=435, x2=360, y2=490, page=0),
                Appearance(stroke_color=(1, 0, 0), stroke_width=3),
            )
            annotated = True

        if pdf_info.index(
                'Type of Order') == pdf_info.index('Instructions') - 2:
            self.type = pdf_info[pdf_info.index('Type of Order') + 1]
        else:
            self.type = None
            annotator.add_annotation(
                'square',
                Location(x1=360, y1=435, x2=460, y2=490, page=0),
                Appearance(stroke_color=(1, 0, 0), stroke_width=3),
            )
            annotated = True

        if pdf_info.index('Broker/Dealer') == pdf_info.index(
                'Broker/Dealer Representative') - 2:
            self.broker_dealer = pdf_info[pdf_info.index('Broker/Dealer') + 1]
        else:
            self.broker_dealer = None
            annotator.add_annotation(
                'square',
                Location(x1=70, y1=330, x2=285, y2=400, page=0),
                Appearance(stroke_color=(1, 0, 0), stroke_width=3),
            )
            annotated = True

        if pdf_info.index('Broker/Dealer Representative'
                          ) == pdf_info.index('Comments:') - 2:
            self.broker_dealer_representative = pdf_info[
                pdf_info.index('Broker/Dealer Representative') + 1]
        else:
            self.broker_dealer_representative = None
            annotator.add_annotation(
                'square',
                Location(x1=300, y1=330, x2=500, y2=400, page=0),
                Appearance(stroke_color=(1, 0, 0), stroke_width=3),
            )
            annotated = True

        if pdf_info.index('Phone:') == pdf_info.index('Signature:') - 3:
            self.phone = pdf_info[pdf_info.index('Phone:') +
                                  1] + "-" + pdf_info[pdf_info.index('Phone:')
                                                      + 2]
        else:
            self.phone = None
            annotator.add_annotation(
                'square',
                Location(x1=300, y1=265, x2=500, y2=330, page=0),
                Appearance(stroke_color=(1, 0, 0), stroke_width=3),
            )
            annotated = True

        try:
            self.amount = self.quantity * self.price_per_share
        except:
            self.amount = None

        if annotated:
            # os.mkdir(os.getcwd() + "/ANNOTATED/trade_tickets")
            annotator.write(os.getcwd() + "/ANNOTATED" + self.path)
            # else maybe move it to the completed folder

        self.valid_pdf = self.amount != None and self.transaction_type != None and self.quantity != None
        pdfFileObject.close()
Exemple #25
0
def generate_timesheet(form):
    # Setting default strings
    sunday_in = ''
    monday_in = ''
    tuesday_in = ''
    wednesday_in = ''
    thursday_in = ''
    friday_in = ''
    saturday_in = ''
    sunday_out = ''
    monday_out = ''
    tuesday_out = ''
    wednesday_out = ''
    thursday_out = ''
    friday_out = ''
    saturday_out = ''
    sunday_hours = ''
    monday_hours = ''
    tuesday_hours = ''
    wednesday_hours = ''
    thursday_hours = ''
    friday_hours = ''
    saturday_hours = ''
    fund = ''

    def calc_hours_worked(time_in, time_out):
        hours = datetime.datetime.combine(
            datetime.date.today(), time_out.data) - datetime.datetime.combine(
                datetime.date.today(), time_in.data)
        return round(hours.seconds / 3600, 2)

    def next_saturday(d):
        if d.weekday() == 5:
            return d
        else:
            days_ahead = 5 - d.weekday()
            if days_ahead < 0:
                days_ahead += 7
            return d + datetime.timedelta(days_ahead)

    def previous_sunday(d):
        if d.weekday() == 6:
            return d
        else:
            days_behind = -d.weekday() - 1
            return d + datetime.timedelta(days_behind)

    name = form['name'].data
    mcgill_id = form['mcgill_id'].data
    hourly_rate = round(float(form['hourly_rate'].data), 2)
    if form['fund_number'].data is not None:
        fund = form['fund_number'].data

    week = datetime.date(int(form['week_of_year'].data),
                         int(form['week_of_month'].data),
                         int(form['week_of_day'].data))
    # find the closest past sunday
    week_start = previous_sunday(week)
    # find the closest future saturday
    week_end = next_saturday(week)

    total_hours = 0
    if form['sunday_in'].data is not None and form[
            'sunday_out'].data is not None:
        sunday_in = form['sunday_in'].data.strftime('%H:%M')
        sunday_out = form['sunday_out'].data.strftime('%H:%M')
        sunday_hours = calc_hours_worked(form['sunday_in'], form['sunday_out'])
        total_hours += sunday_hours
    if form['monday_in'].data is not None and form[
            'monday_out'].data is not None:
        monday_in = form['monday_in'].data.strftime('%H:%M')
        monday_out = form['monday_out'].data.strftime('%H:%M')
        monday_hours = calc_hours_worked(form['monday_in'], form['monday_out'])
        total_hours += monday_hours
    if form['tuesday_in'].data is not None and form[
            'tuesday_out'].data is not None:
        tuesday_in = form['tuesday_in'].data.strftime('%H:%M')
        tuesday_out = form['tuesday_out'].data.strftime('%H:%M')
        tuesday_hours = calc_hours_worked(form['tuesday_in'],
                                          form['tuesday_out'])
        total_hours += tuesday_hours
    if form['wednesday_in'].data is not None and form[
            'wednesday_out'].data is not None:
        wednesday_in = form['wednesday_in'].data.strftime('%H:%M')
        wednesday_out = form['wednesday_out'].data.strftime('%H:%M')
        wednesday_hours = calc_hours_worked(form['wednesday_in'],
                                            form['wednesday_out'])
        total_hours += wednesday_hours
    if form['thursday_in'].data is not None and form[
            'thursday_out'].data is not None:
        thursday_in = form['thursday_in'].data.strftime('%H:%M')
        thursday_out = form['thursday_out'].data.strftime('%H:%M')
        thursday_hours = calc_hours_worked(form['thursday_in'],
                                           form['thursday_out'])
        total_hours += thursday_hours
    if form['friday_in'].data is not None and form[
            'friday_out'].data is not None:
        friday_in = form['friday_in'].data.strftime('%H:%M')
        friday_out = form['friday_out'].data.strftime('%H:%M')
        friday_hours = calc_hours_worked(form['friday_in'], form['friday_out'])
        total_hours += friday_hours
    if form['saturday_in'].data is not None and form[
            'saturday_out'].data is not None:
        saturday_in = form['saturday_in'].data.strftime('%H:%M')
        saturday_out = form['saturday_out'].data.strftime('%H:%M')
        saturday_hours = calc_hours_worked(form['saturday_in'],
                                           form['saturday_out'])
        total_hours += saturday_hours

    total_money = round(total_hours * hourly_rate, 2)

    if form['timesheet_template'].data == '1':
        base_timesheet = 'academic_casual_timesheet_-_2017_0.pdf'
        annotations = constants.annotations_academic_casual_timesheet
        personal_data = constants.personal_data_academic_casual_timesheet
    else:
        base_timesheet = 'admin_support_staff_casual_employee_timesheet_-_2017.pdf'
        annotations = constants.annotations_admin_support_staff_casual_employee_timesheet
        personal_data = constants.personal_data_admin_support_staff_casual_employee_timesheet

    pdf_out_dir = 'pdf/'
    out_file = form['name'].data + ' ' + week_start.strftime(
        '%d %b %Y') + '.pdf'
    # out_file = ''.join([random.choice(string.ascii_letters + string.digits) for n in range(32)]) + '.pdf'
    out_path = pdf_out_dir + out_file

    department = 'Building 21'
    signature_date = datetime.date.today()

    timesheet = PdfAnnotator(base_timesheet)

    for annotation in annotations:
        x1 = annotation[1]
        y1 = annotation[2]
        x2 = x1 + annotation[3]
        y2 = y1 + annotation[4]
        timesheet.add_annotation(
            'text',
            Location(x1=x1, y1=y1, x2=x2, y2=y2, page=0),
            Appearance(content=str(eval(annotation[0])),
                       fill=(0, 0, 0),
                       text_baseline='bottom'),
        )

    for annotation in personal_data:
        x1 = annotation[1]
        y1 = annotation[2]
        x2 = x1 + annotation[3]
        y2 = y1 + annotation[4]
        timesheet.add_annotation(
            'text',
            Location(x1=x1, y1=y1, x2=x2, y2=y2, page=0),
            Appearance(content=str(eval(annotation[0])),
                       fill=(0, 0, 0),
                       text_baseline='middle',
                       text_align='center'),
        )

    timesheet.write('static/' + out_path)

    return out_path
Exemple #26
0
    def draw_rectangles_for_solution(self, f_in, f_out, solution, points):
        """Drawing green filled rectangles near the correct answers for every problem,
        in order to indicate the correct solution.
        It calculates and writes the total score achieved too.
        
        Parameters:
            f_in (str): Path to the input PDF file.
            f_out (str): Path to the output PDF file.
            solution (dict): The solution (correct answers) corresponding to the input PDF file (f_in).
            points (float): Total points achieved.
        """
        pr = PdfFileReader(f_in)
        dest = pr.getNamedDestinations()
        fields = pr.getFields()

        # """IT IS NOT WORKING IF THIS COMES FIRST:"""
        #         a = PdfAnnotator(f_in)
        #         for p in range(pr.getNumPages()):
        #             for dk, dv in dest.items():
        #                 if pr.getDestinationPageNumber(dv) == p and dk.startswith('ht_'):
        #                     inds = [int(ind) for ind in dk[3:].split(':')]
        # #                     if inds[2] in solution[inds[1]][1]:
        #                     if inds[4] in solution[inds[1]][1]:
        #                         # using some hard-coded values:
        #                         a.add_annotation('square',
        #                                          Location(x1=float(dv['/Left']), y1=float(dv['/Top']), x2=float(dv['/Left'])+5, y2=float(dv['/Top'])+5, page=p),
        #                                          Appearance(stroke_color=(0, 1, 0), stroke_width=5),)
        #         a.write(f_out)

        pw = PdfFileWriter()
        #         pr = PdfFileReader(f_out, strict=False)
        pr = PdfFileReader(f_in, strict=False)
        pw.appendPagesFromReader(pr)
        pw._root_object.update(
            {NameObject("/AcroForm"): pr.trailer["/Root"]["/AcroForm"]})
        pw._root_object["/AcroForm"].update(
            {NameObject("/NeedAppearances"): BooleanObject(True)})
        for p in range(pr.getNumPages()):
            self._update_page_form_checkbox_values(pw.getPage(p), {
                fk: fv['/V']
                for fk, fv in fields.items() if '/V' in fv.keys()
            })  # sometimes '/V' disappears from the keys
        self._update_page_form_checkbox_values(pw.getPage(0),
                                               {'points': str(points)})
        f = codecs.open(f_out, 'wb')
        pw.write(f)
        f.close()

        a = PdfAnnotator(f_out)
        for p in range(pr.getNumPages()):
            for dk, dv in dest.items():
                if pr.getDestinationPageNumber(dv) == p and dk.startswith(
                        'ht_'):
                    inds = [int(ind) for ind in dk[3:].split(':')]
                    #                     if inds[2] in solution[inds[1]][1]:
                    if inds[4] in solution[inds[1]][1]:
                        # using some hard-coded values:
                        a.add_annotation(
                            'square',
                            Location(x1=float(dv['/Left']),
                                     y1=float(dv['/Top']),
                                     x2=float(dv['/Left']) + 5,
                                     y2=float(dv['/Top']) + 5,
                                     page=p),
                            Appearance(stroke_color=(0, 1, 0), stroke_width=5),
                        )
        a.write(f_out)
Exemple #27
0
def create_annotation(node: PdfAnnotator, is_name: bool, count: int, value):
    coordinate_dict_name = {
        '1': {
            'x1': 95,
            'y1': 720,
            'x2': 160,
            'y2': 740
        },
        '2': {
            'x1': 335,
            'y1': 720,
            'x2': 405,
            'y2': 740
        },
        '3': {
            'x1': 95,
            'y1': 690,
            'x2': 160,
            'y2': 710
        },
        '4': {
            'x1': 335,
            'y1': 690,
            'x2': 405,
            'y2': 710
        }
    }
    coordinate_dict_id = {
        '1': {
            'x1': 215,
            'y1': 720,
            'x2': 295,
            'y2': 740
        },
        '2': {
            'x1': 465,
            'y1': 720,
            'x2': 550,
            'y2': 740
        },
        '3': {
            'x1': 215,
            'y1': 690,
            'x2': 295,
            'y2': 710
        },
        '4': {
            'x1': 465,
            'y1': 690,
            'x2': 550,
            'y2': 710
        }
    }

    if is_name:
        return node.add_annotation(
            'text',
            Location(x1=coordinate_dict_name[str(count)]['x1'],
                     y1=coordinate_dict_name[str(count)]['y1'],
                     x2=coordinate_dict_name[str(count)]['x2'],
                     y2=coordinate_dict_name[str(count)]['y2'],
                     page=0),
            Appearance(stroke_color=(0, 0, 0),
                       stroke_width=5,
                       content=value,
                       fill=(0, 0, 0, 1)))
    else:
        return node.add_annotation(
            'text',
            Location(x1=coordinate_dict_id[str(count)]['x1'],
                     y1=coordinate_dict_id[str(count)]['y1'],
                     x2=coordinate_dict_id[str(count)]['x2'],
                     y2=coordinate_dict_id[str(count)]['y2'],
                     page=0),
            Appearance(stroke_color=(0, 0, 0),
                       stroke_width=5,
                       content=value,
                       fill=(0, 0, 0, 1)))
class EndToEndMixin(object):
    """End to end test of PdfAnnotator.

    To truly test PDF annotations end to end, you need to do some sort of
    visual inspection. There are several options, including rastering the PDF
    and doing pixel diffs. Until we end up doing something like this, the end-
    to-end test will be a tiny amount of validation in code + manual inspection
    of the output.
    """
    EXPECTED_ANNOTATIONS = 36

    def setUp(self):
        self.gaudy = Appearance(
            stroke_color=[1, 0, 0],
            stroke_width=3,
            fill=[0, 1, 0],
            content='Latin',
            font_size=12,
            wrap_text=True,
        )

        self.transparent = self.gaudy.copy(
            fill=[0, 0, 1, 0.5],
            stroke_color=[1, 0, 0, 0.25],
        )

        self.top_left = self.gaudy.copy(
            fill=[0, 0.5, 0.75],
            content=(r"Though yet of Hamlet, our dear brother's death \\ "
                     r"The memory be green"),
            font_size=6,
            text_align='left',
            text_baseline='top',
        )
        self.top_center = self.top_left.copy(text_align='center')
        self.top_right = self.top_left.copy(text_align='right')

        self.middle_left = self.top_left.copy(text_baseline='middle')
        self.middle_center = self.middle_left.copy(text_align='center')
        self.middle_right = self.middle_left.copy(text_align='right')

        self.bottom_left = self.top_left.copy(text_baseline='bottom')
        self.bottom_center = self.bottom_left.copy(text_align='center')
        # One text annotation is transparent grey
        self.bottom_right = self.bottom_left.copy(
            text_align='right',
            fill=[0, 0, 0, 0.25],
        )

        self.texts = [
            self.top_left,
            self.top_center,
            self.top_right,
            self.middle_left,
            self.middle_center,
            self.middle_right,
            self.bottom_left,
            self.bottom_center,
            self.bottom_right,
        ]

        self.image_appearance = Appearance(stroke_width=0)
        self.transparent_image_appearance = self.image_appearance.copy(
            fill_transparency=0.5,
            stroke_transparency=0.5,
        )

    def test_end_to_end(self):
        a = PdfAnnotator(self.INPUT_FILENAME)
        self._add_annotations(a)
        output_file = self._get_output_file()
        a.write(output_file)
        # self._check_num_annotations(output_file)

    def _check_num_annotations(self, output_file):
        f = pdfrw.PdfReader(output_file)
        assert len(f.pages[0].Annots) == self.EXPECTED_ANNOTATIONS

    def _get_output_file(self):
        dirname, _ = os.path.split(os.path.abspath(__file__))
        return os.path.join(dirname, 'pdfs', self.OUTPUT_FILENAME)

    def _add_annotations(self, a):
        # Original page size (612, 792)
        self._add_shape_annotations(a, self.gaudy)
        self._add_shape_annotations(a, self.transparent, y1=70, y2=110)
        self._add_image_annotations(a, self.image_appearance)
        self._add_image_annotations(
            a,
            self.transparent_image_appearance,
            y1=170,
            y2=210,
        )
        self._add_text_annotations(a)
        self._add_explicit_image_annotation(a)
        self._add_explicit_graphics_state_annotation(a)
        self._add_explicit_text_annotation(a)
        self._add_rounded_rectangles(a)

    def _add_shape_annotations(self, a, appearance, y1=20, y2=60):
        a.add_annotation(
            'square',
            Location(x1=10, y1=y1, x2=50, y2=y2, page=0),
            appearance,
        )
        a.add_annotation(
            'circle',
            Location(x1=60, y1=y1, x2=100, y2=y2, page=0),
            appearance,
        )
        a.add_annotation(
            'polygon',
            Location(points=[[110, y1], [150, y1], [130, y2]], page=0),
            appearance,
        )
        a.add_annotation(
            'polyline',
            Location(points=[[160, y1], [200, y1], [180, y2]], page=0),
            appearance,
        )
        a.add_annotation(
            'line',
            Location(points=[[210, y1], [250, y2]], page=0),
            appearance,
        )
        a.add_annotation(
            'ink',
            Location(points=[[260, y1], [300, y2]], page=0),
            appearance,
        )

        round = appearance.copy(line_cap=constants.LINE_CAP_ROUND)
        a.add_annotation(
            'line',
            location=Location(points=[[310, y1], [350, y2]], page=0),
            appearance=round,
        )

        dashed = appearance.copy(dash_array=[[3], 0])
        a.add_annotation(
            'line',
            location=Location(points=[[360, y1], [400, y2]], page=0),
            appearance=dashed,
        )

    def _add_image_annotations(self, a, appearance, y1=120, y2=160):
        # Draw a row of image annotations for each type of image, with a label
        # on top of the image type
        x = 10
        text_appearance = Appearance(
            font_size=5,
            text_baseline=constants.TEXT_BASELINE_BOTTOM,
            fill=[0, 0, 0])
        a.add_annotation(
            'text',
            Location(x1=x, y1=y2, x2=(x + 20), y2=(y2 + 10), page=0),
            text_appearance.copy(content='PNG'),
        )
        for png_file in PNG_FILES[:-1]:
            a.add_annotation(
                'image',
                Location(x1=x, y1=y1, x2=(x + 40), y2=y2, page=0),
                appearance.copy(image=png_file),
            )
            x += 50
        # The last PNG file has transparency, so let's draw a rectangle behind
        # so you can see that it's transparent.
        a.add_annotation(
            'square',
            Location(x1=x, y1=y1, x2=(x + 40), y2=y2, page=0),
            self.gaudy.copy(stroke_width=0),
        )
        a.add_annotation(
            'image',
            Location(x1=x, y1=y1, x2=(x + 40), y2=y2, page=0),
            appearance.copy(image=PNG_FILES[-1]),
        )
        x += 50

        a.add_annotation(
            'text',
            Location(x1=x, y1=y2, x2=(x + 20), y2=(y2 + 10), page=0),
            text_appearance.copy(content='JPEG'),
        )
        for jpeg_file in JPEG_FILES:
            a.add_annotation(
                'image',
                Location(x1=x, y1=y1, x2=(x + 40), y2=y2, page=0),
                appearance.copy(image=jpeg_file),
            )
            x += 50

        a.add_annotation(
            'text',
            Location(x1=x, y1=y2, x2=(x + 20), y2=(y2 + 10), page=0),
            text_appearance.copy(content='GIF'),
        )
        for gif_file in GIF_FILES:
            a.add_annotation(
                'image',
                Location(x1=x, y1=y1, x2=(x + 40), y2=y2, page=0),
                appearance.copy(image=gif_file),
            )
            x += 50

    def _add_text_annotations(self, a, y1=220, y2=300):
        xs = [10 + (i * 50) for i in range(len(self.texts))]
        for x, appearance in zip(xs, self.texts):
            a.add_annotation(
                'text',
                Location(x1=x, y1=y1, x2=(x + 40), y2=y2, page=0),
                appearance,
            )

    def _add_rounded_rectangles(self, a):
        """Add a few rounded rectangles with different border radii."""
        y1, y2 = 360, 410
        xs = [10, 60, 110]
        rxs = [5, 10, 15]
        rys = [5, 5, 15]
        for x1, rx, ry in zip(xs, rxs, rys):
            x2 = x1 + 40
            location = Location(x1=x1, y1=y1, x2=x2, y2=y2, page=0)
            content_stream = ContentStream([
                Save(),
                StrokeColor(1, 0, 0),
                FillColor(0, 1, 0),
            ])
            add_rounded_rectangle(
                stream=content_stream,
                x=x1,
                y=y1,
                width=(x2 - x1),
                height=(y2 - y1),
                rx=rx,
                ry=ry,
            )
            content_stream.extend([
                StrokeAndFill(),
                Restore(),
            ])
            appearance = Appearance(appearance_stream=content_stream, )
            a.add_annotation('square', location, appearance)

    def _add_explicit_image_annotation(self, a):
        """Add an image annotation using ContentStream commands instead of the
        Image type's commands. This is testing that the external XObjects API
        works, and that images can be embedded inside other, more complex
        annotations.
        """
        x1, y1, x2, y2 = 10, 310, 50, 350
        location = Location(x1=x1, y1=y1, x2=x2, y2=y2, page=0)

        content_stream = ContentStream([
            StrokeColor(1, 0, 0),
            Rect(x1, y1, x2 - x1, y2 - y1),
            Save(),
            # The image is inside an outer rectangle
            CTM(Image.get_ctm(x1 + 10, y1 + 10, x2 - 10, y2 - 10)),
            XObject('MyXObject'),
            Restore(),
            Stroke(),
        ])
        appearance = Appearance(
            appearance_stream=content_stream,
            xobjects={
                'MyXObject': Image.make_image_xobject(PNG_FILES[0]),
            },
        )

        a.add_annotation(
            'square',
            location=location,
            appearance=appearance,
        )

    def _add_explicit_graphics_state_annotation(self, a):
        graphics_states = {
            'BevelSquare':
            GraphicsState(
                line_join=constants.LINE_JOIN_BEVEL,
                line_cap=constants.LINE_CAP_SQUARE,
                stroke_transparency=0.75,
            ),
            'MiterButt':
            GraphicsState(
                line_join=constants.LINE_JOIN_MITER,
                line_cap=constants.LINE_CAP_BUTT,
                stroke_transparency=0.5,
            ),
            'RoundRound':
            GraphicsState(
                line_join=constants.LINE_JOIN_ROUND,
                line_cap=constants.LINE_CAP_ROUND,
                stroke_transparency=0.25,
            ),
        }

        # Defines the bounding box of the chevrons
        x1, y1, x2, y2 = 60, 310, 100, 350
        lines_location = Location(x1=x1, y1=y1, x2=x2, y2=y2, page=0)

        # Defines the start/end of the chevrons
        x1, midpoint, x2 = 65, 80, 95
        y1 = 315

        content_stream = ContentStream([
            Save(),
            StrokeWidth(5),
            CSGraphicsState('BevelSquare'),
            Move(x1, y1),
            Line(midpoint, y1 + 10),
            Line(x2, y1),
            Stroke(),
            CSGraphicsState('MiterButt'),
            Move(x1, y1 + 10),
            Line(midpoint, y1 + 20),
            Line(x2, y1 + 10),
            Stroke(),
            CSGraphicsState('RoundRound'),
            Move(x1, y1 + 20),
            Line(midpoint, y1 + 30),
            Line(x2, y1 + 20),
            Stroke(),
            Restore(),
        ])
        appearance = Appearance(
            appearance_stream=content_stream,
            graphics_states=graphics_states,
        )
        a.add_annotation(
            'square',
            location=lines_location,
            appearance=appearance,
        )

    def _add_explicit_text_annotation(self, a):
        x1, y1, x2, y2 = 110, 310, 200, 350
        font_size = 4

        content_stream = ContentStream([
            Save(),
            BeginText(),
            FillColor(0, 0, 0),
            Font('MyFontyFont', font_size),
        ])
        content_stream.extend(
            get_text_commands(
                x1,
                y1,
                x2,
                y2,
                text=(r'Twas brilling and the slithy toves \n'
                      r'Did gyre and gimbel in the wabe \n'
                      r'All mimsy were the borogroves \n'
                      r'And the mome raths outgrabe \n'),
                font_size=font_size,
                wrap_text=True,
                align=constants.TEXT_ALIGN_LEFT,
                baseline=constants.TEXT_BASELINE_TOP,
                line_spacing=1.2,
            ))
        content_stream.extend([
            EndText(),
            Restore(),
        ])

        appearance = Appearance(
            appearance_stream=content_stream,
            fonts={'MyFontyFont': FreeText.make_font_object()},
        )
        a.add_annotation(
            'square',
            location=Location(x1=x1, y1=y1, x2=x2, y2=y2, page=0),
            appearance=appearance,
        )