Exemple #1
0
    def test_invert_rotation(self):
        assert rotate(-45) == matrix_inverse(rotate(45))
        assert rotate(90) == matrix_inverse(rotate(-90))

        assert identity() == matrix_multiply(rotate(45), rotate(-45))
        assert identity() == matrix_multiply(rotate(-45), rotate(45))

        assert identity() == matrix_multiply(rotate(90), rotate(-90))
        assert identity() == matrix_multiply(rotate(-90), rotate(90))
Exemple #2
0
    def imagevisual(self, image_path, no, udct, nsig, page):
        x1, y1, x2, y2 = udct.get(b'signaturebox', (0, 0, 0, 0))
        annotation = Image(
            Location(x1=x1, y1=y1, x2=x2, y2=y2, page=0),
            Appearance(image=image_path),
        )

        pdfa = annotation.as_pdf_object(identity(), page=None)
        pdfar = b'[%d %d %d %d]' % tuple(pdfa.Rect)
        pdfao = pdfa.AP.N
        visual, nav = self.makeannotation(pdfao, no + 4)
        obj = [
            self.makeobj(
                no + 3, b'''
/Type
/Annot
/Subtype %s
/Rect %s
/AP <</N %d 0 R>>
/F 4
/P %d 0 R
/FT
/Sig
%s
/T(Signature%d)
/V %d 0 R
''' % (b'/Widget' if udct.get(b'sigbutton', False) else b'/Square',
        pdfar, no + 4, page, b'/SM(TabletPOSinline)' if udct.get(
           b'sigbutton', False) else b'', nsig, nav + 1)),
            visual,
        ]
        return b''.join(obj), nav
Exemple #3
0
 def test_identity(self):
     t = PdfAnnotator._get_transform(
         bounding_box=[0, 0, 100, 200],
         rotation=0,
         _scale=(1, 1),
     )
     assert t == identity()
Exemple #4
0
 def test_as_pdf_object(self):
     x1, y1, x2, y2 = 10, 20, 100, 200
     image = Image(
         location=Location(x1=x1, y1=y1, x2=x2, y2=y2, page=0),
         appearance=Appearance(stroke_width=0, image=PNG_FILES[0]),
     )
     obj = image.as_pdf_object(identity(), page=None)
     # Appearance stream should place the Image correctly
     assert obj.AP.N.stream == (
         'q 0 0 0 RG 0 w 10 20 90 180 re 90 0 0 180 10 20 cm /Image Do Q')
     assert obj.Rect == [x1, y1, x2, y2]
     assert obj.AP.N.BBox == [x1, y1, x2, y2]
     assert obj.AP.N.Matrix == translate(-x1, -y1)
Exemple #5
0
    def textvisual(self, no, udct, nsig, page):
        annotation = udct.get(b'signature', b'').decode('utf8')
        x1, y1, x2, y2 = udct.get(b'signaturebox', (0, 0, 0, 0))
        annotation = FreeText(
            Location(x1=x1, y1=y1, x2=x2, y2=y2, page=0),
            Appearance(
                fill=[0, 0, 0],
                stroke_width=1,
                wrap_text=True,
                font_size=udct.get(b'fontsize', 12),
                content=annotation,
            ),
        )
        pdfa = annotation.as_pdf_object(identity(), page=None)
        pdfar = b'[%d %d %d %d]' % tuple(pdfa.Rect)
        pdfao = pdfa.AP.N
        visual, nav = self.makeannotation(pdfao, no+4)
        obj = [
            self.makeobj(no + 3,
                         b'''
/Type
/Annot
/Subtype
%s
/AP <</N %d 0 R>>
/BS <</S /S /Type /Border /W 0>>
/C []
/Contents (%s)
/DA (0 0 0 rg /%s 12 Tf)
/Rect %s
/F 704
/P %d 0 R
/FT
/Sig
%s
/T(Signature%d)
/V %d 0 R
''' % (
                             b'/Widget' if udct.get(b'sigbutton', False) else b'/FreeText',
                             no + 4, pdfa.Contents.encode('latin1'),
                             pdfa.AP.N.Resources.Font.keys()[0].encode('latin1'),
                             pdfar,
                             page,
                             b'/SM(TabletPOSinline)' if udct.get(b'sigbutton', False) else b'',
                             nsig, nav + 1)),

            visual
        ]
        return b''.join(obj), nav
 def test_pdf_object_backslash_escapes(self):
     x1, y1, x2, y2 = 10, 20, 100, 200
     annotation = FreeText(
         Location(x1=x1, y1=y1, x2=x2, y2=y2, page=0),
         Appearance(
             fill=[0.4, 0, 0],
             stroke_width=1,
             font_size=5,
             content='\\A \\\\B C',
         ),
     )
     obj = annotation.as_pdf_object(identity(), page=None)
     assert obj.AP.N.stream == (
         'q BT 0.4 0 0 rg /{} 5 Tf '
         '1 0 0 1 11 109 Tm (\\\\A \\\\\\\\B C) Tj ET Q'
     ).format(PDF_ANNOTATOR_FONT)
Exemple #7
0
 def test_pdf_object(self):
     x1, y1, x2, y2 = 10, 20, 100, 200
     annotation = FreeText(
         Location(x1=x1, y1=y1, x2=x2, y2=y2, page=0),
         Appearance(
             fill=[0.4, 0, 0],
             stroke_width=1,
             font_size=5,
             content='Hi',
         ),
     )
     obj = annotation.as_pdf_object(identity(), page=None)
     assert obj.AP.N.stream == (
         'q BT 0.4 0 0 rg /{} 5 Tf '
         '1 0 0 1 11 109 Tm (Hi) Tj ET Q').format(PDF_ANNOTATOR_FONT)
     assert obj.DA == '0.4 0 0 rg /{} 5 Tf'.format(PDF_ANNOTATOR_FONT)
     assert obj.Rect == [x1, y1, x2, y2]
     assert obj.AP.N.BBox == [x1, y1, x2, y2]
     assert obj.AP.N.Matrix == translate(-x1, -y1)
Exemple #8
0
    def _get_transform(bounding_box, rotation, _scale):
        """Get the transformation required to go from the user's desired
        coordinate space to PDF user space, taking into account rotation,
        scaling, translation (for things like weird media boxes).
        """
        # Unrotated width and height, in pts
        W = bounding_box[2] - bounding_box[0]
        H = bounding_box[3] - bounding_box[1]

        scale_matrix = scale(*_scale)

        x_translate = 0 + min(bounding_box[0], bounding_box[2])
        y_translate = 0 + min(bounding_box[1], bounding_box[3])
        mb_translate = translate(x_translate, y_translate)

        # Because of how rotation works the point isn't rotated around an axis,
        # but the axis itself shifts. So we have to represent the rotation as
        # rotation + translation.
        rotation_matrix = rotate(rotation)

        translate_matrix = identity()
        if rotation == 90:
            translate_matrix = translate(W, 0)
        elif rotation == 180:
            translate_matrix = translate(W, H)
        elif rotation == 270:
            translate_matrix = translate(0, H)

        # Order matters here - the transformation matrices are applied in
        # reverse order. So first we scale to get the points in PDF user space,
        # since all other operations are in that space. Then we rotate and
        # scale to capture page rotation, then finally we translate to account
        # for offset media boxes.
        transform = matrix_multiply(
            mb_translate,
            translate_matrix,
            rotation_matrix,
            scale_matrix,
        )
        return transform
Exemple #9
0
    def makepdf(self, pdfdata1, udct, zeros):
        parser = PDFParser(BytesIO(pdfdata1))
        document = PDFDocument(parser, fallback=False)

        prev = document.find_xref(parser)
        info = document.xrefs[0].trailer['Info'].objid
        root = document.xrefs[0].trailer['Root'].objid
        size = 1
        # calculate last object id, size is only xref size but not count of object in xref
        for ref in document.xrefs:
            if isinstance(ref, PDFXRefStream):
                no = max(ref.ranges, key=operator.itemgetter(1))[1]
            else:
                if len(ref.offsets) == 0:
                    no = 0
                else:
                    no = max(ref.offsets.keys())
            size = max(size, no)
        page = document.getobj(
            document.catalog['Pages'].objid)['Kids'][0].objid

        nsig, fields = self.getfields(root, document)
        annots = self.getannots(page, document)

        infodata = self.getdata(pdfdata1, info, prev, document)
        rootdata = self.getdata(pdfdata1, root, prev, document, ('AcroForm', ))
        pagedata = self.getdata(pdfdata1, page, prev, document, ('Annots', ))

        annotation = udct.get(b'signature', b'').decode('utf8')
        x1, y1, x2, y2 = udct.get(b'signaturebox', (0, 0, 0, 0))
        annotation = FreeText(
            Location(x1=x1, y1=y1, x2=x2, y2=y2, page=0),
            Appearance(
                fill=[0, 0, 0],
                stroke_width=1,
                wrap_text=True,
                font_size=12,
                content=annotation,
            ),
        )
        pdfa = annotation.as_pdf_object(identity(), page=None)
        pdfar = b'[%d %d %d %d]' % tuple(pdfa.Rect)
        pdfas = pdfa.AP.N.stream.encode('latin1')

        no = size + 1
        objs = [
            self.makeobj(page,
                         (b'/Annots[%s%d 0 R]' % (annots, no + 3) + pagedata)),
            self.makeobj(no + 0, infodata),
            self.makeobj(no + 1, (b'/AcroForm %d 0 R' % (no + 2)) + rootdata),
            self.makeobj(
                no + 2, b'/Fields[%s%d 0 R]/SigFlags %d' %
                (fields, no + 3, udct[b'sigflags'])),
            self.makeobj(
                no + 3, b'''
/Type
/Annot
/Subtype
/FreeText
/AP <</N %d 0 R>>
/BS <</S /S /Type /Border /W 0>>
/C []
/Contents (%s)
/DA (0 0 0 rg /%s 12 Tf)
/Rect %s
/F 704
/P %d 0 R
/FT
/Sig
/T(Signature%d)
/V %d 0 R
''' % (no + 4, pdfa.Contents.encode('latin1'),
        pdfa.AP.N.Resources.Font.keys()[0].encode('latin1'), pdfar, page, nsig,
        no + 5)),
            self.makeobj(
                no + 4, b'''
/BBox %s
/FormType 1
/Length %d
/Matrix [1 0 0 1 0 0]
/Resources <</Font <<%s <</BaseFont /Helvetica /Encoding /WinAnsiEncoding /Subtype /Type1 /Type /Font>>>> /ProcSet /PDF>>
/Subtype
/Form
/Type
/XObject
''' % (
                    pdfar,
                    len(pdfas),
                    pdfa.AP.N.Resources.Font.keys()[0].encode('latin1'),
                ), b'stream\n' + pdfas + b'\nendstream\n'),
            self.makeobj(no + 5, (
                b'/ByteRange [0000000000 0000000000 0000000000 0000000000]/ContactInfo(%s)\
/Filter/Adobe.PPKLite/Location(%s)/M(D:%s)/Prop_Build<</App<</Name/>>>>/Reason(%s)/SubFilter/adbe.pkcs7.detached/Type/Sig\
/Contents <' % (udct[b'contact'], udct[b'location'], udct[b'signingdate'],
                udct[b'reason'])) + zeros + b'>'),
        ]

        pdfdata2 = b''.join(objs)
        xref = b'''\
xref\n\
%(page)d 1\n\
%(p0)010d 00000 n \n\
%(no)d 6\n\
%(n0)010d 00000 n \n\
%(n1)010d 00000 n \n\
%(n2)010d 00000 n \n\
%(n3)010d 00000 n \n\
%(n4)010d 00000 n \n\
%(n5)010d 00000 n \n\
'''
        startxref = len(pdfdata1)
        dct = {
            b'page': page,
            b'no': no,
            b'startxref': startxref + len(pdfdata2),
            b'prev': prev,
            b'info': no + 0,
            b'root': no + 1,
            b'size': 6,
            b'p0': startxref + pdfdata2.find(b'\n%d 0 obj\n' % page) + 1,
            b'n0': startxref + pdfdata2.find(b'\n%d 0 obj\n' % (no + 0)) + 1,
            b'n1': startxref + pdfdata2.find(b'\n%d 0 obj\n' % (no + 1)) + 1,
            b'n2': startxref + pdfdata2.find(b'\n%d 0 obj\n' % (no + 2)) + 1,
            b'n3': startxref + pdfdata2.find(b'\n%d 0 obj\n' % (no + 3)) + 1,
            b'n4': startxref + pdfdata2.find(b'\n%d 0 obj\n' % (no + 4)) + 1,
            b'n5': startxref + pdfdata2.find(b'\n%d 0 obj\n' % (no + 5)) + 1,
            b'h1': hashlib.md5(pdfdata1).hexdigest().upper().encode('ascii'),
            b'h2': hashlib.md5(pdfdata2).hexdigest().upper().encode('ascii'),
        }

        trailer = b'''\
trailer
<</ID [<%(h1)s><%(h2)s>]/Info %(info)d 0 R/Prev %(prev)d/Root %(root)d 0 R/Size %(size)d>>\n\
startxref\n\
%(startxref)d\n\
%%%%EOF\n\
'''

        xref = xref % dct
        trailer = trailer % dct

        pdfdata2 = pdfdata2 + xref + trailer

        return pdfdata2
Exemple #10
0
    def test_invert_identity(self):
        I = identity()

        assert I == matrix_inverse(I)
Exemple #11
0
    def test_invert_scale(self):
        assert scale(2, 4) == matrix_inverse(scale(0.5, 0.25))
        assert scale(0.1, 8) == matrix_inverse(scale(10, 0.125))

        assert identity() == matrix_multiply(scale(2, 4), scale(0.5, 0.25))
        assert identity() == matrix_multiply(scale(0.1, 8), scale(10, 0.125))
Exemple #12
0
    def test_multiply_identity(self):
        matrix = [1, 2, 3, 4, 5, 6]
        I = identity()

        assert matrix == matrix_multiply(matrix, I)
        assert matrix == matrix_multiply(I, matrix)
    def makepdf(self, zeros):
        root = self.prev.Root
        size = int(self.prev.Size, 10)

        while len(self.objects) < size - 1:
            self.objects.append(None)

        page0 = self.copydict(root.Pages.Kids[0])
        page0ref = PdfIndirect(root.Pages.Kids[0].indirect)

        obj10 = pdf.PdfDict()
        obj10ref = self.addObject(obj10)
        obj11 = pdf.PdfDict()
        obj11ref = self.addObject(obj11)
        obj12 = pdf.PdfDict()
        obj12ref = self.addObject(obj12)
        obj13 = pdf.PdfDict()
        obj13ref = self.addObject(obj13)
        obj14 = pdf.PdfDict()
        obj14ref = self.addObject(obj14)

        obj10.update({
            pdf.PdfName("Type"): pdf.PdfName("TransformParams"),
            pdf.PdfName("P"): PdfNumber(2),
            pdf.PdfName("V"): pdf.PdfName("1.2"),
        })
        obj11.update({
            pdf.PdfName("Type"): pdf.PdfName("SigRef"),
            pdf.PdfName("TransformMethod"): pdf.PdfName("DocMDP"),
            pdf.PdfName("DigestMethod"): pdf.PdfName("SHA1"),
            pdf.PdfName("TransformParams"): obj10ref,
        })
        obj12.update({
            pdf.PdfName("Type"):
            pdf.PdfName("Sig"),
            pdf.PdfName("Filter"):
            pdf.PdfName("Adobe.PPKLite"),
            pdf.PdfName("SubFilter"):
            pdf.PdfName("adbe.pkcs7.detached"),
            pdf.PdfName("Name"):
            pdf.PdfString.from_unicode("Example User"),
            pdf.PdfName("Location"):
            pdf.PdfString.from_unicode("Los Angeles, CA"),
            pdf.PdfName("Reason"):
            pdf.PdfString.from_unicode("Testing"),
            pdf.PdfName("M"):
            pdf.PdfString.from_unicode("D:20200317214832+01'00'"),
            pdf.PdfName("Reference"):
            pdf.PdfArray([obj11ref]),
            pdf.PdfName("Contents"):
            PdfHexBytes(zeros),
            pdf.PdfName("ByteRange"):
            pdf.PdfArray(
                [PdfNumberB(0),
                 PdfNumberB(0),
                 PdfNumberB(0),
                 PdfNumberB(0)]),
        })
        obj13.update({
            pdf.PdfName("FT"):
            pdf.PdfName("Sig"),
            pdf.PdfName("Type"):
            pdf.PdfName("Annot"),
            pdf.PdfName("Subtype"):
            pdf.PdfName("Widget"),
            pdf.PdfName("F"):
            PdfNumber(132),
            pdf.PdfName("T"):
            pdf.PdfString.from_unicode("Signature1"),
            pdf.PdfName("V"):
            obj12ref,
            pdf.PdfName("P"):
            page0ref,
            pdf.PdfName("Rect"):
            pdf.PdfArray([
                PdfNumberFloat(0.0),
                PdfNumberFloat(0.0),
                PdfNumberFloat(0.0),
                PdfNumberFloat(0.0),
            ]),
        })
        obj14.update({pdf.PdfName("DocMDP"): obj12ref})
        obj15 = pdf.PdfDict()
        obj15.update({
            pdf.PdfName("Fields"): pdf.PdfArray([obj13ref]),
            pdf.PdfName("SigFlags"): PdfNumber(3),
        })
        obj15ref = self.addObject(obj15)
        if self.annotbutton:
            from pdf_annotate.annotations.image import Image
            from pdf_annotate.annotations.text import FreeText
            from pdf_annotate.config.appearance import Appearance
            from pdf_annotate.config.location import Location
            from pdf_annotate.util.geometry import identity

            annotation = "User signature text"
            x1, y1, x2, y2 = (470, 0, 570, 100)
            annotation = FreeText(
                Location(x1=x1, y1=y1, x2=x2, y2=y2, page=0),
                Appearance(
                    fill=[0, 0, 0],
                    stroke_width=1,
                    wrap_text=True,
                    font_size=12,
                    content=annotation,
                ),
            )
            pdfa = annotation.as_pdf_object(identity(), page=None)
            objapn = self.extend(pdfa[pdf.PdfName("AP")][pdf.PdfName("N")])
            objapnref = self.addObject(objapn)
            for name in (
                    "BS",
                    "C",
                    "Contents",
                    "DA",
                    "Rect",
                    # "Subtype",
            ):
                key = pdf.PdfName(name)
                v = pdfa[key]
                if isinstance(v, str):
                    v = v.replace("/", "//")
                    v = pdf.PdfString.from_unicode(v)
                elif isinstance(v, list):
                    v = pdf.PdfArray(v)
                obj13.update({key: v})

            objap = pdf.PdfDict()
            objap.update({pdf.PdfName("N"): objapnref})
            obj13.update({
                pdf.PdfName("SM"):
                pdf.PdfString.from_unicode("TabletPOSinline"),
                pdf.PdfName("AP"):
                objap,
            })
            self.objects[root.Pages.Kids[0].indirect[0] - 1] = page0
            annots = pdf.PdfArray([obj13ref])
            # if False and pdf.PdfName("Annots") in page0:
            if pdf.PdfName("Annots") in page0:
                page0annots = page0[pdf.PdfName("Annots")]
                if isinstance(page0annots, PdfIndirect):
                    annots.insert(0, page0annots)
                elif isinstance(page0annots, pdf.PdfArray):
                    annots = page0annots
                    annots.append(obj13ref)
            page0.update({pdf.PdfName("Annots"): annots})

        croot = self.copydict(root)
        croot.update({
            pdf.PdfName("Perms"): obj14ref,
            pdf.PdfName("AcroForm"): obj15ref
        })
        self.objects[root.indirect[0] - 1] = croot
        try:
            ID = self.prev.ID[0]
        except:
            b = hashlib.md5(self.datau).digest()
            ID = pdf.PdfString.from_bytes(b, bytes_encoding="hex")
        b = repr(random.random()).encode()
        b = hashlib.md5(b).digest()
        self.trailer = pdf.PdfDict(
            Size=len(self.objects),
            Root=PdfIndirect(root.indirect),
            Info=PdfIndirect(self.prev.Info.indirect),
            Prev=self.startprev,
            ID=pdf.PdfArray(
                [ID, pdf.PdfString.from_bytes(b, bytes_encoding="hex")]),
        )
        if self.prev.private.pdfdict.encrypt:
            self.trailer.Encrypt = PdfIndirect(
                self.prev.private.pdfdict.encrypt.indirect)
Exemple #14
0
    def test_invert_identity(self):
        ident = identity()

        assert ident == matrix_inverse(ident)
Exemple #15
0
    def test_multiply_identity(self):
        matrix = [1, 2, 3, 4, 5, 6]
        ident = identity()

        assert matrix == matrix_multiply(matrix, ident)
        assert matrix == matrix_multiply(ident, matrix)