def add_resources(self): r = Dictionary() if self.opacities: extgs = Dictionary() for opref, name in iteritems(self.opacities): extgs[name] = opref r['ExtGState'] = extgs if self.fonts: fonts = Dictionary() for ref, name in iteritems(self.fonts): fonts[name] = ref r['Font'] = fonts if self.xobjects: xobjects = Dictionary() for ref, name in iteritems(self.xobjects): xobjects[name] = ref r['XObject'] = xobjects if self.patterns: r['ColorSpace'] = Dictionary( {'PCSp': Array([Name('Pattern'), Name('DeviceRGB')])}) patterns = Dictionary() for ref, name in iteritems(self.patterns): patterns[name] = ref r['Pattern'] = patterns if r: self.page_dict['Resources'] = r
def __init__(self, brush, matrix, pdf, pixel_page_width, pixel_page_height): self.matrix = (matrix.m11(), matrix.m12(), matrix.m21(), matrix.m22(), matrix.dx(), matrix.dy()) gradient = sip.cast(brush.gradient(), QLinearGradient) start, stop, stops = self.spread_gradient(gradient, pixel_page_width, pixel_page_height, matrix) # TODO: Handle colors with different opacities self.const_opacity = stops[0].color[-1] funcs = Array() bounds = Array() encode = Array() for i, current_stop in enumerate(stops): if i < len(stops) - 1: next_stop = stops[i+1] func = Dictionary({ 'FunctionType': 2, 'Domain': Array([0, 1]), 'C0': Array(current_stop.color[:3]), 'C1': Array(next_stop.color[:3]), 'N': 1, }) funcs.append(func) encode.extend((0, 1)) if i+1 < len(stops) - 1: bounds.append(next_stop.t) func = Dictionary({ 'FunctionType': 3, 'Domain': Array([stops[0].t, stops[-1].t]), 'Functions': funcs, 'Bounds': bounds, 'Encode': encode, }) shader = Dictionary({ 'ShadingType': 2, 'ColorSpace': Name('DeviceRGB'), 'AntiAlias': True, 'Coords': Array([start.x(), start.y(), stop.x(), stop.y()]), 'Function': func, 'Extend': Array([True, True]), }) Dictionary.__init__(self, { 'Type': Name('Pattern'), 'PatternType': 2, 'Shading': shader, 'Matrix': Array(self.matrix), }) self.cache_key = (self.__class__.__name__, self.matrix, tuple(shader['Coords']), stops)
def add_standard_font(self, name): if name not in STANDARD_FONTS: raise ValueError('%s is not a standard font'%name) if name not in self.std_map: self.std_map[name] = self.objects.add(Dictionary({ 'Type':Name('Font'), 'Subtype':Name('Type1'), 'BaseFont':Name(name) })) return self.std_map[name]
def add_links(self): for link in self.links: path, href, frag = link[0] page, rect = link[1:] combined_path = os.path.normcase( os.path.abspath( os.path.join(os.path.dirname(path), *unquote(href).split('/')))) is_local = not href or combined_path in self.anchors annot = Dictionary({ 'Type': Name('Annot'), 'Subtype': Name('Link'), 'Rect': rect, 'Border': Array([0, 0, 0]), }) if self.mark_links: annot.update({ 'Border': Array([16, 16, 1]), 'C': Array([1.0, 0, 0]) }) if is_local: path = combined_path if href else path try: annot['Dest'] = self.anchors[path][frag] except KeyError: try: annot['Dest'] = self.anchors[path][None] except KeyError: pass else: url = href + (('#' + frag) if frag else '') try: purl = urlparse(url) except Exception: self.pdf.debug('Ignoring unparseable URL: %r' % url) continue if purl.scheme and purl.scheme != 'file': action = Dictionary({ 'Type': Name('Action'), 'S': Name('URI'), }) # Do not try to normalize/quote/unquote this URL as if it # has a query part, it will get corrupted action['URI'] = String(url) annot['A'] = action if 'A' in annot or 'Dest' in annot: if 'Annots' not in page: page['Annots'] = Array() page['Annots'].append(self.pdf.objects.add(annot)) else: self.pdf.debug( 'Could not find destination for link: %s in file %s' % (href, path))
def add_links(self): for link in self.links: path, href, frag = link[0] page, rect = link[1:] combined_path = os.path.abspath( os.path.join(os.path.dirname(path), *unquote(href).split('/'))) is_local = not href or combined_path in self.anchors annot = Dictionary({ 'Type': Name('Annot'), 'Subtype': Name('Link'), 'Rect': rect, 'Border': Array([0, 0, 0]), }) if self.mark_links: annot.update({ 'Border': Array([16, 16, 1]), 'C': Array([1.0, 0, 0]) }) if is_local: path = combined_path if href else path try: annot['Dest'] = self.anchors[path][frag] except KeyError: try: annot['Dest'] = self.anchors[path][None] except KeyError: pass else: url = href + (('#' + frag) if frag else '') purl = urlparse(url) if purl.scheme and purl.scheme != 'file': action = Dictionary({ 'Type': Name('Action'), 'S': Name('URI'), }) parts = (x.encode('utf-8') if isinstance(x, type(u'')) else x for x in purl) url = urlunparse(map(quote, map(unquote, parts))).decode('ascii') action['URI'] = String(url) annot['A'] = action if 'A' in annot or 'Dest' in annot: if 'Annots' not in page: page['Annots'] = Array() page['Annots'].append(self.pdf.objects.add(annot)) else: self.pdf.debug( 'Could not find destination for link: %s in file %s' % (href, path))
def __init__(self, page_size): super().__init__({ 'Type': Name('Pages'), 'MediaBox': Array([0, 0, page_size[0], page_size[1]]), 'Kids': Array(), 'Count': 0, })
def draw_image(self, x, y, width, height, imgref): name = self.current_page.add_image(imgref) self.current_page.write( 'q %s 0 0 %s %s %s cm ' % (fmtnum(width), fmtnum(-height), fmtnum(x), fmtnum(y + height))) serialize(Name(name), self.current_page) self.current_page.write_line(' Do Q')
def add_extra_keys(self, d): d['Type'] = Name('XObject') d['Subtype'] = Name('Image') d['Width'] = self.width d['Height'] = self.height if self.depth == 1: d['ImageMask'] = True d['Decode'] = Array([1, 0]) else: d['BitsPerComponent'] = 8 d['ColorSpace'] = Name('Device' + ('RGB' if self.depth == 32 else 'Gray')) if self.mask is not None: d['Mask'] = self.mask if self.soft_mask is not None: d['SMask'] = self.soft_mask
def __init__(self, start_page, pos, get_pageref): pnum = start_page + pos['column'] try: pref = get_pageref(pnum) except IndexError: pref = get_pageref(pnum - 1) super(Destination, self).__init__( [pref, Name('XYZ'), pos['left'], pos['top'], None])
def __init__(self, data, w, h, depth, mask, soft_mask, dct): Stream.__init__(self) self.width, self.height, self.depth = w, h, depth self.mask, self.soft_mask = mask, soft_mask if dct: self.filters.append(Name('DCTDecode')) else: self.compress = True self.write(data)
def draw_image_with_transform(self, imgref, translation=(0, 0), scaling=(1, 1)): name = self.current_page.add_image(imgref) self.current_page.write('q {} 0 0 {} {} {} cm '.format( *(tuple(scaling) + tuple(translation)))) serialize(Name(name), self.current_page) self.current_page.write_line(' Do Q')
def __init__(self, parentref, *args, **kwargs): super(Page, self).__init__(*args, **kwargs) self.page_dict = Dictionary({ 'Type': Name('Page'), 'Parent': parentref, }) self.opacities = {} self.fonts = {} self.xobjects = {} self.patterns = {}
def add_extra_keys(self, d): d['Type'] = Name('Pattern') d['PatternType'] = 1 d['PaintType'] = self.paint_type d['TilingType'] = 1 d['BBox'] = Array([0, 0, self.w, self.h]) d['XStep'] = self.w d['YStep'] = self.h d['Matrix'] = Array(self.matrix) d['Resources'] = self.resources
def draw_glyph_run(self, transform, size, font_metrics, glyphs): glyph_ids = {x[-1] for x in glyphs} fontref = self.font_manager.add_font(font_metrics, glyph_ids) name = self.current_page.add_font(fontref) self.current_page.write(b'BT ') serialize(Name(name), self.current_page) self.current_page.write(' %s Tf '%fmtnum(size)) self.current_page.write('%s Tm '%' '.join(map(fmtnum, transform))) for x, y, glyph_id in glyphs: self.current_page.write_raw(('%s %s Td <%04X> Tj '%( fmtnum(x), fmtnum(y), glyph_id)).encode('ascii')) self.current_page.write_line(b' ET')
def __init__(self, metrics, num, objects, compress): self.metrics, self.compress = metrics, compress self.is_otf = self.metrics.is_otf self.subset_tag = str( re.sub('.', lambda m: codepoint_to_chr(int(m.group())+ord('A')), oct(num).replace('o', '') )).rjust(6, 'A') self.font_stream = FontStream(metrics.is_otf, compress=compress) try: psname = metrics.postscript_name except Exception: psname = uuid4() self.font_descriptor = Dictionary({ 'Type': Name('FontDescriptor'), 'FontName': Name('%s+%s'%(self.subset_tag, psname)), 'Flags': 0b100, # Symbolic font 'FontBBox': Array(metrics.pdf_bbox), 'ItalicAngle': metrics.post.italic_angle, 'Ascent': metrics.pdf_ascent, 'Descent': metrics.pdf_descent, 'CapHeight': metrics.pdf_capheight, 'AvgWidth': metrics.pdf_avg_width, 'StemV': metrics.pdf_stemv, }) self.descendant_font = Dictionary({ 'Type':Name('Font'), 'Subtype':Name('CIDFontType' + ('0' if metrics.is_otf else '2')), 'BaseFont': self.font_descriptor['FontName'], 'FontDescriptor':objects.add(self.font_descriptor), 'CIDSystemInfo':Dictionary({ 'Registry':String('Adobe'), 'Ordering':String('Identity'), 'Supplement':0, }), }) if not self.is_otf: self.descendant_font['CIDToGIDMap'] = Name('Identity') self.font_dict = Dictionary({ 'Type':Name('Font'), 'Subtype':Name('Type0'), 'Encoding':Name('Identity-H'), 'BaseFont':self.descendant_font['BaseFont'], 'DescendantFonts':Array([objects.add(self.descendant_font)]), }) self.used_glyphs = set()
def __init__(self, start_page, pos, get_pageref): pnum = start_page + max(0, pos['column']) q = pnum while q > -1: try: pref = get_pageref(q) break except IndexError: pos['left'] = pos['top'] = 0 q -= 1 if q != pnum: current_log().warn( 'Could not find page {} for link destination, using page {} instead' .format(pnum, q)) super().__init__([pref, Name('XYZ'), pos['left'], pos['top'], None])
def set_opacity(self, opref): if opref not in self.opacities: self.opacities[opref] = 'Opa%d' % len(self.opacities) name = self.opacities[opref] serialize(Name(name), self) self.write(b' gs ')
def set_fill_opacity(self, opacity): opacity = float(opacity) if opacity not in self.fill_opacities: op = Dictionary({'Type': Name('ExtGState'), 'ca': opacity}) self.fill_opacities[opacity] = self.objects.add(op) self.current_page.set_opacity(self.fill_opacities[opacity])
def set_stroke_opacity(self, opacity): if opacity not in self.stroke_opacities: op = Dictionary({'Type': Name('ExtGState'), 'CA': opacity}) self.stroke_opacities[opacity] = self.objects.add(op) self.current_page.set_opacity(self.stroke_opacities[opacity])
def add_extra_keys(self, d): d['Type'] = Name('Metadata') d['Subtype'] = Name('XML')
def add_outline(self, toc): parent = Dictionary({'Type': Name('Outlines')}) parentref = self.pdf.objects.add(parent) self.process_children(toc, parentref, parent_is_root=True) self.pdf.catalog.obj['Outlines'] = parentref
def add_extra_keys(self, d): d['Length1'] = d['DL'] if self.is_otf: d['Subtype'] = Name('CIDFontType0C')
def __init__(self, pagetree): super(Catalog, self).__init__({ 'Type': Name('Catalog'), 'Pages': pagetree })