Esempio n. 1
0
    def __init__(
            self,
            field_name,
            *,
            box=None,
            include_on_page=None,
            is_annotation=True,
            # this sets the "print" bit
            annot_flags=0b100):

        if box is not None:
            rect = list(map(generic.FloatObject, box))
        else:
            rect = [generic.FloatObject(0)] * 4

        super().__init__({
            # Signature field properties
            pdf_name('/FT'):
            pdf_name('/Sig'),
            pdf_name('/T'):
            pdf_string(field_name),
        })
        if is_annotation:
            # Annotation properties: bare minimum
            self['/Type'] = pdf_name('/Annot')
            self['/Subtype'] = pdf_name('/Widget')
            self['/F'] = generic.NumberObject(annot_flags)
            self['/Rect'] = generic.ArrayObject(rect)
            if include_on_page is not None:
                self['/P'] = include_on_page
Esempio n. 2
0
    def __init__(self, cf: CIDFont):
        tt = cf.tt_font

        # Some metrics
        hhea = tt['hhea']
        head = tt['head']
        bbox = [head.xMin, head.yMin, head.xMax, head.yMax]
        os2 = tt['OS/2']
        weight = os2.usWeightClass
        stemv = int(10 + 220 * (weight - 50) / 900)
        super().__init__({
            pdf_name('/Type'): pdf_name('/FontDescriptor'),
            pdf_name('/FontName'): pdf_name('/' + cf.name),
            pdf_name('/Ascent'): generic.NumberObject(hhea.ascent),
            pdf_name('/Descent'): generic.NumberObject(hhea.descent),
            pdf_name('/FontBBox'): generic.ArrayObject(
                map(generic.NumberObject, bbox)
            ),
            # FIXME I'm setting the Serif and Symbolic flags here, but
            #  is there any way we can read/infer those from the TTF metadata?
            pdf_name('/Flags'): generic.NumberObject(0b110),
            pdf_name('/StemV'): generic.NumberObject(stemv),
            pdf_name('/ItalicAngle'): generic.FloatObject(
                getattr(tt['post'], 'italicAngle', 0)
            ),
            pdf_name('/CapHeight'): generic.NumberObject(
                getattr(os2, 'sCapHeight', 750)
            )
        })
Esempio n. 3
0
    def __init__(self, field_name, *, box=None, include_on_page=None,
                 combine_annotation=True,
                 # this sets the "print" and "lock" bits
                 annot_flags=0b10000100):

        if box is not None:
            rect = list(map(generic.FloatObject, box))
        else:
            rect = [generic.FloatObject(0)] * 4

        super().__init__({
            # Signature field properties
            pdf_name('/FT'): pdf_name('/Sig'),
            pdf_name('/T'): pdf_string(field_name),
        })

        if combine_annotation:
            annot_dict = self
        else:
            annot_dict = generic.DictionaryObject()

        # Annotation properties: bare minimum
        annot_dict['/Type'] = pdf_name('/Annot')
        annot_dict['/Subtype'] = pdf_name('/Widget')
        annot_dict['/F'] = generic.NumberObject(annot_flags)
        annot_dict['/Rect'] = generic.ArrayObject(rect)

        self.page_ref = include_on_page
        if include_on_page is not None:
            annot_dict['/P'] = include_on_page

        self.annot_dict = annot_dict
Esempio n. 4
0
    def __init__(self,
                 field_name,
                 include_on_page,
                 *,
                 writer,
                 sig_object_ref=None,
                 box=None,
                 appearances: Optional[AnnotAppearances] = None):

        if box is not None:
            visible = True
            rect = list(map(generic.FloatObject, box))
            if appearances is not None:
                ap = appearances.as_pdf_object()
            else:
                ap = None
        else:
            rect = [generic.FloatObject(0)] * 4
            ap = None
            visible = False

        # this sets the "Print" bit, and activates "Locked" if the
        # signature field is ready to be filled
        flags = 0b100 if sig_object_ref is None else 0b10000100
        super().__init__({
            # Signature field properties
            pdf_name('/FT'):
            pdf_name('/Sig'),
            pdf_name('/T'):
            pdf_string(field_name),
            # Annotation properties: bare minimum
            pdf_name('/Type'):
            pdf_name('/Annot'),
            pdf_name('/Subtype'):
            pdf_name('/Widget'),
            pdf_name('/F'):
            generic.NumberObject(flags),
            pdf_name('/P'):
            include_on_page,
            pdf_name('/Rect'):
            generic.ArrayObject(rect)
        })
        if sig_object_ref is not None:
            self[pdf_name('/V')] = sig_object_ref
        if ap is not None:
            self[pdf_name('/AP')] = ap

        # register ourselves
        self.reference = self_reference = writer.add_object(self)
        # if we're building an invisible form field, this is all there is to it
        if visible:
            writer.register_annotation(include_on_page, self_reference)
Esempio n. 5
0
    def _render_background(self):

        bg = self.style.background
        bg.set_writer(self.writer)
        bg_content = bg.render()  # render first, in case the BBox is lazy

        bg_box = bg.box
        if bg_box.width_defined and bg_box.height_defined:
            # apply layout rule
            positioning = self.style.background_layout.fit(
                self.box, bg_box.width, bg_box.height
            )
        else:
            # No idea about the background dimensions, so just use
            # the left/bottom margins and hope for the best
            margins = self.style.background_layout.margins
            positioning = layout.Positioning(
                x_scale=1, y_scale=1,
                x_pos=margins.left, y_pos=margins.bottom
            )

        # set opacity in graphics state
        opacity = generic.FloatObject(self.style.background_opacity)
        self.set_resource(
            category=content.ResourceType.EXT_G_STATE,
            name=pdf_name('/BackgroundGS'),
            value=generic.DictionaryObject({
                pdf_name('/CA'): opacity, pdf_name('/ca'): opacity
            })
        )

        # Position & render the background
        command = b'q /BackgroundGS gs %s %s Q' % (
            positioning.as_cm(), bg_content
        )
        # we do this after render(), just in case our background resource
        # decides to pull in extra stuff during rendering
        self.import_resources(bg.resources)
        return command
Esempio n. 6
0
    def render(self):
        command_stream = [b'q']

        # text rendering
        self._init_text_box()
        _text_params = self.get_default_text_params()
        if self.text_params is not None:
            _text_params.update(self.text_params)
        text = self.style.stamp_text % _text_params
        self.text_box.content = text

        stamp_height = self.get_stamp_height()
        stamp_width = self.get_stamp_width()

        bg = self.style.background
        if bg is not None:
            # TODO this is one of the places where some more clever layout
            #  engine would really help, since all of this is pretty ad hoc and
            #  makes a number of non-obvious choices that would be better off
            #  delegated to somewhere else.
            bg.set_writer(self.writer)

            # scale the background
            bg_height = 0.9 * stamp_height
            if bg.box.height_defined:
                sf = bg_height / bg.box.height
            else:
                bg.box.height = bg_height
                sf = 1
            bg_y = 0.05 * stamp_height
            bg_width = bg.box.width * sf
            bg_x = 0
            if bg_width <= stamp_width:
                bg_x = (stamp_width - bg_width) // 2

            # set opacity in graphics state
            opacity = generic.FloatObject(self.style.background_opacity)
            self.set_resource(category=ResourceType.EXT_G_STATE,
                              name=pdf_name('/BackgroundGS'),
                              value=generic.DictionaryObject({
                                  pdf_name('/CA'):
                                  opacity,
                                  pdf_name('/ca'):
                                  opacity
                              }))
            command_stream.append(
                b'q /BackgroundGS gs %g 0 0 %g %g %g cm %s Q' %
                (sf, sf, bg_x, bg_y, bg.render()))
            self.import_resources(bg.resources)

        tb = self.text_box
        text_commands = tb.render()

        text_scale = 1
        if self.expected_text_width is not None and tb.box.width_defined:
            text_scale = self.expected_text_width / tb.box.width

        command_stream.append(
            b'q %g 0 0 %g %g %g cm' %
            (text_scale, text_scale, self.text_box_x(), self.text_box_y()))
        command_stream.append(text_commands)
        command_stream.append(b'Q')

        # append additional drawing commands
        command_stream.extend(self.extra_commands())

        # draw border around stamp
        command_stream.append(
            b'%g w 0 0 %g %g re S' %
            (self.style.border_width, stamp_width, stamp_height))
        command_stream.append(b'Q')
        return b' '.join(command_stream)