[ Avaa Bypassed ]




Upload:

Command:

www-data@18.188.0.144: ~ $
#Copyright ReportLab Europe Ltd. 2000-2017
#see license.txt for license details
#history https://hg.reportlab.com/hg-public/reportlab/log/tip/src/reportlab/graphics/renderPS.py
__version__='3.3.0'
__doc__="""Render drawing objects in Postscript"""

from reportlab.pdfbase.pdfmetrics import getFont, stringWidth, unicode2T1 # for font info
from reportlab.lib.utils import getBytesIO, getStringIO, asBytes, char2int, rawBytes, asNative, isUnicode
from reportlab.lib.rl_accel import fp_str
from reportlab.lib.colors import black
from reportlab.graphics.renderbase import Renderer, StateTracker, getStateDelta, renderScaledDrawing
from reportlab.graphics.shapes import STATE_DEFAULTS
import math
from operator import getitem
from reportlab import rl_config, xrange, ascii
from reportlab.pdfgen.canvas import FILL_EVEN_ODD, FILL_NON_ZERO
_ESCAPEDICT={}
for c in xrange(256):
    if c<32 or c>=127:
        _ESCAPEDICT[c]= '\\%03o' % c
    elif c in (ord('\\'),ord('('),ord(')')):
        _ESCAPEDICT[c] = '\\'+chr(c)
    else:
        _ESCAPEDICT[c] = chr(c)
del c

def _escape_and_limit(s):
    s = asBytes(s)
    R = []
    aR = R.append
    n = 0
    for c in s:
        c = _ESCAPEDICT[char2int(c)]
        aR(c)
        n += len(c)
        if n>=200:
            n = 0
            aR('\\\n')
    return ''.join(R)

# we need to create encoding vectors for each font we use, or they will
 # come out in Adobe's old StandardEncoding, which NOBODY uses.
PS_WinAnsiEncoding="""
/RE { %def
  findfont begin
  currentdict dup length dict begin
 { %forall
   1 index /FID ne { def } { pop pop } ifelse
 } forall
 /FontName exch def dup length 0 ne { %if
   /Encoding Encoding 256 array copy def
   0 exch { %forall
     dup type /nametype eq { %ifelse
       Encoding 2 index 2 index put
       pop 1 add
     }{ %else
       exch pop
     } ifelse
   } forall
 } if pop
  currentdict dup end end
  /FontName get exch definefont pop
} bind def

/WinAnsiEncoding [
  39/quotesingle 96/grave 128/euro 130/quotesinglbase/florin/quotedblbase
  /ellipsis/dagger/daggerdbl/circumflex/perthousand
  /Scaron/guilsinglleft/OE 145/quoteleft/quoteright
  /quotedblleft/quotedblright/bullet/endash/emdash
  /tilde/trademark/scaron/guilsinglright/oe/dotlessi
  159/Ydieresis 164/currency 166/brokenbar 168/dieresis/copyright
  /ordfeminine 172/logicalnot 174/registered/macron/ring
  177/plusminus/twosuperior/threesuperior/acute/mu
  183/periodcentered/cedilla/onesuperior/ordmasculine
  188/onequarter/onehalf/threequarters 192/Agrave/Aacute
  /Acircumflex/Atilde/Adieresis/Aring/AE/Ccedilla
  /Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute
  /Icircumflex/Idieresis/Eth/Ntilde/Ograve/Oacute
  /Ocircumflex/Otilde/Odieresis/multiply/Oslash
  /Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn
  /germandbls/agrave/aacute/acircumflex/atilde/adieresis
  /aring/ae/ccedilla/egrave/eacute/ecircumflex
  /edieresis/igrave/iacute/icircumflex/idieresis
  /eth/ntilde/ograve/oacute/ocircumflex/otilde
  /odieresis/divide/oslash/ugrave/uacute/ucircumflex
  /udieresis/yacute/thorn/ydieresis
] def
"""

class PSCanvas:
    def __init__(self,size=(300,300), PostScriptLevel=2):
        self.width, self.height = size
        xtraState = []
        self._xtraState_push = xtraState.append
        self._xtraState_pop = xtraState.pop
        self.comments = 0
        self.code = []
        self.code_append = self.code.append
        self._sep = '\n'
        self._strokeColor = self._fillColor = self._lineWidth = \
            self._font = self._fontSize = self._lineCap = \
            self._lineJoin = self._color = None

        self._fontsUsed =   [] # track them as we go
        self.setFont(STATE_DEFAULTS['fontName'],STATE_DEFAULTS['fontSize'])
        self.setStrokeColor(STATE_DEFAULTS['strokeColor'])
        self.setLineCap(2)
        self.setLineJoin(0)
        self.setLineWidth(1)
        self.PostScriptLevel=PostScriptLevel
        self._fillMode = FILL_EVEN_ODD

    def comment(self,msg):
        if self.comments: self.code_append('%'+msg)

    def drawImage(self, image, x1,y1, width=None,height=None): # Postscript Level2 version
        # select between postscript level 1 or level 2
        if self.PostScriptLevel==1:
            self._drawImageLevel1(image, x1,y1, width, height)
        elif self.PostScriptLevel==2:
            self._drawImageLevel2(image, x1, y1, width, height)
        else :
            raise ValueError('Unsupported Postscript Level %s' % self.PostScriptLevel)

    def clear(self):
        self.code_append('showpage') # ugh, this makes no sense oh well.

    def _t1_re_encode(self):
        if not self._fontsUsed: return
        # for each font used, reencode the vectors
        C = []
        for fontName in self._fontsUsed:
            fontObj = getFont(fontName)
            if not fontObj._dynamicFont and fontObj.encName=='WinAnsiEncoding':
                C.append('WinAnsiEncoding /%s /%s RE' % (fontName, fontName))
        if C:
            C.insert(0,PS_WinAnsiEncoding)
            self.code.insert(1, self._sep.join(C))

    def save(self,f=None):
        if not hasattr(f,'write'):
            _f = open(f,'wb')
        else:
            _f = f
        if self.code[-1]!='showpage': self.clear()
        self.code.insert(0,'''\
%%!PS-Adobe-3.0 EPSF-3.0
%%%%BoundingBox: 0 0 %d %d
%%%% Initialization:
/m {moveto} bind def
/l {lineto} bind def
/c {curveto} bind def
''' % (self.width,self.height))

        self._t1_re_encode()
        _f.write(rawBytes(self._sep.join(self.code)))
        if _f is not f:
            _f.close()
            from reportlab.lib.utils import markfilename
            markfilename(f,creatorcode='XPR3',filetype='EPSF')

    def saveState(self):
        self._xtraState_push((self._fontCodeLoc,))
        self.code_append('gsave')

    def restoreState(self):
        self.code_append('grestore')
        self._fontCodeLoc, = self._xtraState_pop()

    def stringWidth(self, s, font=None, fontSize=None):
        """Return the logical width of the string if it were drawn
        in the current font (defaults to self.font)."""
        font = font or self._font
        fontSize = fontSize or self._fontSize
        return stringWidth(s, font, fontSize)

    def setLineCap(self,v):
        if self._lineCap!=v:
            self._lineCap = v
            self.code_append('%d setlinecap'%v)

    def setLineJoin(self,v):
        if self._lineJoin!=v:
            self._lineJoin = v
            self.code_append('%d setlinejoin'%v)

    def setDash(self, array=[], phase=0):
        """Two notations.  pass two numbers, or an array and phase"""
        # copied and modified from reportlab.canvas
        psoperation = "setdash"
        if isinstance(array,(float,int)):
            self.code_append('[%s %s] 0 %s' % (array, phase, psoperation))
        elif isinstance(array,(tuple,list)):
            assert phase >= 0, "phase is a length in user space"
            textarray = ' '.join(map(str, array))
            self.code_append('[%s] %s %s' % (textarray, phase, psoperation))

    def setStrokeColor(self, color):
        self._strokeColor = color
        self.setColor(color)

    def setColor(self, color):
        if self._color!=color:
            self._color = color
            if color:
                if hasattr(color, "cyan"):
                    self.code_append('%s setcmykcolor' % fp_str(color.cyan, color.magenta, color.yellow, color.black))
                else:
                    self.code_append('%s setrgbcolor' % fp_str(color.red, color.green, color.blue))

    def setFillColor(self, color):
        self._fillColor = color
        self.setColor(color)

    def setFillMode(self, v):
        self._fillMode = v

    def setLineWidth(self, width):
        if width != self._lineWidth:
            self._lineWidth = width
            self.code_append('%s setlinewidth' % width)

    def setFont(self,font,fontSize,leading=None):
        if self._font!=font or self._fontSize!=fontSize:
            self._fontCodeLoc = len(self.code)
            self._font = font
            self._fontSize = fontSize
            self.code_append('')

    def line(self, x1, y1, x2, y2):
        if self._strokeColor != None:
            self.setColor(self._strokeColor)
            self.code_append('%s m %s l stroke' % (fp_str(x1, y1), fp_str(x2, y2)))

    def _escape(self, s):
        '''
        return a copy of string s with special characters in postscript strings
        escaped with backslashes.
        '''
        try:
            return _escape_and_limit(s)
        except:
            raise ValueError("cannot escape %s" % ascii(s))

    def _issueT1String(self,fontObj,x,y,s):
        fc = fontObj
        code_append = self.code_append
        fontSize = self._fontSize
        fontsUsed = self._fontsUsed
        escape = self._escape
        if not isUnicode(s):
            try:
                s = s.decode('utf8')
            except UnicodeDecodeError as e:
                i,j = e.args[2:4]
                raise UnicodeDecodeError(*(e.args[:4]+('%s\n%s-->%s<--%s' % (e.args[4],s[i-10:i],s[i:j],s[j:j+10]),)))

        for f, t in unicode2T1(s,[fontObj]+fontObj.substitutionFonts):
            if f!=fc:
                psName = asNative(f.face.name)
                code_append('(%s) findfont %s scalefont setfont' % (psName,fp_str(fontSize)))
                if psName not in fontsUsed:
                    fontsUsed.append(psName)
                fc = f
            code_append('%s m (%s) show ' % (fp_str(x,y),escape(t)))
            x += f.stringWidth(t.decode(f.encName),fontSize)
        if fontObj!=fc:
            self._font = None
            self.setFont(fontObj.face.name,fontSize)

    def drawString(self, x, y, s, angle=0):
        if self._fillColor != None:
            fontObj = getFont(self._font)
            if not self.code[self._fontCodeLoc]:
                psName = asNative(fontObj.face.name)
                self.code[self._fontCodeLoc]='(%s) findfont %s scalefont setfont' % (psName,fp_str(self._fontSize))
                if psName not in self._fontsUsed:
                    self._fontsUsed.append(psName)
            self.setColor(self._fillColor)
            if angle!=0:
                self.code_append('gsave %s translate %s rotate' % (fp_str(x,y),fp_str(angle)))
                x = y = 0
            if fontObj._dynamicFont:
                s = self._escape(s)
                self.code_append('%s m (%s) show ' % (fp_str(x,y),s))
            else:
                self._issueT1String(fontObj,x,y,s)
            if angle!=0:
                self.code_append('grestore')

    def drawCentredString(self, x, y, text, text_anchor='middle'):
        if self._fillColor is not None:
            textLen = stringWidth(text, self._font,self._fontSize)
            if text_anchor=='end':
                x -= textLen
            elif text_anchor=='middle':
                x -= textLen/2.
            elif text_anchor=='numeric':
                x -= numericXShift(text_anchor,text,textLen,self._font,self._fontSize)
            self.drawString(x,y,text)

    def drawRightString(self, text, x, y):
        self.drawCentredString(text,x,y,text_anchor='end')

    def drawCurve(self, x1, y1, x2, y2, x3, y3, x4, y4, closed=0):
        codeline = '%s m %s curveto'
        data = (fp_str(x1, y1), fp_str(x2, y2, x3, y3, x4, y4))
        if self._fillColor != None:
            self.setColor(self._fillColor)
            self.code_append((codeline % data) + ' eofill')
        if self._strokeColor != None:
            self.setColor(self._strokeColor)
            self.code_append((codeline % data)
                            + ((closed and ' closepath') or '')
                            + ' stroke')

    ########################################################################################

    def rect(self, x1,y1, x2,y2, stroke=1, fill=1):
        "Draw a rectangle between x1,y1, and x2,y2"
        # Path is drawn in counter-clockwise direction"

        x1, x2 = min(x1,x2), max(x1, x2) # from piddle.py
        y1, y2 = min(y1,y2), max(y1, y2)
        self.polygon(((x1,y1),(x2,y1),(x2,y2),(x1,y2)), closed=1, stroke=stroke, fill = fill)

    def roundRect(self, x1,y1, x2,y2, rx=8, ry=8):
        """Draw a rounded rectangle between x1,y1, and x2,y2,
        with corners inset as ellipses with x radius rx and y radius ry.
        These should have x1<x2, y1<y2, rx>0, and ry>0."""
        # Path is drawn in counter-clockwise direction

        x1, x2 = min(x1,x2), max(x1, x2) # from piddle.py
        y1, y2 = min(y1,y2), max(y1, y2)

        # Note: arcto command draws a line from current point to beginning of arc
        # save current matrix, translate to center of ellipse, scale by rx ry, and draw
        # a circle of unit radius in counterclockwise dir, return to original matrix
        # arguments are (cx, cy, rx, ry, startAngle, endAngle)
        ellipsePath = 'matrix currentmatrix %s %s translate %s %s scale 0 0 1 %s %s arc setmatrix'

        # choice between newpath and moveTo beginning of arc
        # go with newpath for precision, does this violate any assumptions in code???
        rr = ['newpath'] # Round Rect code path
        a = rr.append
        # upper left corner ellipse is first
        a(ellipsePath % (x1+rx, y1+ry, rx, -ry, 90, 180))
        a(ellipsePath % (x1+rx, y2-ry, rx, -ry, 180, 270))
        a(ellipsePath % (x2-rx, y2-ry, rx, -ry, 270, 360))
        a(ellipsePath % (x2-rx, y1+ry, rx, -ry, 0,  90) )
        a('closepath')

        self._fillAndStroke(rr)

    def ellipse(self, x1,y1, x2,y2):
        """Draw an orthogonal ellipse inscribed within the rectangle x1,y1,x2,y2.
        These should have x1<x2 and y1<y2."""
        #Just invoke drawArc to actually draw the ellipse
        self.drawArc(x1,y1, x2,y2)

    def circle(self, xc, yc, r):
        self.ellipse(xc-r,yc-r, xc+r,yc+r)

    def drawArc(self, x1,y1, x2,y2, startAng=0, extent=360, fromcenter=0):
        """Draw a partial ellipse inscribed within the rectangle x1,y1,x2,y2,
        starting at startAng degrees and covering extent degrees.   Angles
        start with 0 to the right (+x) and increase counter-clockwise.
        These should have x1<x2 and y1<y2."""
        #calculate centre of ellipse
        #print "x1,y1,x2,y2,startAng,extent,fromcenter", x1,y1,x2,y2,startAng,extent,fromcenter
        cx, cy = (x1+x2)/2.0, (y1+y2)/2.0
        rx, ry = (x2-x1)/2.0, (y2-y1)/2.0

        codeline = self._genArcCode(x1, y1, x2, y2, startAng, extent)

        startAngleRadians = math.pi*startAng/180.0
        extentRadians = math.pi*extent/180.0
        endAngleRadians = startAngleRadians + extentRadians

        codelineAppended = 0

        # fill portion

        if self._fillColor != None:
            self.setColor(self._fillColor)
            self.code_append(codeline)
            codelineAppended = 1
            if self._strokeColor!=None: self.code_append('gsave')
            self.lineTo(cx,cy)
            self.code_append('eofill')
            if self._strokeColor!=None: self.code_append('grestore')

        # stroke portion
        if self._strokeColor != None:
            # this is a bit hacked up.  There is certainly a better way...
            self.setColor(self._strokeColor)
            (startx, starty) = (cx+rx*math.cos(startAngleRadians), cy+ry*math.sin(startAngleRadians))
            if not codelineAppended:
                self.code_append(codeline)
            if fromcenter:
                # move to center
                self.lineTo(cx,cy)
                self.lineTo(startx, starty)
                self.code_append('closepath')
            self.code_append('stroke')

    def _genArcCode(self, x1, y1, x2, y2, startAng, extent):
        "Calculate the path for an arc inscribed in rectangle defined by (x1,y1),(x2,y2)"
        #calculate semi-minor and semi-major axes of ellipse
        xScale = abs((x2-x1)/2.0)
        yScale = abs((y2-y1)/2.0)
        #calculate centre of ellipse
        x, y = (x1+x2)/2.0, (y1+y2)/2.0

        codeline = 'matrix currentmatrix %s %s translate %s %s scale 0 0 1 %s %s %s setmatrix'

        if extent >= 0:
            arc='arc'
        else:
            arc='arcn'
        data = (x,y, xScale, yScale, startAng, startAng+extent, arc)

        return codeline % data

    def polygon(self, p, closed=0, stroke=1, fill=1):
        assert len(p) >= 2, 'Polygon must have 2 or more points'

        start = p[0]
        p = p[1:]

        poly = []
        a = poly.append
        a("%s m" % fp_str(start))
        for point in p:
            a("%s l" % fp_str(point))
        if closed:
            a("closepath")

        self._fillAndStroke(poly,stroke=stroke,fill=fill)

    def lines(self, lineList, color=None, width=None):
        if self._strokeColor != None:
            self._setColor(self._strokeColor)
            codeline = '%s m %s l stroke'
            for line in lineList:
                self.code_append(codeline % (fp_str(line[0]),fp_str(line[1])))

    def moveTo(self,x,y):
        self.code_append('%s m' % fp_str(x, y))

    def lineTo(self,x,y):
        self.code_append('%s l' % fp_str(x, y))

    def curveTo(self,x1,y1,x2,y2,x3,y3):
        self.code_append('%s c' % fp_str(x1,y1,x2,y2,x3,y3))

    def closePath(self):
        self.code_append('closepath')

    def polyLine(self, p):
        assert len(p) >= 1, 'Polyline must have 1 or more points'
        if self._strokeColor != None:
            self.setColor(self._strokeColor)
            self.moveTo(p[0][0], p[0][1])
            for t in p[1:]:
                self.lineTo(t[0], t[1])
            self.code_append('stroke')

    def drawFigure(self, partList, closed=0):
        figureCode = []
        a = figureCode.append
        first = 1

        for part in partList:
            op = part[0]
            args = list(part[1:])

            if op == figureLine:
                if first:
                    first = 0
                    a("%s m" % fp_str(args[:2]))
                else:
                    a("%s l" % fp_str(args[:2]))
                a("%s l" % fp_str(args[2:]))

            elif op == figureArc:
                first = 0
                x1,y1,x2,y2,startAngle,extent = args[:6]
                a(self._genArcCode(x1,y1,x2,y2,startAngle,extent))

            elif op == figureCurve:
                if first:
                    first = 0
                    a("%s m" % fp_str(args[:2]))
                else:
                    a("%s l" % fp_str(args[:2]))
                a("%s curveto" % fp_str(args[2:]))
            else:
                raise TypeError("unknown figure operator: "+op)

        if closed:
            a("closepath")
        self._fillAndStroke(figureCode)

    def _fillAndStroke(self,code,clip=0,fill=1,stroke=1,fillMode=None):
        fill = self._fillColor and fill
        stroke = self._strokeColor and stroke
        if fill or stroke or clip:
            self.code.extend(code)
            if fill:
                if fillMode is None:
                    fillMode = self._fillMode
                if stroke or clip: self.code_append("gsave")
                self.setColor(self._fillColor)
                self.code_append("eofill" if fillMode==FILL_EVEN_ODD else "fill")
                if stroke or clip: self.code_append("grestore")
            if stroke:
                if clip: self.code_append("gsave")
                self.setColor(self._strokeColor)
                self.code_append("stroke")
                if clip: self.code_append("grestore")
            if clip:
                self.code_append("clip")
                self.code_append("newpath")

    def translate(self,x,y):
        self.code_append('%s translate' % fp_str(x,y))

    def scale(self,x,y):
        self.code_append('%s scale' % fp_str(x,y))

    def transform(self,a,b,c,d,e,f):
        self.code_append('[%s] concat' % fp_str(a,b,c,d,e,f))

    def _drawTimeResize(self,w,h):
        '''if this is used we're probably in the wrong world'''
        self.width, self.height = w, h

    def _drawImageLevel1(self, image, x1, y1, width=None, height=None):
        # Postscript Level1 version available for fallback mode when Level2 doesn't work
        # For now let's start with 24 bit RGB images (following piddlePDF again)
        component_depth = 8
        myimage = image.convert('RGB')
        imgwidth, imgheight = myimage.size
        if not width:
            width = imgwidth
        if not height:
            height = imgheight
        #print 'Image size (%d, %d); Draw size (%d, %d)' % (imgwidth, imgheight, width, height)
        # now I need to tell postscript how big image is

        # "image operators assume that they receive sample data from
        # their data source in x-axis major index order.  The coordinate
        # of the lower-left corner of the first sample is (0,0), of the
        # second (1,0) and so on" -PS2 ref manual p. 215
        #
        # The ImageMatrix maps unit squre of user space to boundary of the source image
        #

        # The CurrentTransformationMatrix (CTM) maps the unit square of
        # user space to the rect...on the page that is to receive the
        # image. A common ImageMatrix is [width 0 0 -height 0 height]
        # (for a left to right, top to bottom image )

        # first let's map the user coordinates start at offset x1,y1 on page

        self.code.extend([
            'gsave',
            '%s %s translate' % (x1,y1), # need to start are lower left of image
            '%s %s scale' % (width,height),
            '/scanline %d 3 mul string def' % imgwidth  # scanline by multiples of image width
            ])

        # now push the dimensions and depth info onto the stack
        # and push the ImageMatrix to map the source to the target rectangle (see above)
        # finally specify source (PS2 pp. 225 ) and by exmample
        self.code.extend([
            '%s %s %s' % (imgwidth, imgheight, component_depth),
            '[%s %s %s %s %s %s]' % (imgwidth, 0, 0, -imgheight, 0, imgheight),
            '{ currentfile scanline readhexstring pop } false 3',
            'colorimage '
            ])

        # data source output--now we just need to deliver a hex encode
        # series of lines of the right overall size can follow
        # piddlePDF again
        rawimage = (myimage.tobytes if hasattr(myimage,'tobytes') else myimage.tostring)()
        hex_encoded = self._AsciiHexEncode(rawimage)

        # write in blocks of 78 chars per line
        outstream = getStringIO(hex_encoded)

        dataline = outstream.read(78)
        while dataline != "":
            self.code_append(dataline)
            dataline= outstream.read(78)
        self.code_append('% end of image data') # for clarity
        self.code_append('grestore') # return coordinates to normal

    # end of drawImage
    def _AsciiHexEncode(self, input):  # also based on piddlePDF
        "Helper function used by images"
        output = getStringIO()
        for char in asBytes(input):
            output.write('%02x' % char2int(char))
        return output.getvalue()

    def _drawImageLevel2(self, image, x1,y1, width=None,height=None): # Postscript Level2 version
        '''At present we're handling only PIL'''
        ### what sort of image are we to draw
        if image.mode=='L' :
            imBitsPerComponent = 8
            imNumComponents = 1
            myimage = image
        elif image.mode == '1':
            myimage = image.convert('L')
            imNumComponents = 1
            myimage = image
        else :
            myimage = image.convert('RGB')
            imNumComponents = 3
            imBitsPerComponent = 8

        imwidth, imheight = myimage.size
        if not width:
            width = imwidth
        if not height:
            height = imheight
        self.code.extend([
            'gsave',
            '%s %s translate' % (x1,y1), # need to start are lower left of image
            '%s %s scale' % (width,height)])

        if imNumComponents == 3 :
            self.code_append('/DeviceRGB setcolorspace')
        elif imNumComponents == 1 :
            self.code_append('/DeviceGray setcolorspace')
        # create the image dictionary
        self.code_append("""
<<
/ImageType 1
/Width %d /Height %d  %% dimensions of source image
/BitsPerComponent %d""" % (imwidth, imheight, imBitsPerComponent) )

        if imNumComponents == 1:
            self.code_append('/Decode [0 1]')
        if imNumComponents == 3:
            self.code_append('/Decode [0 1 0 1 0 1]  %% decode color values normally')

        self.code.extend([  '/ImageMatrix [%s 0 0 %s 0 %s]' % (imwidth, -imheight, imheight),
                            '/DataSource currentfile /ASCIIHexDecode filter',
                            '>> % End image dictionary',
                            'image'])
        # after image operator just need to dump image dat to file as hexstring
        rawimage = (myimage.tobytes if hasattr(myimage,'tobytes') else myimage.tostring)()
        hex_encoded = self._AsciiHexEncode(rawimage)

        # write in blocks of 78 chars per line
        outstream = getStringIO(hex_encoded)

        dataline = outstream.read(78)
        while dataline != "":
            self.code_append(dataline)
            dataline= outstream.read(78)
        self.code_append('> % end of image data') # > is EOD for hex encoded filterfor clarity
        self.code_append('grestore') # return coordinates to normal

# renderpdf - draws them onto a canvas
"""Usage:
    from reportlab.graphics import renderPS
    renderPS.draw(drawing, canvas, x, y)
Execute the script to see some test drawings."""
from reportlab.graphics.shapes import *

# hack so we only get warnings once each
#warnOnce = WarnOnce()

# the main entry point for users...
def draw(drawing, canvas, x=0, y=0, showBoundary=rl_config.showBoundary):
    """As it says"""
    R = _PSRenderer()
    R.draw(renderScaledDrawing(drawing), canvas, x, y, showBoundary=showBoundary)

def _pointsFromList(L):
    '''
    given a list of coordinates [x0, y0, x1, y1....]
    produce a list of points [(x0,y0), (y1,y0),....]
    '''
    P=[]
    a = P.append
    for i in range(0,len(L),2):
        a((L[i],L[i+1]))
    return P

class _PSRenderer(Renderer):
    """This draws onto a EPS document.  It needs to be a class
    rather than a function, as some EPS-specific state tracking is
    needed outside of the state info in the SVG model."""

    def drawNode(self, node):
        """This is the recursive method called for each node
        in the tree"""
        self._canvas.comment('begin node %r'%node)
        color = self._canvas._color
        if not (isinstance(node, Path) and node.isClipPath):
            self._canvas.saveState()

        #apply state changes
        deltas = getStateDelta(node)
        self._tracker.push(deltas)
        self.applyStateChanges(deltas, {})

        #draw the object, or recurse
        self.drawNodeDispatcher(node)

        rDeltas = self._tracker.pop()
        if not (isinstance(node, Path) and node.isClipPath):
            self._canvas.restoreState()
        self._canvas.comment('end node %r'%node)
        self._canvas._color = color

        #restore things we might have lost (without actually doing anything).
        for k, v in rDeltas.items():
            if k in self._restores:
                setattr(self._canvas,self._restores[k],v)

##  _restores = {'stroke':'_stroke','stroke_width': '_lineWidth','stroke_linecap':'_lineCap',
##              'stroke_linejoin':'_lineJoin','fill':'_fill','font_family':'_font',
##              'font_size':'_fontSize'}
    _restores = {'strokeColor':'_strokeColor','strokeWidth': '_lineWidth','strokeLineCap':'_lineCap',
                'strokeLineJoin':'_lineJoin','fillColor':'_fillColor','fontName':'_font',
                'fontSize':'_fontSize'}

    def drawRect(self, rect):
        if rect.rx == rect.ry == 0:
            #plain old rectangle
            self._canvas.rect(
                    rect.x, rect.y,
                    rect.x+rect.width, rect.y+rect.height)
        else:
            #cheat and assume ry = rx; better to generalize
            #pdfgen roundRect function.  TODO
            self._canvas.roundRect(
                    rect.x, rect.y,
                    rect.x+rect.width, rect.y+rect.height, rect.rx, rect.ry
                    )

    def drawLine(self, line):
        if self._canvas._strokeColor:
            self._canvas.line(line.x1, line.y1, line.x2, line.y2)

    def drawCircle(self, circle):
        self._canvas.circle( circle.cx, circle.cy, circle.r)

    def drawWedge(self, wedge):
        yradius, radius1, yradius1 = wedge._xtraRadii()
        if (radius1==0 or radius1 is None) and (yradius1==0 or yradius1 is None) and not wedge.annular:
            startangledegrees = wedge.startangledegrees
            endangledegrees = wedge.endangledegrees
            centerx= wedge.centerx
            centery = wedge.centery
            radius = wedge.radius
            extent = endangledegrees - startangledegrees
            self._canvas.drawArc(centerx-radius, centery-yradius, centerx+radius, centery+yradius,
                startangledegrees, extent, fromcenter=1)
        else:
            P = wedge.asPolygon()
            if isinstance(P,Path):
                self.drawPath(P)
            else:
                self.drawPolygon(P)

    def drawPolyLine(self, p):
        if self._canvas._strokeColor:
            self._canvas.polyLine(_pointsFromList(p.points))

    def drawEllipse(self, ellipse):
        #need to convert to pdfgen's bounding box representation
        x1 = ellipse.cx - ellipse.rx
        x2 = ellipse.cx + ellipse.rx
        y1 = ellipse.cy - ellipse.ry
        y2 = ellipse.cy + ellipse.ry
        self._canvas.ellipse(x1,y1,x2,y2)

    def drawPolygon(self, p):
        self._canvas.polygon(_pointsFromList(p.points), closed=1)

    def drawString(self, stringObj):
        if self._canvas._fillColor:
            S = self._tracker.getState()
            text_anchor, x, y, text = S['textAnchor'], stringObj.x,stringObj.y,stringObj.text
            if not text_anchor in ['start','inherited']:
                font, fontSize = S['fontName'], S['fontSize']
                textLen = stringWidth(text, font,fontSize)
                if text_anchor=='end':
                    x -= textLen
                elif text_anchor=='middle':
                    x -= textLen/2
                elif text_anchor=='numeric':
                    x -= numericXShift(text_anchor,text,textLen,font,fontSize,encoding='winansi')
                else:
                    raise ValueError('bad value for text_anchor '+str(text_anchor))
            self._canvas.drawString(x,y,text)

    def drawPath(self, path, fillMode=None):
        from reportlab.graphics.shapes import _renderPath
        c = self._canvas
        drawFuncs = (c.moveTo, c.lineTo, c.curveTo, c.closePath)
        autoclose = getattr(path,'autoclose','')
        def rP(**kwds):
            return _renderPath(path, drawFuncs, **kwds)
        if fillMode is None:
            fillMode = getattr(path,'fillMode',c._fillMode)
        fill = c._fillColor is not None
        stroke = c._strokeColor is not None
        clip = path.isClipPath
        fas = lambda **kwds: c._fillAndStroke([], fillMode=fillMode, **kwds)
        pathFill = lambda : c._fillAndStroke([], stroke=0, fillMode=fillMode)
        pathStroke = lambda : c._fillAndStroke([], fill=0)
        if autoclose=='svg':
            rP()
            fas(stroke=stroke,fill=fill,clip=clip)
        elif autoclose=='pdf':
            if fill:
                rP(forceClose=True)
                fas(stroke=stroke,fill=fill,clip=clip)
            elif stroke or clip:
                rP()
                fas(stroke=stroke,fill=0,clip=clip)
        else:
            if fill and rP(countOnly=True):
                rP()
            elif stroke or clip:
                fas(stroke=stroke,fill=0,clip=clip)

    def applyStateChanges(self, delta, newState):
        """This takes a set of states, and outputs the operators
        needed to set those properties"""
        for key, value in delta.items():
            if key == 'transform':
                self._canvas.transform(value[0], value[1], value[2],
                                 value[3], value[4], value[5])
            elif key == 'strokeColor':
                #this has different semantics in PDF to SVG;
                #we always have a color, and either do or do
                #not apply it; in SVG one can have a 'None' color
                self._canvas.setStrokeColor(value)
            elif key == 'strokeWidth':
                self._canvas.setLineWidth(value)
            elif key == 'strokeLineCap':  #0,1,2
                self._canvas.setLineCap(value)
            elif key == 'strokeLineJoin':
                self._canvas.setLineJoin(value)
            elif key == 'strokeDashArray':
                if value:
                    if isinstance(value,(list,tuple)) and len(value)==2 and isinstance(value[1],(tuple,list)):
                        phase = value[0]
                        value = value[1]
                    else:
                        phase = 0
                    self._canvas.setDash(value,phase)
                else:
                    self._canvas.setDash()
##          elif key == 'stroke_opacity':
##              warnOnce('Stroke Opacity not supported yet')
            elif key == 'fillColor':
                #this has different semantics in PDF to SVG;
                #we always have a color, and either do or do
                #not apply it; in SVG one can have a 'None' color
                self._canvas.setFillColor(value)
##          elif key == 'fill_rule':
##              warnOnce('Fill rules not done yet')
##          elif key == 'fill_opacity':
##              warnOnce('Fill opacity not done yet')
            elif key in ['fontSize', 'fontName']:
                # both need setting together in PDF
                # one or both might be in the deltas,
                # so need to get whichever is missing
                fontname = delta.get('fontName', self._canvas._font)
                fontsize = delta.get('fontSize', self._canvas._fontSize)
                self._canvas.setFont(fontname, fontsize)

    def drawImage(self, image):
        from reportlab.lib.utils import ImageReader
        im = ImageReader(image.path)
        self._canvas.drawImage(im._image,image.x,image.y,image.width,image.height)

def drawToFile(d,fn, showBoundary=rl_config.showBoundary,**kwd):
    d = renderScaledDrawing(d)
    c = PSCanvas((d.width,d.height))
    draw(d, c, 0, 0, showBoundary=showBoundary)
    c.save(fn)

def drawToString(d, showBoundary=rl_config.showBoundary):
    "Returns a PS as a string in memory, without touching the disk"
    s = getBytesIO()
    drawToFile(d, s, showBoundary=showBoundary)
    return s.getvalue()

#########################################################
#
#   test code.  First, define a bunch of drawings.
#   Routine to draw them comes at the end.
#
#########################################################
def test(outDir='epsout',shout=False):
    from reportlab.graphics import testshapes
    from reportlab.rl_config import verbose
    OLDFONTS = testshapes._FONTS[:]
    testshapes._FONTS[:] = ['Times-Roman','Times-Bold','Times-Italic', 'Times-BoldItalic','Courier']
    try:
        import os
        # save all drawings and their doc strings from the test file
        if not os.path.isdir(outDir):
            os.mkdir(outDir)
        #grab all drawings from the test module
        drawings = []

        for funcname in dir(testshapes):
            if funcname[0:10] == 'getDrawing':
                func = getattr(testshapes,funcname)
                drawing = func()
                docstring = getattr(func,'__doc__','')
                drawings.append((drawing, docstring))

        i = 0
        for (d, docstring) in drawings:
            filename = outDir + os.sep + 'renderPS_%d.eps'%i
            drawToFile(d,filename)
            if shout or verbose>2: print('renderPS test saved %s' % ascii(filename))
            i += 1
    finally:
        testshapes._FONTS[:] = OLDFONTS

if __name__=='__main__':
    import sys
    if len(sys.argv)>1:
        outdir = sys.argv[1]
    else:
        outdir = 'epsout'
    test(outdir,shout=True)

Filemanager

Name Type Size Permission Actions
__pycache__ Folder 0755
barcode Folder 0755
charts Folder 0755
samples Folder 0755
widgets Folder 0755
__init__.py File 274 B 0644
_renderPM.cpython-38-x86_64-linux-gnu.so File 129.52 KB 0644
renderPDF.py File 14.67 KB 0644
renderPM.py File 27.42 KB 0644
renderPS.py File 35.61 KB 0644
renderSVG.py File 36.1 KB 0644
renderbase.py File 13.14 KB 0644
shapes.py File 54.46 KB 0644
testdrawings.py File 9.21 KB 0755
testshapes.py File 16.95 KB 0755
widgetbase.py File 24.94 KB 0644