コード例 #1
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))
コード例 #2
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))
コード例 #3
0
    def textdispatch(self, client, node, replaceEnt=True):
        self = self.findsubclass(node, 'textdispatch')
        pre, post = self.get_pre_post(client, node, replaceEnt)
        text = self.get_text(client, node, replaceEnt)
        text = pre + text + post

        try:
            log.debug("%s.textdispatch: %s" % (self.getclassname(self), text))
        except UnicodeDecodeError:
            pass

        text = self.apply_smartypants(text, client.smarty, node)
        node.pdftext = text
        return text
コード例 #4
0
    def textdispatch(self, client, node, replaceEnt=True):
        self = self.findsubclass(node, 'textdispatch')
        pre, post = self.get_pre_post(client, node, replaceEnt)
        text = self.get_text(client, node, replaceEnt)
        text = pre + text + post

        try:
            log.debug("%s.textdispatch: %s" % (self.getclassname(self), text))
        except UnicodeDecodeError:
            pass

        text = self.apply_smartypants(text, client.smarty, node)
        node.pdftext = text
        return text
コード例 #5
0
    def isSatisfied(self):
        if self._entries == self._lastEntries:
            log.debug('Table Of Contents is stable')
            return True
        else:
            if len(self._entries) != len(self._lastEntries):
                log.info('Number of items in TOC changed '\
                'from %d to %d, not satisfied' % \
                (len(self._lastEntries), len(self._entries)))
                return False

            log.info('TOC entries that moved in this pass:')
            for i in range(len(self._entries)):
                if self._entries[i] != self._lastEntries[i]:
                    log.info(str(self._entries[i]))
                    log.info(str(self._lastEntries[i]))
        return False
コード例 #6
0
    def isSatisfied(self):
        if self._entries == self._lastEntries:
            log.debug('Table Of Contents is stable')
            return True
        else:
            if len(self._entries) != len(self._lastEntries):
                log.info('Number of items in TOC changed '\
                'from %d to %d, not satisfied' % \
                (len(self._lastEntries), len(self._entries)))
                return False

            log.info('TOC entries that moved in this pass:')
            for i in range(len(self._entries)):
                if self._entries[i] != self._lastEntries[i]:
                    log.info(str(self._entries[i]))
                    log.info(str(self._lastEntries[i]))
        return False
コード例 #7
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", handlerinfo, 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
コード例 #8
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", handlerinfo, 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
コード例 #9
0
    def _classinit(cls):
        """
        This is called once the subclass has actually been created.

        For the base class, just add a dispatch dictionary
        """
        if cls._baseclass is None:
            cls.dispatchdict = {}
            return

        # for subclasses, instantiate them, and then add
        # the class to the dispatch dictionary for each of its targets.
        self = cls()
        for target in cls._targets:
            if cls.dispatchdict.setdefault(target, self) is not self:
                t = repr(target)
                old = repr(cls.dispatchdict[target])
                new = repr(self)
                log.debug('Dispatch handler %s for node type %s overridden by %s' %
                    (old, t, new))
                cls.dispatchdict[target] = self
コード例 #10
0
    def _classinit(cls):
        """
        This is called once the subclass has actually been created.

        For the base class, just add a dispatch dictionary
        """
        if cls._baseclass is None:
            cls.dispatchdict = {}
            return

        # for subclasses, instantiate them, and then add
        # the class to the dispatch dictionary for each of its targets.
        self = cls()
        for target in cls._targets:
            if cls.dispatchdict.setdefault(target, self) is not self:
                t = repr(target)
                old = repr(cls.dispatchdict[target])
                new = repr(self)
                log.debug(
                    'Dispatch handler %s for node type %s overridden by %s' %
                    (old, t, new))
                cls.dispatchdict[target] = self
コード例 #11
0
    def split(self, w, h):
        _w, _h = self.wrap(w, h)

        if _h > h:  # Can't split!
            # The right column data mandates the split
            # Find which flowable exceeds the available height

            dw = self.colWidths[0] + self.padding[1] + self.padding[3]
            dh = self.padding[0] + self.padding[2]

            bullet = self.data[0][0]
            text = self.data[0][1]
            for l in range(0, len(text)):
                _, fh = _listWrapOn(text[:l + 1], w - dw, None)
                if fh + dh > h:
                    # The lth flowable is the guilty one
                    # split it

                    _, lh = _listWrapOn(text[:l], w - dw, None)
                    # Workaround for Issue 180
                    text[l].wrap(w - dw, h - lh - dh)
                    l2 = text[l].split(w - dw, h - lh - dh)
                    if l2 == []:  # Not splittable, push some to next page
                        if l == 0:  # Can't fit anything, push all to next page
                            return l2

                        # We reduce the number of items we keep on the
                        # page for two reasons:
                        #    1) If an item is associated with the following
                        #       item (getKeepWithNext() == True), we have
                        #       to back up to a previous one.
                        #    2) If we miscalculated the size required on
                        #       the first page (I dunno why, probably not
                        #       counting borders properly, but we do
                        #       miscalculate occasionally).  Seems to
                        #       have to do with nested tables, so it might
                        #       be the extra space on the border on the
                        #       inner table.

                        while l > 0:
                            if not text[l - 1].getKeepWithNext():
                                first_t = Table([[bullet, text[:l]]],
                                                colWidths=self.colWidths,
                                                style=self.style)
                                _w, _h = first_t.wrap(w, h)
                                if _h <= h:
                                    break
                            l -= 1

                        if l > 0:
                            # Workaround for Issue 180 with wordaxe:
                            # if wordaxe is not None:
                            # l3=[Table([
                            # [bullet,
                            # text[:l]]
                            # ],
                            # colWidths=self.colWidths,
                            # style=self.style),
                            # Table([['',text[l:]]],
                            # colWidths=self.colWidths,
                            # style=self.style)]
                            # else:
                            l3 = [
                                first_t,
                                SplitTable([['', text[l:]]],
                                           colWidths=self.colWidths,
                                           style=self.style,
                                           padding=self.padding)
                            ]
                        else:  # Everything flows
                            l3 = []
                    else:
                        l3 = [
                            Table([[bullet, text[:l] + [l2[0]]]],
                                  colWidths=self.colWidths,
                                  rowHeights=[h],
                                  style=self.style)
                        ]
                        if l2[1:] + text[l + 1:]:
                            # # Workaround for Issue 180 with wordaxe:
                            # if wordaxe is not None:
                            # l3.append(
                            # Table([['',l2[1:]+text[l+1:]]],
                            # colWidths=self.colWidths,
                            # style=self.style))
                            # else:
                            l3.append(
                                SplitTable([['', l2[1:] + text[l + 1:]]],
                                           colWidths=self.colWidths,
                                           style=self.style,
                                           padding=self.padding))
                    return l3
            log.debug("Can't split splittable")
            return self.t.split(w, h)
        else:
            return DelayedTable.split(self, w, h)
コード例 #12
0
ファイル: image.py プロジェクト: aquavitae/rst2pdf-py3-dev
    def size_for_node(self, node, client):
        """
        Given a docutils image node, return 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.request.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

        # 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']:
            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 == 'pdf':
            if VectorPdf is not None:
                xobj = VectorPdf.load_xobj(srcinfo)
                iw, ih = xobj.w, xobj.h
            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']]
                iw, ih = x2 - x1, y2 - y1
            # These are in pt, so convert to px
            iw = iw * xdpi / 72.0
            ih = ih * ydpi / 72.0

        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
コード例 #13
0
    def size_for_node(self, node, client):
        """
        Given a docutils image node, return 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.request.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

        # 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']:
            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 == 'pdf':
            if VectorPdf is not None:
                xobj = VectorPdf.load_xobj(srcinfo)
                iw, ih = xobj.w, xobj.h
            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']]
                iw, ih = x2 - x1, y2 - y1
            # These are in pt, so convert to px
            iw = iw * xdpi / 72.0
            ih = ih * ydpi / 72.0

        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
コード例 #14
0
    def split(self, w, h):
        _w, _h = self.wrap(w, h)

        if _h > h:  # Can't split!
            # The right column data mandates the split
            # Find which flowable exceeds the available height

            dw = self.colWidths[0] + self.padding[1] + self.padding[3]
            dh = self.padding[0] + self.padding[2]

            bullet = self.data[0][0]
            text = self.data[0][1]
            for l in range(0, len(text)):
                _, fh = _listWrapOn(text[:l + 1], w - dw, None)
                if fh + dh > h:
                    # The lth flowable is the guilty one
                    # split it

                    _, lh = _listWrapOn(text[:l], w - dw, None)
                    # Workaround for Issue 180
                    text[l].wrap(w - dw, h - lh - dh)
                    l2 = text[l].split(w - dw, h - lh - dh)
                    if l2 == []:  # Not splittable, push some to next page
                        if l == 0:  # Can't fit anything, push all to next page
                            return l2

                        # We reduce the number of items we keep on the
                        # page for two reasons:
                        #    1) If an item is associated with the following
                        #       item (getKeepWithNext() == True), we have
                        #       to back up to a previous one.
                        #    2) If we miscalculated the size required on
                        #       the first page (I dunno why, probably not
                        #       counting borders properly, but we do
                        #       miscalculate occasionally).  Seems to
                        #       have to do with nested tables, so it might
                        #       be the extra space on the border on the
                        #       inner table.

                        while l > 0:
                            if not text[l - 1].getKeepWithNext():
                                first_t = Table(
                                    [[bullet, text[:l]]],
                                    colWidths=self.colWidths,
                                    style=self.style
                                )
                                _w, _h = first_t.wrap(w, h)
                                if _h <= h:
                                    break
                            l -= 1

                        if l > 0:
                            # Workaround for Issue 180 with wordaxe:
                            # if wordaxe is not None:
                                # l3=[Table([
                                            # [bullet,
                                             # text[:l]]
                                           # ],
                                        # colWidths=self.colWidths,
                                        # style=self.style),
                                        # Table([['',text[l:]]],
                                        # colWidths=self.colWidths,
                                        # style=self.style)]
                            # else:
                            l3 = [
                                first_t,
                                SplitTable([['', text[l:]]],
                                colWidths=self.colWidths,
                                style=self.style,
                                padding=self.padding)
                            ]
                        else:  # Everything flows
                            l3 = []
                    else:
                        l3 = [Table(
                            [[bullet, text[:l] + [l2[0]]]],
                            colWidths=self.colWidths,
                            rowHeights=[h],
                            style=self.style
                        )]
                        if l2[1:] + text[l + 1:]:
                            # # Workaround for Issue 180 with wordaxe:
                            # if wordaxe is not None:
                                # l3.append(
                                    # Table([['',l2[1:]+text[l+1:]]],
                                    # colWidths=self.colWidths,
                                    # style=self.style))
                            # else:
                            l3.append(SplitTable(
                                [['', l2[1:] + text[l + 1:]]],
                                colWidths=self.colWidths,
                                style=self.style,
                                padding=self.padding
                            ))
                    return l3
            log.debug("Can't split splittable")
            return self.t.split(w, h)
        else:
            return DelayedTable.split(self, w, h)