def gather_elements(self, client, node, style): try: for entry in node["entries"]: client.pending_targets.append(docutils.nodes.make_id(entry[2])) except IndexError: if node["entries"]: log.error("Can't process index entry: %s [%s]", node["entries"], nodeid(node)) return []
def gather_elements(self, client, node, style): try: client.pending_targets.append(node['entries'][0][2]) except IndexError: if node['entries']: log.error("Can't process index entry: %s [%s]", node['entries'], nodeid(node)) return []
def gather_elements(self, client, node, style): try: for entry in node['entries']: client.pending_targets.append(docutils.nodes.make_id(entry[2])) except IndexError: if node['entries']: log.error("Can't process index entry: %s [%s]", node['entries'], nodeid(node)) return []
def parseRaw(data, node): """Parse and process a simple DSL to handle creation of flowables. Supported (can add others on request): * PageBreak * EvenPageBreak * OddPageBreak * FrameBreak * Spacer width, height * Transition * SetPageCounter * TextAnnotation "text of annotation" x_begin=-1 y_begin=-1 x_end=-1 y_end=-1 """ elements = [] lines = data.splitlines() for line in lines: lexer = shlex.shlex(line) lexer.whitespace += ',' tokens = list(lexer) if not tokens: continue # Empty line command = tokens[0] if command == 'PageBreak': if len(tokens) == 1: elements.append(MyPageBreak()) else: elements.append(MyPageBreak(tokens[1])) elif command == 'EvenPageBreak': if len(tokens) == 1: elements.append(MyPageBreak(breakTo='even')) else: elements.append(MyPageBreak(tokens[1], breakTo='even')) elif command == 'OddPageBreak': if len(tokens) == 1: elements.append(MyPageBreak(breakTo='odd')) else: elements.append(MyPageBreak(tokens[1], breakTo='odd')) elif command == 'FrameBreak': if len(tokens) == 1: elements.append(CondPageBreak(99999)) else: elements.append(CondPageBreak(float(tokens[1]))) elif command == 'Spacer': elements.append( MySpacer(adjustUnits(tokens[1]), adjustUnits(tokens[2]))) elif command == 'Transition': elements.append(Transition(*tokens[1:])) elif command == 'SetPageCounter': elements.append(flowables.PageCounter(*tokens[1:])) elif command == 'TextAnnotation': elements.append(TextAnnotation(*tokens[1:])) else: log.error('Unknown command %s in raw pdf directive [%s]' % (command, nodeid(node))) return elements
def log_unknown(self, node, during): if not hasattr(self, "unkn_node"): self.unkn_node = set() cln = self.getclassname(node) if not cln in self.unkn_node: self.unkn_node.add(cln) log.warning("Unkn. node (self.%s): %s [%s]", during, cln, nodeid(node)) try: log.debug(node) except (UnicodeDecodeError, UnicodeEncodeError): log.debug(repr(node))
def log_unknown(self, node, during): if not hasattr(self, 'unkn_node'): self.unkn_node = set() cln = self.getclassname(node) if not cln in self.unkn_node: self.unkn_node.add(cln) log.warning("Unkn. node (self.%s): %s [%s]", during, cln, nodeid(node)) try: log.debug(node) except (UnicodeDecodeError, UnicodeEncodeError): log.debug(repr(node))
def getstyle(self, client, node, style): try: if node["classes"] and node["classes"][0]: # FIXME: Supports only one class, sorry ;-) if client.styles.StyleSheet.has_key(node["classes"][0]): style = client.styles[node["classes"][0]] else: log.info("Unknown class %s, ignoring. [%s]", node["classes"][0], nodeid(node)) except TypeError: # Happens when a docutils.node.Text reaches here pass if style is None or style == client.styles["bodytext"]: style = client.styles.styleForNode(node) return style
def parseRaw(data, node): """Parse and process a simple DSL to handle creation of flowables. Supported (can add others on request): * PageBreak * Spacer width, height """ elements = [] lines = data.splitlines() for line in lines: lexer = shlex.shlex(line) lexer.whitespace += ',' tokens = list(lexer) if not tokens: continue # Empty line command = tokens[0] if command == 'PageBreak': if len(tokens) == 1: elements.append(MyPageBreak()) else: elements.append(MyPageBreak(tokens[1])) elif command == 'EvenPageBreak': if len(tokens) == 1: elements.append(MyPageBreak(breakTo='even')) else: elements.append(MyPageBreak(tokens[1],breakTo='even')) elif command == 'OddPageBreak': if len(tokens) == 1: elements.append(MyPageBreak(breakTo='odd')) else: elements.append(MyPageBreak(tokens[1],breakTo='odd')) elif command == 'FrameBreak': if len(tokens) == 1: elements.append(CondPageBreak(99999)) else: elements.append(CondPageBreak(float(tokens[1]))) elif command == 'Spacer': elements.append(MySpacer(adjustUnits(tokens[1]), adjustUnits(tokens[2]))) elif command == 'Transition': elements.append(Transition(*tokens[1:])) elif command == 'SetPageCounter': elements.append(flowables.PageCounter(*tokens[1:])) else: log.error('Unknown command %s in raw pdf directive [%s]'%(command,nodeid(node))) return elements
def getstyle(self, client, node, style): try: if node['classes'] and node['classes'][0]: # FIXME: Supports only one class, sorry ;-) if client.styles.StyleSheet.has_key(node['classes'][0]): style = client.styles[node['classes'][0]] else: log.info("Unknown class %s, ignoring. [%s]", node['classes'][0], nodeid(node)) except TypeError: # Happens when a docutils.node.Text reaches here pass if style is None or style == client.styles['bodytext']: style = client.styles.styleForNode(node) return style
def findsubclass(self, node, during): handlerinfo = '%s.%s' % (self.getclassname(self), during) log.debug("%s: %s", handlerinfo, self.getclassname(node)) log.debug("%s: [%s]", handlerinfo, nodeid(node)) try: log.debug("%s: %s", handlerinfo, node) except (UnicodeDecodeError, UnicodeEncodeError): log.debug("%s: %r", handlerninfo, node) log.debug("") # Dispatch to the first matching class in the MRO dispatchdict = self.dispatchdict for baseclass in inspect.getmro(node.__class__): result = dispatchdict.get(baseclass) if result is not None: break else: self.log_unknown(node, during) result = self return result
def size_for_node(self, node, client): '''Given a docutils image node, returns the size the image should have in the PDF document, and what 'kind' of size that is. That involves lots of guesswork''' uri = os.path.join(client.basedir, str(node.get("uri"))) srcinfo = client, uri # Extract all the information from the URI imgname, extension, options = self.split_uri(uri) if not os.path.isfile(imgname): imgname = missing scale = float(node.get('scale', 100)) / 100 size_known = False # Figuring out the size to display of an image is ... annoying. # If the user provides a size with a unit, it's simple, adjustUnits # will return it in points and we're done. # However, often the unit wil be "%" (specially if it's meant for # HTML originally. In which case, we will use a percentage of # the containing frame. # Find the image size in pixels: kind = 'direct' xdpi, ydpi = client.styles.def_dpi, client.styles.def_dpi extension = imgname.split('.')[-1].lower() if extension in ['svg', 'svgz'] and SVGImage.available(): iw, ih = SVGImage(imgname, srcinfo=srcinfo).wrap(0, 0) # These are in pt, so convert to px iw = iw * xdpi / 72 ih = ih * ydpi / 72 elif extension in [ "ai", "ccx", "cdr", "cgm", "cmx", "sk1", "sk", "xml", "wmf", "fig" ] and VectorImage.available(): iw, ih = VectorImage(imgname, srcinfo=srcinfo).wrap(0, 0) # These are in pt, so convert to px iw = iw * xdpi / 72 ih = ih * ydpi / 72 elif extension == 'pdf': if VectorPdf is not None: box = VectorPdf.load_xobj(srcinfo).BBox else: pdf = LazyImports.pdfinfo if pdf is None: log.warning( 'PDF images are not supported without pyPdf or pdfrw [%s]', nodeid(node)) return 0, 0, 'direct' reader = pdf.PdfFileReader(open(imgname, 'rb')) box = [float(x) for x in reader.getPage(0)['/MediaBox']] x1, y1, x2, y2 = box # These are in pt, so convert to px iw = float((x2 - x1) * xdpi / 72) ih = float((y2 - y1) * ydpi / 72) size_known = True # Assume size from original PDF is OK else: keeptrying = True if LazyImports.PILImage: try: img = LazyImports.PILImage.open(imgname) img.load() iw, ih = img.size xdpi, ydpi = img.info.get('dpi', (xdpi, ydpi)) keeptrying = False except IOError: # PIL throws this when it's a broken/unknown image pass if keeptrying and LazyImports.PMImage: img = LazyImports.PMImage(imgname) iw = img.size().width() ih = img.size().height() density = img.density() # The density is in pixelspercentimeter (!?) xdpi = density.width() * 2.54 ydpi = density.height() * 2.54 keeptrying = False if keeptrying: log.error( "The image (%s, %s) is broken or in an unknown format", imgname, nodeid(node)) raise ValueError # Try to get the print resolution from the image itself via PIL. # If it fails, assume a DPI of 300, which is pretty much made up, # and then a 100% size would be iw*inch/300, so we pass # that as the second parameter to adjustUnits # # Some say the default DPI should be 72. That would mean # the largest printable image in A4 paper would be something # like 480x640. That would be awful. # w = node.get('width') h = node.get('height') if h is None and w is None: # Nothing specified # Guess from iw, ih log.warning( "Using image %s without specifying size." "Calculating based on image size at %ddpi [%s]", imgname, xdpi, nodeid(node)) w = iw * inch / xdpi h = ih * inch / ydpi elif w is not None: # Node specifies only w # In this particular case, we want the default unit # to be pixels so we work like rst2html if w[-1] == '%': kind = 'percentage_of_container' w = int(w[:-1]) else: # This uses default DPI setting because we # are not using the image's "natural size" # this is what LaTeX does, according to the # docutils mailing list discussion w = client.styles.adjustUnits(w, client.styles.tw, default_unit='px') if h is None: # h is set from w with right aspect ratio h = w * ih / iw else: h = client.styles.adjustUnits(h, ih * inch / ydpi, default_unit='px') elif h is not None and w is None: if h[-1] != '%': h = client.styles.adjustUnits(h, ih * inch / ydpi, default_unit='px') # w is set from h with right aspect ratio w = h * iw / ih else: log.error('Setting height as a percentage does **not** work. '\ 'ignoring height parameter [%s]', nodeid(node)) # Set both from image data w = iw * inch / xdpi h = ih * inch / ydpi # Apply scale factor w = w * scale h = h * scale # And now we have this probably completely bogus size! log.info("Image %s size calculated: %fcm by %fcm [%s]", imgname, w / cm, h / cm, nodeid(node)) return w, h, kind
def size_for_node(self, node, client): '''Given a docutils image node, returns the size the image should have in the PDF document, and what 'kind' of size that is. That involves lots of guesswork''' uri = str(node.get("uri")) if uri.split("://")[0].lower() not in ('http','ftp','https'): uri = os.path.join(client.basedir,uri) else: uri, _ = urllib.urlretrieve(uri) client.to_unlink.append(uri) srcinfo = client, uri # Extract all the information from the URI imgname, extension, options = self.split_uri(uri) if not os.path.isfile(imgname): imgname = missing scale = float(node.get('scale', 100))/100 size_known = False # Figuring out the size to display of an image is ... annoying. # If the user provides a size with a unit, it's simple, adjustUnits # will return it in points and we're done. # However, often the unit wil be "%" (specially if it's meant for # HTML originally. In which case, we will use a percentage of # the containing frame. # Find the image size in pixels: kind = 'direct' xdpi, ydpi = client.styles.def_dpi, client.styles.def_dpi extension = imgname.split('.')[-1].lower() if extension in ['svg','svgz'] and SVGImage.available(): iw, ih = SVGImage(imgname, srcinfo=srcinfo).wrap(0, 0) # These are in pt, so convert to px iw = iw * xdpi / 72 ih = ih * ydpi / 72 elif extension in [ "ai", "ccx", "cdr", "cgm", "cmx", "sk1", "sk", "xml", "wmf", "fig"] and VectorImage.available(): iw, ih = VectorImage(imgname, srcinfo=srcinfo).wrap(0, 0) # These are in pt, so convert to px iw = iw * xdpi / 72 ih = ih * ydpi / 72 elif extension == 'pdf': if VectorPdf is not None: box = VectorPdf.load_xobj(srcinfo).BBox else: pdf = LazyImports.pdfinfo if pdf is None: log.warning('PDF images are not supported without pyPdf or pdfrw [%s]', nodeid(node)) return 0, 0, 'direct' reader = pdf.PdfFileReader(open(imgname, 'rb')) box = [float(x) for x in reader.getPage(0)['/MediaBox']] x1, y1, x2, y2 = box # These are in pt, so convert to px iw = float((x2-x1) * xdpi / 72) ih = float((y2-y1) * ydpi / 72) size_known = True # Assume size from original PDF is OK else: keeptrying = True if sys.platform[0:4] == 'java': try: from javax.imageio import ImageIO from java.io import File iis = ImageIO.createImageInputStream(File(imgname)) readers = ImageIO.getImageReaders(iis) if readers.hasNext(): reader = readers.next() reader.setInput(iis, True) metadata = reader.getImageMetadata(0) iw = reader.getWidth(0) ih = reader.getHeight(0) xdpi = None ydpi = None if metadata.getNativeMetadataFormatName() == 'javax_imageio_png_1.0': png_metadata = metadata.getAsTree(metadata.getNativeMetadataFormatName()) if png_metadata is not None: phys_metadata = png_metadata.getElementsByTagName('pHYs') if phys_metadata.getLength() == 1: xdpi = phys_metadata.item(0).getAttribute('pixelsPerUnitXAxis') if xdpi is not None: xdpi = float(xdpi) ydpi = phys_metadata.item(0).getAttribute('pixelsPerUnitYAxis') if ydpi is not None: ydpi = float(ydpi) elif metadata.getNativeMetadataFormatName() == 'javax_imageio_jpeg_image_1.0': jpg_metadata = metadata.getAsTree(metadata.getNativeMetadataFormatName()) if jpg_metadata is not None: jfif_metadata = jpg_metadata.getElementsByTagName('app0JFIF') if jfif_metadata.getLength() == 1: resUnits = jfif_metadata.item(0).getAttribute('resUnits') # 0 = plain aspect ratio, 1 = dots per inch, 2 = dots per cm if resUnits is not None and (resUnits == '1' or resUnits == '2'): xdpi = jfif_metadata.item(0).getAttribute('pixelsPerUnitXAxis') if xdpi is not None: xdpi = float(xdpi) if resUnits == '2': xdpi = xdpi * 2.54 ydpi = jfif_metadata.item(0).getAttribute('pixelsPerUnitYAxis') if ydpi is not None: ydpi = float(ydpi) if resUnits == '2': ydpi = ydpi * 2.54 if xdpi is None: xdpi = 300 if ydpi is None: ydpi = 300 keeptrying = False except Exception, err: log.error('Error %s', str(err)) pass if LazyImports.PILImage: try: img = LazyImports.PILImage.open(imgname) img.load() iw, ih = img.size xdpi, ydpi = img.info.get('dpi', (xdpi, ydpi)) keeptrying = False except IOError: # PIL throws this when it's a broken/unknown image pass if keeptrying and LazyImports.PMImage: img = LazyImports.PMImage(imgname) iw = img.size().width() ih = img.size().height() density=img.density() # The density is in pixelspercentimeter (!?) xdpi=density.width()*2.54 ydpi=density.height()*2.54 keeptrying = False if keeptrying: if extension not in ['jpg', 'jpeg']: log.error("The image (%s, %s) is broken or in an unknown format" , imgname, nodeid(node)) raise ValueError else: # Can be handled by reportlab log.warning("Can't figure out size of the image (%s, %s). Install PIL for better results." , imgname, nodeid(node)) iw = 1000 ih = 1000
# If it fails, assume a DPI of 300, which is pretty much made up, # and then a 100% size would be iw*inch/300, so we pass # that as the second parameter to adjustUnits # # Some say the default DPI should be 72. That would mean # the largest printable image in A4 paper would be something # like 480x640. That would be awful. # w = node.get('width') h = node.get('height') if h is None and w is None: # Nothing specified # Guess from iw, ih log.debug("Using image %s without specifying size." "Calculating based on image size at %ddpi [%s]", imgname, xdpi, nodeid(node)) w = iw*inch/xdpi h = ih*inch/ydpi elif w is not None: # Node specifies only w # In this particular case, we want the default unit # to be pixels so we work like rst2html if w[-1] == '%': kind = 'percentage_of_container' w=int(w[:-1]) else: # This uses default DPI setting because we # are not using the image's "natural size" # this is what LaTeX does, according to the # docutils mailing list discussion w = client.styles.adjustUnits(w, client.styles.tw,
def size_for_node(self, node, client): '''Given a docutils image node, returns the size the image should have in the PDF document, and what 'kind' of size that is. That involves lots of guesswork''' uri = str(node.get("uri")) if uri.split("://")[0].lower() not in ('http','ftp','https'): uri = os.path.join(client.basedir,uri) else: uri, _ = urllib.urlretrieve(uri) client.to_unlink.append(uri) srcinfo = client, uri # Extract all the information from the URI imgname, extension, options = self.split_uri(uri) if not os.path.isfile(imgname): imgname = missing scale = float(node.get('scale', 100))/100 size_known = False # Figuring out the size to display of an image is ... annoying. # If the user provides a size with a unit, it's simple, adjustUnits # will return it in points and we're done. # However, often the unit wil be "%" (specially if it's meant for # HTML originally. In which case, we will use a percentage of # the containing frame. # Find the image size in pixels: kind = 'direct' xdpi, ydpi = client.styles.def_dpi, client.styles.def_dpi extension = imgname.split('.')[-1].lower() if extension in ['svg','svgz'] and SVGImage.available(): iw, ih = SVGImage(imgname, srcinfo=srcinfo).wrap(0, 0) # These are in pt, so convert to px iw = iw * xdpi / 72 ih = ih * ydpi / 72 elif extension in [ "ai", "ccx", "cdr", "cgm", "cmx", "sk1", "sk", "xml", "wmf", "fig"] and VectorImage.available(): iw, ih = VectorImage(imgname, srcinfo=srcinfo).wrap(0, 0) # These are in pt, so convert to px iw = iw * xdpi / 72 ih = ih * ydpi / 72 elif extension == 'pdf': if VectorPdf is not None: box = VectorPdf.load_xobj(srcinfo).BBox else: pdf = LazyImports.pdfinfo if pdf is None: log.warning('PDF images are not supported without pyPdf or pdfrw [%s]', nodeid(node)) return 0, 0, 'direct' reader = pdf.PdfFileReader(open(imgname, 'rb')) box = [float(x) for x in reader.getPage(0)['/MediaBox']] x1, y1, x2, y2 = box # These are in pt, so convert to px iw = float((x2-x1) * xdpi / 72) ih = float((y2-y1) * ydpi / 72) size_known = True # Assume size from original PDF is OK else: keeptrying = True if LazyImports.PILImage: try: img = LazyImports.PILImage.open(imgname) img.load() iw, ih = img.size xdpi, ydpi = img.info.get('dpi', (xdpi, ydpi)) keeptrying = False except IOError: # PIL throws this when it's a broken/unknown image pass if keeptrying and LazyImports.PMImage: img = LazyImports.PMImage(imgname) iw = img.size().width() ih = img.size().height() density=img.density() # The density is in pixelspercentimeter (!?) xdpi=density.width()*2.54 ydpi=density.height()*2.54 keeptrying = False if keeptrying: if extension not in ['jpg', 'jpeg']: log.error("The image (%s, %s) is broken or in an unknown format" , imgname, nodeid(node)) raise ValueError else: # Can be handled by reportlab log.warning("Can't figure out size of the image (%s, %s). Install PIL for better results." , imgname, nodeid(node)) iw = 1000 ih = 1000 # Try to get the print resolution from the image itself via PIL. # If it fails, assume a DPI of 300, which is pretty much made up, # and then a 100% size would be iw*inch/300, so we pass # that as the second parameter to adjustUnits # # Some say the default DPI should be 72. That would mean # the largest printable image in A4 paper would be something # like 480x640. That would be awful. # w = node.get('width') h = node.get('height') if h is None and w is None: # Nothing specified # Guess from iw, ih log.debug("Using image %s without specifying size." "Calculating based on image size at %ddpi [%s]", imgname, xdpi, nodeid(node)) w = iw*inch/xdpi h = ih*inch/ydpi elif w is not None: # Node specifies only w # In this particular case, we want the default unit # to be pixels so we work like rst2html if w[-1] == '%': kind = 'percentage_of_container' w=int(w[:-1]) else: # This uses default DPI setting because we # are not using the image's "natural size" # this is what LaTeX does, according to the # docutils mailing list discussion w = client.styles.adjustUnits(w, client.styles.tw, default_unit='px') if h is None: # h is set from w with right aspect ratio h = w*ih/iw else: h = client.styles.adjustUnits(h, ih*inch/ydpi, default_unit='px') elif h is not None and w is None: if h[-1] != '%': h = client.styles.adjustUnits(h, ih*inch/ydpi, default_unit='px') # w is set from h with right aspect ratio w = h*iw/ih else: log.error('Setting height as a percentage does **not** work. '\ 'ignoring height parameter [%s]', nodeid(node)) # Set both from image data w = iw*inch/xdpi h = ih*inch/ydpi # Apply scale factor w = w*scale h = h*scale # And now we have this probably completely bogus size! log.info("Image %s size calculated: %fcm by %fcm [%s]", imgname, w/cm, h/cm, nodeid(node)) return w, h, kind