Пример #1
0
    def make_appearance_stream(self):
        A = self._appearance
        L = self._location

        stream = ContentStream([
            Save(),
            BeginText(),
            FillColor(*A.fill[:3]),
            Font(PDF_ANNOTATOR_FONT, A.font_size),
        ])

        graphics_state = A.get_graphics_state()
        if graphics_state.has_content():
            stream.add(CSGraphicsState(GRAPHICS_STATE_NAME))

        # Actually draw the text inside the rectangle
        stream.extend(
            get_text_commands(
                L.x1,
                L.y1,
                L.x2,
                L.y2,
                text=A.content,
                font_size=A.font_size,
                wrap_text=A.wrap_text,
                align=A.text_align,
                baseline=A.text_baseline,
                line_spacing=A.line_spacing,
            ))
        stream.extend([
            EndText(),
            Restore(),
        ])

        return stream
 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,
        )
Пример #4
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,
        )
Пример #5
0
 def test_transform_content_stream(self):
     cs = ContentStream([
         Save(),
         Move(1, 1),
         Restore(),
     ])
     transformed = cs.transform([2, 0, 0, 2, 5, 10]).resolve()
     assert transformed == 'q 7 12 m Q'
Пример #6
0
    def make_appearance_stream(self):
        L = self._location
        A = self._appearance

        stream = ContentStream([Save()])
        set_appearance_state(stream, A)
        add_bezier_circle(stream, L.x1, L.y1, L.x2, L.y2)
        stroke_or_fill(stream, A)
        stream.add(Restore())

        return stream
Пример #7
0
    def make_appearance_stream(self):
        A = self._appearance
        points = self._location.points

        stream = ContentStream([Save()])
        set_appearance_state(stream, A)
        stream.add(Move(points[0][0], points[0][1]))
        stream.add(CSLine(points[1][0], points[1][1]))
        stroke_or_fill(stream, A)
        stream.add(Restore())

        return stream
Пример #8
0
    def make_appearance_stream(self):
        A = self._appearance
        L = self._location

        stream = ContentStream([Save()])
        set_appearance_state(stream, A)
        stream.extend([
            Rect(L.x1, L.y1, L.x2 - L.x1, L.y2 - L.y1),
            CTM(self.get_ctm(L.x1, L.y1, L.x2, L.y2)),
            XObject('Image'),
            Restore(),
        ])
        return stream
Пример #9
0
    def make_appearance_stream(self):
        A = self._appearance
        points = self._location.points

        stream = ContentStream([Save()])
        set_appearance_state(stream, A)
        stream.add(Move(points[0][0], points[0][1]))
        for x, y in points[1:]:
            stream.add(CSLine(x, y))
        # TODO add a 'close' attribute?
        stream.extend([Stroke(), Restore()])

        return stream
Пример #10
0
    def make_appearance_stream(self):
        A = self._appearance
        points = self._location.points

        stream = ContentStream([Save()])
        set_appearance_state(stream, A)
        stream.add(Move(points[0][0], points[0][1]))
        # TODO "real" PDF editors do smart smoothing of ink points using
        # interpolated Bezier curves.
        for x, y in points[1:]:
            stream.add(CSLine(x, y))
        stream.extend([Stroke(), Restore()])

        return stream
Пример #11
0
    def make_appearance_stream(self):
        L = self._location
        A = self._appearance
        stream = ContentStream([Save()])

        set_appearance_state(stream, A)
        stream.add(Rect(
            L.x1,
            L.y1,
            L.x2 - L.x1,
            L.y2 - L.y1,
        ))
        stroke_or_fill(stream, A)
        stream.add(Restore())

        # TODO dash array
        return stream
    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,
        )
Пример #13
0
 def test_content_stream(self):
     # Basically a smoke test for all the simple functions of ContentStream
     cs = ContentStream([Save(), StrokeWidth(2)])
     cs.add(StrokeColor(0, 0, 0))
     cs.add(FillColor(1, 0, 0))
     cs.extend([
         Move(10, 10),
         Line(20, 20),
         Bezier(30, 30, 40, 40, 50, 50),
         Rect(50, 50, 10, 10),
     ])
     cs = ContentStream.join(
         cs,
         ContentStream([
             Close(),
             StrokeAndFill(),
             Stroke(),
             Fill(),
             Restore(),
         ]))
     assert cs.resolve() == ('q 2 w 0 0 0 RG 1 0 0 rg 10 10 m 20 20 l '
                             '30 30 40 40 50 50 c 50 50 10 10 re '
                             'h B S f Q')
Пример #14
0
class TestContentStream(TestCase):
    # a list of (ContentStream, stream_string) pairs for testing parse/resolve
    FIXTURES = [
        (ContentStream([
            CTM([1, 0, 0, 1, 0, 0]),
            Font('Helvetica', 12),
            TextMatrix([1, 0, 0, 1, 20, 50]),
            BeginText(),
            Text('Sure, why not?'),
            EndText(),
        ]), ('1 0 0 1 0 0 cm /Helvetica 12 Tf '
             '1 0 0 1 20 50 Tm BT '
             '(Sure, why not?) Tj ET')),
        (ContentStream([
            Save(),
            StrokeWidth(2),
            StrokeColor(0, 0, 0),
            FillColor(1, 0, 0),
            Move(10, 10),
            Line(20, 20),
            Bezier(30, 30, 40, 40, 50, 50),
            Rect(50, 50, 10, 10),
            Close(),
            StrokeAndFill(),
            Stroke(),
            Fill(),
            Restore(),
        ]), ('q 2 w 0 0 0 RG 1 0 0 rg 10 10 m 20 20 l '
             '30 30 40 40 50 50 c 50 50 10 10 re '
             'h B S f Q')),
    ]

    def test_equality(self):
        assert ContentStream() == ContentStream()

        cs1 = ContentStream([Save(), FillColor(1, 0, 0)])
        cs2 = ContentStream([Save(), FillColor(1, 0, 0)])
        assert cs1 == cs2

    def test_content_stream_not_equal_to_string(self):
        assert ContentStream() != ''
        assert ContentStream([Save()]) != 'q'

    def test_resolve(self):
        for cs, stream_string in self.FIXTURES:
            assert cs.resolve() == stream_string

    def test_content_stream(self):
        # Basically a smoke test for all the simple functions of ContentStream
        cs = ContentStream([Save(), StrokeWidth(2)])
        cs.add(StrokeColor(0, 0, 0))
        cs.add(FillColor(1, 0, 0))
        cs.extend([
            Move(10, 10),
            Line(20, 20),
            Bezier(30, 30, 40, 40, 50, 50),
            Rect(50, 50, 10, 10),
        ])
        cs = ContentStream.join(
            cs,
            ContentStream([
                Close(),
                StrokeAndFill(),
                Stroke(),
                Fill(),
                Restore(),
            ]))
        assert cs.resolve() == ('q 2 w 0 0 0 RG 1 0 0 rg 10 10 m 20 20 l '
                                '30 30 40 40 50 50 c 50 50 10 10 re '
                                'h B S f Q')

    def test_text_content_stream(self):
        cs = ContentStream([
            CTM([1, 0, 0, 1, 0, 0]),
            Font('Helvetica', 12),
            TextMatrix([1, 0, 0, 1, 20, 50]),
            BeginText(),
            Text('Sure, why not?'),
            EndText(),
        ])
        assert cs.resolve() == ('1 0 0 1 0 0 cm /Helvetica 12 Tf '
                                '1 0 0 1 20 50 Tm BT '
                                '(Sure, why not?) Tj ET')

    def test_transform_move(self):
        transformed = Move(1, 1).transform([2, 0, 0, 2, 5, 10]).resolve()
        assert transformed == '7 12 m'

    def test_transform_line(self):
        transformed = Line(1, 1).transform([2, 0, 0, 2, 5, 10]).resolve()
        assert transformed == '7 12 l'

    def test_transform_rect(self):
        transformed = Rect(1, 1, 2, 2).transform([2, 0, 0, 2, 5, 10]).resolve()
        assert transformed == '7 12 4 4 re'

    def test_transform_bezier(self):
        transformed = Bezier(1, 1, 2, 2, 3,
                             3).transform([2, 0, 0, 2, 5, 10], ).resolve()
        assert transformed == '7 12 9 14 11 16 c'

    def test_transform_content_stream(self):
        cs = ContentStream([
            Save(),
            Move(1, 1),
            Restore(),
        ])
        transformed = cs.transform([2, 0, 0, 2, 5, 10]).resolve()
        assert transformed == 'q 7 12 m Q'