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_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 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 "") purl = urlparse(url) 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 __init__(self, metrics, num, objects, compress): self.metrics, self.compress = metrics, compress self.is_otf = self.metrics.is_otf self.subset_tag = bytes( re.sub('.', lambda m: chr(int(m.group()) + ord('A')), oct(num))).rjust(6, b'A').decode('ascii') 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 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 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 __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)