Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SvgImage(Flowable) or SvgReader class that provides convenience functions to scale or wrap the image to a specified space using reportlab.platypus? #69

Open
skidzo opened this issue Jan 23, 2017 · 2 comments

Comments

@skidzo
Copy link

skidzo commented Jan 23, 2017

Something like this would be nice for a future release:

SvgImage(Flowable):
    def __init__(self,fname)
        pass
    def drawOn(self, canv, x, y, _sW=0):
        pass

Maybe it is sufficient to just provide a SvgReader() class, that gives the freedom to implement this in a flexible way...

The wrap() can be overloaded, whereas the wrapOn() method should not be touched.

I found an example somewhere that explains what it could look like, only that this shows how to embed a PDF file:

from reportlab.platypus import Flowable
from pdfrw import PdfReader,PdfDict
from pdfrw.buildxobj import pagexobj
from pdfrw.toreportlab import makerl

class PdfAsset(Flowable):
    def __init__(self,fname,width=None,height=None,kind='direct'):

        self.page = PdfReader(fname=fname, decompress=False).pages[0]
        self.xobj = pagexobj(self.page)

        self.imageWidth = width
        self.imageHeight = height
        x1, y1, x2, y2 = self.xobj.BBox

        self._w, self._h = x2 - x1, y2 - y1
        if not self.imageWidth:
            self.imageWidth = self._w
        if not self.imageHeight:
            self.imageHeight = self._h
        self.__ratio = float(self.imageWidth)/self.imageHeight
        if kind in ['direct','absolute'] or width==None or height==None:
            self.drawWidth = width or self.imageWidth
            self.drawHeight = height or self.imageHeight
        elif kind in ['bound','proportional']:
            factor = min(float(width)/self._w,float(height)/self._h)
            self.drawWidth = self._w*factor
            self.drawHeight = self._h*factor

    def wrap(self, width, height):
        return self.imageWidth, self.imageHeight

    def drawOn(self, canv, x, y, _sW=0):
        if _sW > 0 and hasattr(self, 'hAlign'):
            a = self.hAlign
            if a in ('CENTER', 'CENTRE', TA_CENTER):
                x += 0.5*_sW
            elif a in ('RIGHT', TA_RIGHT):
                x += _sW
            elif a not in ('LEFT', TA_LEFT):
                raise ValueError("Bad hAlign value " + str(a))
        canv.saveState()
        img = self.xobj
        if isinstance(img, PdfDict):
            xscale = self.imageWidth / img.BBox[2]
            yscale = self.imageHeight / img.BBox[3]
            canv.translate(x, y)
            canv.scale(xscale, yscale)
            canv.doForm(makerl(canv, img))
        else:
            #canv.drawInlineImage(img, x, y-self.imageHeight, self.imageWidth, self.imageHeight)
            canv.drawImage(img, x, y, self.imageWidth, self.imageHeight)
        canv.restoreState()
@replabrobin
Copy link
Contributor

Not sure if this is what you want, but I think that the reportlab.lib.utils.ImageReader class now accepts drawings as inputs so any svglib drawing can be used as an image. In any case drawings were already flowables so can be added to a story.

@skidzo
Copy link
Author

skidzo commented Feb 20, 2017

Well that's partly because I don't really know what I want, I just looked at Image Reader "Wraps up either PIL or Java to get data from bitmaps" class in my open source version=3.3.0, and there is no such fancy drawing acceptance as you described. I don't have any Problem to add a drawing to the "story", I was just thinking that it would be fancy to have a possibility to have my own SvgImage class that accepts a file or file like object as Input and where I can implement what it's drawOn method would do.

Without having to (re)write a lot of code, this seems to be impossible, using reportlab and svglib...

for now I have found that this function is needed to (re)scale a drawing returned from svg2rlg


def scaleDrawing(drawing,factor,showBoundary=False):
    """
    scale a reportlab.graphics.shapes.Drawing() object, 
    leaving its aspect ratio unchanged
    """
    sx=sy=factor
    drawing.width,drawing.height = drawing.minWidth()*sx, drawing.height*sy
    drawing.scale(sx,sy)
    if showBoundary:
        drawing._showBoundary = True
    
    return drawing

@skidzo skidzo changed the title SvgImage(Flowable) or SvgReader class that provides a convenience functions to scale or wrap the image to a specified space using reportlab.platypus? SvgImage(Flowable) or SvgReader class that provides convenience functions to scale or wrap the image to a specified space using reportlab.platypus? Feb 20, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants