Example #1
0
 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 []
Example #2
0
 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 []
Example #3
0
 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 []
Example #4
0
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))
Example #6
0
 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
Example #8
0
File: utils.py Project: bemre/cdap
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
Example #9
0
    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
Example #10
0
    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
Example #11
0
    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
Example #12
0
    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
Example #13
0
    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
Example #14
0
        # 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