src/reportlab/graphics/renderSVG.py
author robin
Thu, 24 Oct 2019 16:07:15 +0100
changeset 4551 d357e2acc856
parent 4474 066480f7a206
permissions -rw-r--r--
improve usage of eval/exec; version --> 3.5.32
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
3032
22224b1b4d24 New docstrings mainly for module titles
damian
parents: 3028
diff changeset
     1
__doc__="""An experimental SVG renderer for the ReportLab graphics framework.
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
     2
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
     3
This will create SVG code from the ReportLab Graphics API (RLG).
1670
d2b387acfda8 Added comment on svglib.
dinu_gherman
parents: 1665
diff changeset
     4
To read existing SVG code and convert it into ReportLab graphics
d2b387acfda8 Added comment on svglib.
dinu_gherman
parents: 1665
diff changeset
     5
objects download the svglib module here:
d2b387acfda8 Added comment on svglib.
dinu_gherman
parents: 1665
diff changeset
     6
d2b387acfda8 Added comment on svglib.
dinu_gherman
parents: 1665
diff changeset
     7
  http://python.net/~gherman/#svglib
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
     8
"""
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
     9
4303
1dbe6269e831 improved support for images in renderPM/renderSVG bug report from Claude Paroz; version --> 3.3.26
robin
parents: 4283
diff changeset
    10
import math, types, sys, os, codecs, base64
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    11
from operator import getitem
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    12
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    13
from reportlab.pdfbase.pdfmetrics import stringWidth # for font info
3781
df8b57380768 import from reportlab.lib.lib.rl_accel
robin
parents: 3765
diff changeset
    14
from reportlab.lib.rl_accel import fp_str
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    15
from reportlab.lib.colors import black
4303
1dbe6269e831 improved support for images in renderPM/renderSVG bug report from Claude Paroz; version --> 3.3.26
robin
parents: 4283
diff changeset
    16
from reportlab.lib.utils import asNative, getBytesIO
2544
a6b9aa99b3c3 graphics: added Drawing.renderScale hack for renderer terminal drawing scales
rgbecker
parents: 2360
diff changeset
    17
from reportlab.graphics.renderbase import StateTracker, getStateDelta, Renderer, renderScaledDrawing
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    18
from reportlab.graphics.shapes import STATE_DEFAULTS, Path, UserNode
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    19
from reportlab.graphics.shapes import * # (only for test0)
4367
9960d82643bf remove ascii, cmp & xrange builtins abuse; version-->3.4.15
robin <robin@reportlab.com>
parents: 4325
diff changeset
    20
from reportlab import rl_config, ascii
4283
50081cf927c3 fix problems with svg drawToString contrib by Eric Gillet & Johann Du Toit
robin
parents: 4274
diff changeset
    21
from reportlab.lib.utils import getStringIO, RLString, isPy3, isUnicode, isBytes
4306
8ffb2ffc283b support for Path autoclose & fillMode; version --> 3.3.29
robin
parents: 4303
diff changeset
    22
from reportlab.pdfgen.canvas import FILL_EVEN_ODD, FILL_NON_ZERO
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    23
1617
c449e678a126 Removed dependency on PyXML. Now should use only std. lib. XML modules.
dinu_gherman
parents: 1614
diff changeset
    24
from xml.dom import getDOMImplementation
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    25
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    26
### some constants ###
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    27
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    28
sin = math.sin
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    29
cos = math.cos
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    30
pi = math.pi
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    31
3632
401542b8679b support for passing attributes into the svg renderer
rgbecker
parents: 3631
diff changeset
    32
AREA_STYLES = 'stroke-width stroke-linecap stroke stroke-opacity fill fill-opacity stroke-dasharray id'.split()
401542b8679b support for passing attributes into the svg renderer
rgbecker
parents: 3631
diff changeset
    33
LINE_STYLES = 'stroke-width stroke-linecap stroke stroke-opacity stroke-dasharray id'.split()
401542b8679b support for passing attributes into the svg renderer
rgbecker
parents: 3631
diff changeset
    34
TEXT_STYLES = 'font-family font-weight font-style font-variant font-size id'.split()
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    35
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    36
### top-level user function ###
3644
8072bd965473 renderSVG.py: more features to support web usage
rptlab
parents: 3641
diff changeset
    37
def drawToString(d, showBoundary=rl_config.showBoundary,**kwds):
1743
4815d932fb3a Dirk Datzert's drawToString function
andy_robinson
parents: 1683
diff changeset
    38
    "Returns a SVG as a string in memory, without touching the disk"
4283
50081cf927c3 fix problems with svg drawToString contrib by Eric Gillet & Johann Du Toit
robin
parents: 4274
diff changeset
    39
    s = getStringIO()
3644
8072bd965473 renderSVG.py: more features to support web usage
rptlab
parents: 3641
diff changeset
    40
    drawToFile(d, s, showBoundary=showBoundary,**kwds)
1743
4815d932fb3a Dirk Datzert's drawToString function
andy_robinson
parents: 1683
diff changeset
    41
    return s.getvalue()
4815d932fb3a Dirk Datzert's drawToString function
andy_robinson
parents: 1683
diff changeset
    42
3644
8072bd965473 renderSVG.py: more features to support web usage
rptlab
parents: 3641
diff changeset
    43
def drawToFile(d, fn, showBoundary=rl_config.showBoundary,**kwds):
2544
a6b9aa99b3c3 graphics: added Drawing.renderScale hack for renderer terminal drawing scales
rgbecker
parents: 2360
diff changeset
    44
    d = renderScaledDrawing(d)
3644
8072bd965473 renderSVG.py: more features to support web usage
rptlab
parents: 3641
diff changeset
    45
    c = SVGCanvas((d.width, d.height),**kwds)
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    46
    draw(d, c, 0, 0, showBoundary=showBoundary)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    47
    c.save(fn)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    48
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    49
def draw(drawing, canvas, x=0, y=0, showBoundary=rl_config.showBoundary):
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    50
    """As it says."""
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    51
    r = _SVGRenderer()
2553
a880f43d10bd reprotlab/graphics: fix so renderScale is used properly
rgbecker
parents: 2544
diff changeset
    52
    r.draw(renderScaledDrawing(drawing), canvas, x, y, showBoundary=showBoundary)
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    53
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    54
### helper functions ###
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    55
def _pointsFromList(L):
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    56
    """
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    57
    given a list of coordinates [x0, y0, x1, y1....]
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    58
    produce a list of points [(x0,y0), (y1,y0),....]
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    59
    """
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    60
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    61
    P=[]
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    62
    for i in range(0,len(L), 2):
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    63
        P.append((L[i], L[i+1]))
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    64
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    65
    return P
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    66
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    67
def transformNode(doc, newTag, node=None, **attrDict):
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    68
    """Transform a DOM node into new node and copy selected attributes.
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    69
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1670
diff changeset
    70
    Creates a new DOM node with tag name 'newTag' for document 'doc'
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    71
    and copies selected attributes from an existing 'node' as provided
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    72
    in 'attrDict'. The source 'node' can be None. Attribute values will
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    73
    be converted to strings.
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    74
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1670
diff changeset
    75
    E.g.
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1670
diff changeset
    76
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    77
        n = transformNode(doc, "node1", x="0", y="1")
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    78
        -> DOM node for <node1 x="0" y="1"/>
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    79
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    80
        n = transformNode(doc, "node1", x=0, y=1+1)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    81
        -> DOM node for <node1 x="0" y="2"/>
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    82
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    83
        n = transformNode(doc, "node1", node0, x="x0", y="x0", zoo=bar())
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    84
        -> DOM node for <node1 x="[node0.x0]" y="[node0.y0]" zoo="[bar()]"/>
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    85
    """
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    86
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    87
    newNode = doc.createElement(newTag)
3723
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
    88
    for newAttr, attr in attrDict.items():
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    89
        sattr =  str(attr)
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1670
diff changeset
    90
        if not node:
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    91
            newNode.setAttribute(newAttr, sattr)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    92
        else:
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    93
            attrVal = node.getAttribute(sattr)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    94
            newNode.setAttribute(newAttr, attrVal or sattr)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    95
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    96
    return newNode
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
    97
3620
7b2b21af8759 renderSVG.py: use a properly checking EndodedWriter class
rgbecker
parents: 3608
diff changeset
    98
class EncodedWriter(list):
7b2b21af8759 renderSVG.py: use a properly checking EndodedWriter class
rgbecker
parents: 3608
diff changeset
    99
    '''
7b2b21af8759 renderSVG.py: use a properly checking EndodedWriter class
rgbecker
parents: 3608
diff changeset
   100
    EncodedWriter(encoding) assumes .write will be called with
3924
96733c034012 renderSVG.py, test_renderSVG.py: fix for python2
robin
parents: 3781
diff changeset
   101
    either unicode or utf8 encoded bytes. it will accumulate
3765
a7e7cd6e0003 renderPM.py now works to produce a pmout at least
robin
parents: 3723
diff changeset
   102
    unicode
3620
7b2b21af8759 renderSVG.py: use a properly checking EndodedWriter class
rgbecker
parents: 3608
diff changeset
   103
    '''
3621
e9525ac2459b renderSVG.py: more support for encoded output
rgbecker
parents: 3620
diff changeset
   104
    BOMS =  {
e9525ac2459b renderSVG.py: more support for encoded output
rgbecker
parents: 3620
diff changeset
   105
        'utf-32':codecs.BOM_UTF32,
e9525ac2459b renderSVG.py: more support for encoded output
rgbecker
parents: 3620
diff changeset
   106
        'utf-32-be':codecs.BOM_UTF32_BE,
e9525ac2459b renderSVG.py: more support for encoded output
rgbecker
parents: 3620
diff changeset
   107
        'utf-32-le':codecs.BOM_UTF32_LE,
e9525ac2459b renderSVG.py: more support for encoded output
rgbecker
parents: 3620
diff changeset
   108
        'utf-16':codecs.BOM_UTF16,
e9525ac2459b renderSVG.py: more support for encoded output
rgbecker
parents: 3620
diff changeset
   109
        'utf-16-be':codecs.BOM_UTF16_BE,
e9525ac2459b renderSVG.py: more support for encoded output
rgbecker
parents: 3620
diff changeset
   110
        'utf-16-le':codecs.BOM_UTF16_LE,
e9525ac2459b renderSVG.py: more support for encoded output
rgbecker
parents: 3620
diff changeset
   111
        }
e9525ac2459b renderSVG.py: more support for encoded output
rgbecker
parents: 3620
diff changeset
   112
    def __init__(self,encoding,bom=False):
3620
7b2b21af8759 renderSVG.py: use a properly checking EndodedWriter class
rgbecker
parents: 3608
diff changeset
   113
        list.__init__(self)
3621
e9525ac2459b renderSVG.py: more support for encoded output
rgbecker
parents: 3620
diff changeset
   114
        self.encoding = encoding = codecs.lookup(encoding).name
e9525ac2459b renderSVG.py: more support for encoded output
rgbecker
parents: 3620
diff changeset
   115
        if bom and '16' in encoding or '32' in encoding:
e9525ac2459b renderSVG.py: more support for encoded output
rgbecker
parents: 3620
diff changeset
   116
            self.write(self.BOMS[encoding])
3620
7b2b21af8759 renderSVG.py: use a properly checking EndodedWriter class
rgbecker
parents: 3608
diff changeset
   117
3765
a7e7cd6e0003 renderPM.py now works to produce a pmout at least
robin
parents: 3723
diff changeset
   118
    def write(self,u):
3924
96733c034012 renderSVG.py, test_renderSVG.py: fix for python2
robin
parents: 3781
diff changeset
   119
        if isBytes(u):
3620
7b2b21af8759 renderSVG.py: use a properly checking EndodedWriter class
rgbecker
parents: 3608
diff changeset
   120
            try:
3765
a7e7cd6e0003 renderPM.py now works to produce a pmout at least
robin
parents: 3723
diff changeset
   121
                 u = u.decode('utf-8')
3620
7b2b21af8759 renderSVG.py: use a properly checking EndodedWriter class
rgbecker
parents: 3608
diff changeset
   122
            except:
7b2b21af8759 renderSVG.py: use a properly checking EndodedWriter class
rgbecker
parents: 3608
diff changeset
   123
                et, ev, tb = sys.exc_info()
7b2b21af8759 renderSVG.py: use a properly checking EndodedWriter class
rgbecker
parents: 3608
diff changeset
   124
                ev = str(ev)
7b2b21af8759 renderSVG.py: use a properly checking EndodedWriter class
rgbecker
parents: 3608
diff changeset
   125
                del et, tb
3765
a7e7cd6e0003 renderPM.py now works to produce a pmout at least
robin
parents: 3723
diff changeset
   126
                raise ValueError("String %r not encoded as 'utf-8'\nerror=%s" % (u,ev))
3924
96733c034012 renderSVG.py, test_renderSVG.py: fix for python2
robin
parents: 3781
diff changeset
   127
        elif not isUnicode(u):
96733c034012 renderSVG.py, test_renderSVG.py: fix for python2
robin
parents: 3781
diff changeset
   128
            raise ValueError("EncodedWriter.write(%s) argument should be 'utf-8' bytes or str" % ascii(u))
3765
a7e7cd6e0003 renderPM.py now works to produce a pmout at least
robin
parents: 3723
diff changeset
   129
        self.append(u)
3620
7b2b21af8759 renderSVG.py: use a properly checking EndodedWriter class
rgbecker
parents: 3608
diff changeset
   130
7b2b21af8759 renderSVG.py: use a properly checking EndodedWriter class
rgbecker
parents: 3608
diff changeset
   131
    def getvalue(self):
7b2b21af8759 renderSVG.py: use a properly checking EndodedWriter class
rgbecker
parents: 3608
diff changeset
   132
        r = ''.join(self)
7b2b21af8759 renderSVG.py: use a properly checking EndodedWriter class
rgbecker
parents: 3608
diff changeset
   133
        del self[:]
7b2b21af8759 renderSVG.py: use a properly checking EndodedWriter class
rgbecker
parents: 3608
diff changeset
   134
        return r
7b2b21af8759 renderSVG.py: use a properly checking EndodedWriter class
rgbecker
parents: 3608
diff changeset
   135
4325
fc03e6396da5 add support for fillMode in drawing stack; version-->3.3.34
robin <robin@reportlab.com>
parents: 4306
diff changeset
   136
_fillRuleMap = {
fc03e6396da5 add support for fillMode in drawing stack; version-->3.3.34
robin <robin@reportlab.com>
parents: 4306
diff changeset
   137
        FILL_NON_ZERO: 'nonzero',
fc03e6396da5 add support for fillMode in drawing stack; version-->3.3.34
robin <robin@reportlab.com>
parents: 4306
diff changeset
   138
        'non-zero': 'nonzero',
fc03e6396da5 add support for fillMode in drawing stack; version-->3.3.34
robin <robin@reportlab.com>
parents: 4306
diff changeset
   139
        'nonzero': 'nonzero',
fc03e6396da5 add support for fillMode in drawing stack; version-->3.3.34
robin <robin@reportlab.com>
parents: 4306
diff changeset
   140
        FILL_EVEN_ODD: 'evenodd',
fc03e6396da5 add support for fillMode in drawing stack; version-->3.3.34
robin <robin@reportlab.com>
parents: 4306
diff changeset
   141
        'even-odd': 'evenodd',
fc03e6396da5 add support for fillMode in drawing stack; version-->3.3.34
robin <robin@reportlab.com>
parents: 4306
diff changeset
   142
        'evenodd': 'evenodd',
fc03e6396da5 add support for fillMode in drawing stack; version-->3.3.34
robin <robin@reportlab.com>
parents: 4306
diff changeset
   143
        }
4306
8ffb2ffc283b support for Path autoclose & fillMode; version --> 3.3.29
robin
parents: 4303
diff changeset
   144
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   145
### classes ###
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   146
class SVGCanvas:
3644
8072bd965473 renderSVG.py: more features to support web usage
rptlab
parents: 3641
diff changeset
   147
    def __init__(self, size=(300,300), encoding='utf-8', verbose=0, bom=False, **kwds):
3639
22763fe00fab renderSVG.py: allow way to use clip property rather than <clipPath>
rptlab
parents: 3635
diff changeset
   148
        '''
3644
8072bd965473 renderSVG.py: more features to support web usage
rptlab
parents: 3641
diff changeset
   149
        verbose = 0 >0 means do verbose stuff
8072bd965473 renderSVG.py: more features to support web usage
rptlab
parents: 3641
diff changeset
   150
        useClip = False True means don't use a clipPath definition put the global clip into the clip property
3639
22763fe00fab renderSVG.py: allow way to use clip property rather than <clipPath>
rptlab
parents: 3635
diff changeset
   151
                        to get around an issue with safari
3644
8072bd965473 renderSVG.py: more features to support web usage
rptlab
parents: 3641
diff changeset
   152
        extraXmlDecl = ''   use to add extra xml declarations
8072bd965473 renderSVG.py: more features to support web usage
rptlab
parents: 3641
diff changeset
   153
        scaleGroupId = ''   id of an extra group to add around the drawing to allow easy scaling
8072bd965473 renderSVG.py: more features to support web usage
rptlab
parents: 3641
diff changeset
   154
        svgAttrs = {}       dictionary of attributes to be applied to the svg tag itself
3639
22763fe00fab renderSVG.py: allow way to use clip property rather than <clipPath>
rptlab
parents: 3635
diff changeset
   155
        '''
3607
97d0b7cfa37f renderSVG.py: allow for encoding (default utf8) and verbose=0; Guillaume's changes
rgbecker
parents: 3606
diff changeset
   156
        self.verbose = verbose
3621
e9525ac2459b renderSVG.py: more support for encoded output
rgbecker
parents: 3620
diff changeset
   157
        self.encoding = codecs.lookup(encoding).name
e9525ac2459b renderSVG.py: more support for encoded output
rgbecker
parents: 3620
diff changeset
   158
        self.bom = bom
3644
8072bd965473 renderSVG.py: more features to support web usage
rptlab
parents: 3641
diff changeset
   159
        useClip = kwds.pop('useClip',False)
8072bd965473 renderSVG.py: more features to support web usage
rptlab
parents: 3641
diff changeset
   160
        self.fontHacks = kwds.pop('fontHacks',{})
8072bd965473 renderSVG.py: more features to support web usage
rptlab
parents: 3641
diff changeset
   161
        self.extraXmlDecl = kwds.pop('extraXmlDecl','')
8072bd965473 renderSVG.py: more features to support web usage
rptlab
parents: 3641
diff changeset
   162
        scaleGroupId = kwds.pop('scaleGroupId','')
4306
8ffb2ffc283b support for Path autoclose & fillMode; version --> 3.3.29
robin
parents: 4303
diff changeset
   163
        self._fillMode = FILL_EVEN_ODD
3644
8072bd965473 renderSVG.py: more features to support web usage
rptlab
parents: 3641
diff changeset
   164
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   165
        self.width, self.height = self.size = size
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   166
        # self.height = size[1]
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   167
        self.code = []
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   168
        self.style = {}
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   169
        self.path = ''
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   170
        self._strokeColor = self._fillColor = self._lineWidth = \
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   171
            self._font = self._fontSize = self._lineCap = \
4325
fc03e6396da5 add support for fillMode in drawing stack; version-->3.3.34
robin <robin@reportlab.com>
parents: 4306
diff changeset
   172
            self._lineJoin = None
4385
e4da72e381d5 allow fp_str rendering in renderSVG
robin <robin@reportlab.com>
parents: 4367
diff changeset
   173
        if kwds.pop('use_fp_str',False):
e4da72e381d5 allow fp_str rendering in renderSVG
robin <robin@reportlab.com>
parents: 4367
diff changeset
   174
            self.fp_str = fp_str
e4da72e381d5 allow fp_str rendering in renderSVG
robin <robin@reportlab.com>
parents: 4367
diff changeset
   175
        else:
e4da72e381d5 allow fp_str rendering in renderSVG
robin <robin@reportlab.com>
parents: 4367
diff changeset
   176
            self.fp_str = lambda *args: (' '.join(len(args)*['%f'])) % args
e4da72e381d5 allow fp_str rendering in renderSVG
robin <robin@reportlab.com>
parents: 4367
diff changeset
   177
        self.cfp_str = lambda *args: self.fp_str(*args).replace(' ',',')
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   178
1642
97651958fbe5 Load minidom specifically (pleasing Jython).
dinu_gherman
parents: 1617
diff changeset
   179
        implementation = getDOMImplementation('minidom')
3114
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   180
        #Based on official example here http://www.w3.org/TR/SVG10/linking.html want:
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   181
        #<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" 
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   182
        #  "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   183
        #Thus,
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   184
        #doctype = implementation.createDocumentType("svg",
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   185
        #          "-//W3C//DTD SVG 20010904//EN",
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   186
        #          "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd")
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   187
        #
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   188
        #However, putting that example through http://validator.w3.org/ recommends:
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   189
        #<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" 
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   190
        #  "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   191
        #So we'll use that for our SVG 1.0 output.
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   192
        doctype = implementation.createDocumentType("svg",
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   193
                  "-//W3C//DTD SVG 1.0//EN",
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   194
                  "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd")
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   195
        self.doc = implementation.createDocument(None,"svg",doctype)
1617
c449e678a126 Removed dependency on PyXML. Now should use only std. lib. XML modules.
dinu_gherman
parents: 1614
diff changeset
   196
        self.svg = self.doc.documentElement
3644
8072bd965473 renderSVG.py: more features to support web usage
rptlab
parents: 3641
diff changeset
   197
        svgAttrs = dict(
8072bd965473 renderSVG.py: more features to support web usage
rptlab
parents: 3641
diff changeset
   198
                    width = str(size[0]),
8072bd965473 renderSVG.py: more features to support web usage
rptlab
parents: 3641
diff changeset
   199
                    height=str(self.height),
8072bd965473 renderSVG.py: more features to support web usage
rptlab
parents: 3641
diff changeset
   200
                    preserveAspectRatio="xMinYMin meet",
8072bd965473 renderSVG.py: more features to support web usage
rptlab
parents: 3641
diff changeset
   201
                    viewBox="0 0 %d %d" % (self.width, self.height),
8072bd965473 renderSVG.py: more features to support web usage
rptlab
parents: 3641
diff changeset
   202
                    #baseProfile = "full",  #disliked in V 1.0
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   203
3644
8072bd965473 renderSVG.py: more features to support web usage
rptlab
parents: 3641
diff changeset
   204
                    #these suggested by Tim Roberts, as updated by peter@maubp.freeserve.co.uk 
8072bd965473 renderSVG.py: more features to support web usage
rptlab
parents: 3641
diff changeset
   205
                    xmlns="http://www.w3.org/2000/svg",
8072bd965473 renderSVG.py: more features to support web usage
rptlab
parents: 3641
diff changeset
   206
                    version="1.0",
8072bd965473 renderSVG.py: more features to support web usage
rptlab
parents: 3641
diff changeset
   207
                    )
4325
fc03e6396da5 add support for fillMode in drawing stack; version-->3.3.34
robin <robin@reportlab.com>
parents: 4306
diff changeset
   208
        svgAttrs['fill-rule'] = _fillRuleMap[self._fillMode]
3644
8072bd965473 renderSVG.py: more features to support web usage
rptlab
parents: 3641
diff changeset
   209
        svgAttrs["xmlns:xlink"] = "http://www.w3.org/1999/xlink"
8072bd965473 renderSVG.py: more features to support web usage
rptlab
parents: 3641
diff changeset
   210
        svgAttrs.update(kwds.pop('svgAttrs',{}))
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3644
diff changeset
   211
        for k,v in svgAttrs.items():
3644
8072bd965473 renderSVG.py: more features to support web usage
rptlab
parents: 3641
diff changeset
   212
            self.svg.setAttribute(k,v)
3605
bb3c9e12a4db added viewBox attribute to SVG drawings. This means they can be resized by setting the width and eheight in the embed tag.
andy
parents: 3592
diff changeset
   213
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   214
        title = self.doc.createElement('title')
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   215
        text = self.doc.createTextNode('...')
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   216
        title.appendChild(text)
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1670
diff changeset
   217
        self.svg.appendChild(title)
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1670
diff changeset
   218
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   219
        desc = self.doc.createElement('desc')
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   220
        text = self.doc.createTextNode('...')
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   221
        desc.appendChild(text)
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1670
diff changeset
   222
        self.svg.appendChild(desc)
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   223
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   224
        self.setFont(STATE_DEFAULTS['fontName'], STATE_DEFAULTS['fontSize'])
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   225
        self.setStrokeColor(STATE_DEFAULTS['strokeColor'])
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   226
        self.setLineCap(2)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   227
        self.setLineJoin(0)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   228
        self.setLineWidth(1)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   229
3644
8072bd965473 renderSVG.py: more features to support web usage
rptlab
parents: 3641
diff changeset
   230
        if not useClip:
3639
22763fe00fab renderSVG.py: allow way to use clip property rather than <clipPath>
rptlab
parents: 3635
diff changeset
   231
            # Add a rectangular clipping path identical to view area.
22763fe00fab renderSVG.py: allow way to use clip property rather than <clipPath>
rptlab
parents: 3635
diff changeset
   232
            clipPath = transformNode(self.doc, "clipPath", id="clip")
22763fe00fab renderSVG.py: allow way to use clip property rather than <clipPath>
rptlab
parents: 3635
diff changeset
   233
            clipRect = transformNode(self.doc, "rect", x=0, y=0,
22763fe00fab renderSVG.py: allow way to use clip property rather than <clipPath>
rptlab
parents: 3635
diff changeset
   234
                width=self.width, height=self.height)
22763fe00fab renderSVG.py: allow way to use clip property rather than <clipPath>
rptlab
parents: 3635
diff changeset
   235
            clipPath.appendChild(clipRect)
22763fe00fab renderSVG.py: allow way to use clip property rather than <clipPath>
rptlab
parents: 3635
diff changeset
   236
            self.svg.appendChild(clipPath)
22763fe00fab renderSVG.py: allow way to use clip property rather than <clipPath>
rptlab
parents: 3635
diff changeset
   237
            gtkw = dict(style="clip-path: url(#clip)")
22763fe00fab renderSVG.py: allow way to use clip property rather than <clipPath>
rptlab
parents: 3635
diff changeset
   238
        else:
22763fe00fab renderSVG.py: allow way to use clip property rather than <clipPath>
rptlab
parents: 3635
diff changeset
   239
            gtkw = dict(clip="0 0 %d %d" % (self.width,self.height))
1661
94d09f7b4c9a Added outer rectangular clipping path.
dinu_gherman
parents: 1648
diff changeset
   240
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1670
diff changeset
   241
        self.groupTree = transformNode(self.doc, "g",
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1670
diff changeset
   242
            id="group",
1661
94d09f7b4c9a Added outer rectangular clipping path.
dinu_gherman
parents: 1648
diff changeset
   243
            transform="scale(1,-1) translate(0,-%d)" % self.height,
3639
22763fe00fab renderSVG.py: allow way to use clip property rather than <clipPath>
rptlab
parents: 3635
diff changeset
   244
            **gtkw
22763fe00fab renderSVG.py: allow way to use clip property rather than <clipPath>
rptlab
parents: 3635
diff changeset
   245
            )
3644
8072bd965473 renderSVG.py: more features to support web usage
rptlab
parents: 3641
diff changeset
   246
8072bd965473 renderSVG.py: more features to support web usage
rptlab
parents: 3641
diff changeset
   247
        if scaleGroupId:
8072bd965473 renderSVG.py: more features to support web usage
rptlab
parents: 3641
diff changeset
   248
            self.scaleTree = transformNode(self.doc, "g", id=scaleGroupId, transform="scale(1,1)")
8072bd965473 renderSVG.py: more features to support web usage
rptlab
parents: 3641
diff changeset
   249
            self.scaleTree.appendChild(self.groupTree)
8072bd965473 renderSVG.py: more features to support web usage
rptlab
parents: 3641
diff changeset
   250
            self.svg.appendChild(self.scaleTree)
8072bd965473 renderSVG.py: more features to support web usage
rptlab
parents: 3641
diff changeset
   251
        else:
8072bd965473 renderSVG.py: more features to support web usage
rptlab
parents: 3641
diff changeset
   252
            self.svg.appendChild(self.groupTree)
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   253
        self.currGroup = self.groupTree
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   254
3114
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   255
    def save(self, fn=None):
3621
e9525ac2459b renderSVG.py: more support for encoded output
rgbecker
parents: 3620
diff changeset
   256
        writer = EncodedWriter(self.encoding,bom=self.bom)
3620
7b2b21af8759 renderSVG.py: use a properly checking EndodedWriter class
rgbecker
parents: 3608
diff changeset
   257
        self.doc.writexml(writer,addindent="\t",newl="\n",encoding=self.encoding)
7b2b21af8759 renderSVG.py: use a properly checking EndodedWriter class
rgbecker
parents: 3608
diff changeset
   258
3765
a7e7cd6e0003 renderPM.py now works to produce a pmout at least
robin
parents: 3723
diff changeset
   259
        if hasattr(fn,'write'):
a7e7cd6e0003 renderPM.py now works to produce a pmout at least
robin
parents: 3723
diff changeset
   260
            f = fn
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   261
        else:
3765
a7e7cd6e0003 renderPM.py now works to produce a pmout at least
robin
parents: 3723
diff changeset
   262
            if isPy3:
a7e7cd6e0003 renderPM.py now works to produce a pmout at least
robin
parents: 3723
diff changeset
   263
                f = open(fn, 'w',encoding=self.encoding)
a7e7cd6e0003 renderPM.py now works to produce a pmout at least
robin
parents: 3723
diff changeset
   264
            else:
a7e7cd6e0003 renderPM.py now works to produce a pmout at least
robin
parents: 3723
diff changeset
   265
                f = open(fn, 'w')
a7e7cd6e0003 renderPM.py now works to produce a pmout at least
robin
parents: 3723
diff changeset
   266
3641
2d1e356abce1 renderSVG.py: add canvas extraXmlDecl argument
rptlab
parents: 3640
diff changeset
   267
        svg = writer.getvalue()
2d1e356abce1 renderSVG.py: add canvas extraXmlDecl argument
rptlab
parents: 3640
diff changeset
   268
        exd = self.extraXmlDecl
2d1e356abce1 renderSVG.py: add canvas extraXmlDecl argument
rptlab
parents: 3640
diff changeset
   269
        if exd:
2d1e356abce1 renderSVG.py: add canvas extraXmlDecl argument
rptlab
parents: 3640
diff changeset
   270
            svg = svg.replace('?>','?>'+exd)
3924
96733c034012 renderSVG.py, test_renderSVG.py: fix for python2
robin
parents: 3781
diff changeset
   271
        f.write(svg if isPy3 else svg.encode(self.encoding))
3114
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   272
        if f is not fn:
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   273
            f.close()
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   274
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   275
    ### helpers ###
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   276
    def NOTUSED_stringWidth(self, s, font=None, fontSize=None):
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   277
        """Return the logical width of the string if it were drawn
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   278
        in the current font (defaults to self.font).
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   279
        """
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   280
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   281
        font = font or self._font
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   282
        fontSize = fontSize or self._fontSize
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   283
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   284
        return stringWidth(s, font, fontSize)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   285
3631
faec46a34c20 renderSVG add support for font attributes
rgbecker
parents: 3621
diff changeset
   286
    def _formatStyle(self, include=[], exclude='',**kwds):
3370
0783797d9871 graphics.py: adjust renderPM test and fix renderSVG PolyLine
rgbecker
parents: 3358
diff changeset
   287
        style = self.style.copy()
0783797d9871 graphics.py: adjust renderPM test and fix renderSVG PolyLine
rgbecker
parents: 3358
diff changeset
   288
        style.update(kwds)
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3644
diff changeset
   289
        keys = list(style.keys())
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   290
        if include:
3631
faec46a34c20 renderSVG add support for font attributes
rgbecker
parents: 3621
diff changeset
   291
            keys = [k for k in keys if k in include]
3370
0783797d9871 graphics.py: adjust renderPM test and fix renderSVG PolyLine
rgbecker
parents: 3358
diff changeset
   292
        if exclude:
0783797d9871 graphics.py: adjust renderPM test and fix renderSVG PolyLine
rgbecker
parents: 3358
diff changeset
   293
            exclude = exclude.split()
0783797d9871 graphics.py: adjust renderPM test and fix renderSVG PolyLine
rgbecker
parents: 3358
diff changeset
   294
            items = [k+': '+str(style[k]) for k in keys if k not in exclude]
0783797d9871 graphics.py: adjust renderPM test and fix renderSVG PolyLine
rgbecker
parents: 3358
diff changeset
   295
        else:
0783797d9871 graphics.py: adjust renderPM test and fix renderSVG PolyLine
rgbecker
parents: 3358
diff changeset
   296
            items = [k+': '+str(style[k]) for k in keys]
3114
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   297
        return '; '.join(items) + ';'
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   298
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   299
    def _escape(self, s):
4243
a1dd7de04817 remove unwanted escaping in renderSVG, version --> 3.2.14
robin
parents: 4132
diff changeset
   300
        '''I don't think this was ever needed; seems to have been copied from renderPS'''
a1dd7de04817 remove unwanted escaping in renderSVG, version --> 3.2.14
robin
parents: 4132
diff changeset
   301
        return s
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   302
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   303
    def _genArcCode(self, x1, y1, x2, y2, startAng, extent):
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1670
diff changeset
   304
        """Calculate the path for an arc inscribed in rectangle defined
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   305
        by (x1,y1),(x2,y2)."""
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   306
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   307
        return
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   308
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   309
        #calculate semi-minor and semi-major axes of ellipse
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   310
        xScale = abs((x2-x1)/2.0)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   311
        yScale = abs((y2-y1)/2.0)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   312
        #calculate centre of ellipse
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   313
        x, y = (x1+x2)/2.0, (y1+y2)/2.0
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   314
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   315
        codeline = 'matrix currentmatrix %s %s translate %s %s scale 0 0 1 %s %s %s setmatrix'
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   316
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   317
        if extent >= 0:
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   318
            arc='arc'
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   319
        else:
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   320
            arc='arcn'
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   321
        data = (x,y, xScale, yScale, startAng, startAng+extent, arc)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   322
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   323
        return codeline % data
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   324
4306
8ffb2ffc283b support for Path autoclose & fillMode; version --> 3.3.29
robin
parents: 4303
diff changeset
   325
    def _fillAndStroke(self, code, clip=0, link_info=None,styles=AREA_STYLES,fillMode=None):
8ffb2ffc283b support for Path autoclose & fillMode; version --> 3.3.29
robin
parents: 4303
diff changeset
   326
        xtra = {}
8ffb2ffc283b support for Path autoclose & fillMode; version --> 3.3.29
robin
parents: 4303
diff changeset
   327
        if fillMode:
8ffb2ffc283b support for Path autoclose & fillMode; version --> 3.3.29
robin
parents: 4303
diff changeset
   328
            xtra['fill-rule'] = _fillRuleName(fillMode)
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1670
diff changeset
   329
        path = transformNode(self.doc, "path",
4306
8ffb2ffc283b support for Path autoclose & fillMode; version --> 3.3.29
robin
parents: 4303
diff changeset
   330
            d=self.path, style=self._formatStyle(styles),
8ffb2ffc283b support for Path autoclose & fillMode; version --> 3.3.29
robin
parents: 4303
diff changeset
   331
            )
3128
28e7abf47067 reportlab: renderSVG.py add in PJACock's (<peter@maubp.freeserve.co.uk>) path linkability patch
rgbecker
parents: 3115
diff changeset
   332
        if link_info :
28e7abf47067 reportlab: renderSVG.py add in PJACock's (<peter@maubp.freeserve.co.uk>) path linkability patch
rgbecker
parents: 3115
diff changeset
   333
            path = self._add_link(path, link_info)
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   334
        self.currGroup.appendChild(path)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   335
        self.path = ''
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   336
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   337
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   338
    ### styles ###
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   339
    def setLineCap(self, v):
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   340
        vals = {0:'butt', 1:'round', 2:'square'}
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   341
        if self._lineCap != v:
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   342
            self._lineCap = v
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   343
            self.style['stroke-linecap'] = vals[v]
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   344
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   345
    def setLineJoin(self, v):
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   346
        vals = {0:'miter', 1:'round', 2:'bevel'}
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   347
        if self._lineJoin != v:
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   348
            self._lineJoin = v
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   349
            self.style['stroke-linecap'] = vals[v]
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1670
diff changeset
   350
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   351
    def setDash(self, array=[], phase=0):
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   352
        """Two notations. Pass two numbers, or an array and phase."""
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   353
3502
b2c9927314fc color fixes
rgbecker
parents: 3370
diff changeset
   354
        if isinstance(array,(float,int)):
3114
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   355
            self.style['stroke-dasharray'] = ', '.join(map(str, ([array, phase])))
3502
b2c9927314fc color fixes
rgbecker
parents: 3370
diff changeset
   356
        elif isinstance(array,(tuple,list)) and len(array) > 0:
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   357
            assert phase >= 0, "phase is a length in user space"
4551
d357e2acc856 improve usage of eval/exec; version --> 3.5.32
robin
parents: 4474
diff changeset
   358
            self.style['stroke-dasharray'] = ', '.join(map(str, (list(array)+[phase])))
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   359
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   360
    def setStrokeColor(self, color):
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   361
        self._strokeColor = color
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   362
        if color == None:
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   363
            self.style['stroke'] = 'none'
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   364
        else:
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   365
            r, g, b = color.red, color.green, color.blue
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   366
            self.style['stroke'] = 'rgb(%d%%,%d%%,%d%%)' % (r*100, g*100, b*100)
3632
401542b8679b support for passing attributes into the svg renderer
rgbecker
parents: 3631
diff changeset
   367
            alpha = color.normalizedAlpha
401542b8679b support for passing attributes into the svg renderer
rgbecker
parents: 3631
diff changeset
   368
            if alpha!=1:
401542b8679b support for passing attributes into the svg renderer
rgbecker
parents: 3631
diff changeset
   369
                self.style['stroke-opacity'] = '%s' % alpha
401542b8679b support for passing attributes into the svg renderer
rgbecker
parents: 3631
diff changeset
   370
            elif 'stroke-opacity' in self.style:
401542b8679b support for passing attributes into the svg renderer
rgbecker
parents: 3631
diff changeset
   371
                del self.style['stroke-opacity']
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   372
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   373
    def setFillColor(self, color):
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   374
        self._fillColor = color
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   375
        if color == None:
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   376
            self.style['fill'] = 'none'
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   377
        else:
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   378
            r, g, b = color.red, color.green, color.blue
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   379
            self.style['fill'] = 'rgb(%d%%,%d%%,%d%%)' % (r*100, g*100, b*100)
3632
401542b8679b support for passing attributes into the svg renderer
rgbecker
parents: 3631
diff changeset
   380
            alpha = color.normalizedAlpha
401542b8679b support for passing attributes into the svg renderer
rgbecker
parents: 3631
diff changeset
   381
            if alpha!=1:
401542b8679b support for passing attributes into the svg renderer
rgbecker
parents: 3631
diff changeset
   382
                self.style['fill-opacity'] = '%s' % alpha
401542b8679b support for passing attributes into the svg renderer
rgbecker
parents: 3631
diff changeset
   383
            elif 'fill-opacity' in self.style:
401542b8679b support for passing attributes into the svg renderer
rgbecker
parents: 3631
diff changeset
   384
                del self.style['fill-opacity']
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   385
4325
fc03e6396da5 add support for fillMode in drawing stack; version-->3.3.34
robin <robin@reportlab.com>
parents: 4306
diff changeset
   386
    def setFillMode(self, v):
fc03e6396da5 add support for fillMode in drawing stack; version-->3.3.34
robin <robin@reportlab.com>
parents: 4306
diff changeset
   387
        self._fillMode = v
fc03e6396da5 add support for fillMode in drawing stack; version-->3.3.34
robin <robin@reportlab.com>
parents: 4306
diff changeset
   388
        self.style['fill-rule'] = _fillRuleMap[v]
fc03e6396da5 add support for fillMode in drawing stack; version-->3.3.34
robin <robin@reportlab.com>
parents: 4306
diff changeset
   389
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   390
    def setLineWidth(self, width):
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   391
        if width != self._lineWidth:
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   392
            self._lineWidth = width
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   393
            self.style['stroke-width'] = width
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   394
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   395
    def setFont(self, font, fontSize):
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   396
        if self._font != font or self._fontSize != fontSize:
3631
faec46a34c20 renderSVG add support for font attributes
rgbecker
parents: 3621
diff changeset
   397
            self._font = font
faec46a34c20 renderSVG add support for font attributes
rgbecker
parents: 3621
diff changeset
   398
            self._fontSize = fontSize
faec46a34c20 renderSVG add support for font attributes
rgbecker
parents: 3621
diff changeset
   399
            style = self.style
faec46a34c20 renderSVG add support for font attributes
rgbecker
parents: 3621
diff changeset
   400
            for k in TEXT_STYLES:
faec46a34c20 renderSVG add support for font attributes
rgbecker
parents: 3621
diff changeset
   401
                if k in style:
faec46a34c20 renderSVG add support for font attributes
rgbecker
parents: 3621
diff changeset
   402
                    del style[k]
3640
fe11db4e7bed renderSVG.py: add fontHacks to SVGCanvas
rptlab
parents: 3639
diff changeset
   403
            svgAttrs = self.fontHacks[font] if font in self.fontHacks else {}
3632
401542b8679b support for passing attributes into the svg renderer
rgbecker
parents: 3631
diff changeset
   404
            if isinstance(font,RLString):
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3644
diff changeset
   405
                svgAttrs.update(iter(font.svgAttrs.items()))
3640
fe11db4e7bed renderSVG.py: add fontHacks to SVGCanvas
rptlab
parents: 3639
diff changeset
   406
            if svgAttrs:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3644
diff changeset
   407
                for k,v in svgAttrs.items():
3640
fe11db4e7bed renderSVG.py: add fontHacks to SVGCanvas
rptlab
parents: 3639
diff changeset
   408
                    a = 'font-'+k
fe11db4e7bed renderSVG.py: add fontHacks to SVGCanvas
rptlab
parents: 3639
diff changeset
   409
                    if a in TEXT_STYLES:
fe11db4e7bed renderSVG.py: add fontHacks to SVGCanvas
rptlab
parents: 3639
diff changeset
   410
                        style[a] = v
3631
faec46a34c20 renderSVG add support for font attributes
rgbecker
parents: 3621
diff changeset
   411
            if 'font-family' not in style:
faec46a34c20 renderSVG add support for font attributes
rgbecker
parents: 3621
diff changeset
   412
                style['font-family'] = font
faec46a34c20 renderSVG add support for font attributes
rgbecker
parents: 3621
diff changeset
   413
            style['font-size'] = '%spx' % fontSize
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   414
3114
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   415
    def _add_link(self, dom_object, link_info) :
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   416
        assert isinstance(link_info, dict)
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   417
        link = transformNode(self.doc, "a", **link_info)
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   418
        link.appendChild(dom_object)
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   419
        return link
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   420
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   421
    ### shapes ###
3632
401542b8679b support for passing attributes into the svg renderer
rgbecker
parents: 3631
diff changeset
   422
    def rect(self, x1,y1, x2,y2, rx=8, ry=8, link_info=None, **_svgAttrs):
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   423
        "Draw a rectangle between x1,y1 and x2,y2."
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1670
diff changeset
   424
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3644
diff changeset
   425
        if self.verbose: print("+++ SVGCanvas.rect")
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   426
3358
1c3e05c2cf09 renderSVG.py: attempt to fix negative dimensions for rect
rgbecker
parents: 3326
diff changeset
   427
        x = min(x1,x2)
1c3e05c2cf09 renderSVG.py: attempt to fix negative dimensions for rect
rgbecker
parents: 3326
diff changeset
   428
        y = min(y1,y2)
3632
401542b8679b support for passing attributes into the svg renderer
rgbecker
parents: 3631
diff changeset
   429
        kwds = {}
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1670
diff changeset
   430
        rect = transformNode(self.doc, "rect",
3358
1c3e05c2cf09 renderSVG.py: attempt to fix negative dimensions for rect
rgbecker
parents: 3326
diff changeset
   431
            x=x, y=y, width=max(x1,x2)-x, height=max(y1,y2)-y,
3632
401542b8679b support for passing attributes into the svg renderer
rgbecker
parents: 3631
diff changeset
   432
            style=self._formatStyle(AREA_STYLES),**_svgAttrs)
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   433
3114
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   434
        if link_info :
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   435
            rect = self._add_link(rect, link_info)
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   436
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   437
        self.currGroup.appendChild(rect)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   438
3632
401542b8679b support for passing attributes into the svg renderer
rgbecker
parents: 3631
diff changeset
   439
    def roundRect(self, x1,y1, x2,y2, rx=8, ry=8, link_info=None, **_svgAttrs):
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   440
        """Draw a rounded rectangle between x1,y1 and x2,y2.
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1670
diff changeset
   441
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1670
diff changeset
   442
        Corners inset as ellipses with x-radius rx and y-radius ry.
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   443
        These should have x1<x2, y1<y2, rx>0, and ry>0.
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   444
        """
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   445
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1670
diff changeset
   446
        rect = transformNode(self.doc, "rect",
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1670
diff changeset
   447
            x=x1, y=y1, width=x2-x1, height=y2-y1, rx=rx, ry=ry,
3632
401542b8679b support for passing attributes into the svg renderer
rgbecker
parents: 3631
diff changeset
   448
            style=self._formatStyle(AREA_STYLES), **_svgAttrs)
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   449
3632
401542b8679b support for passing attributes into the svg renderer
rgbecker
parents: 3631
diff changeset
   450
        if link_info:
3114
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   451
            rect = self._add_link(rect, link_info)
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   452
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   453
        self.currGroup.appendChild(rect)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   454
3635
5e6f12790777 more support for passing stuff through to SVG
rgbecker
parents: 3632
diff changeset
   455
    def drawString(self, s, x, y, angle=0, link_info=None,**_svgAttrs):
3986
b807927d18c9 renderSVG.py: fix drawString & test funcs
robin
parents: 3924
diff changeset
   456
        s = asNative(s)
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3644
diff changeset
   457
        if self.verbose: print("+++ SVGCanvas.drawString")
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   458
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   459
        if self._fillColor != None:
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   460
            s = self._escape(s)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   461
            st = self._formatStyle(TEXT_STYLES)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   462
            if angle != 0:
4385
e4da72e381d5 allow fp_str rendering in renderSVG
robin <robin@reportlab.com>
parents: 4367
diff changeset
   463
               st = st + " rotate(%s);" % self.fp_str(angle, x, y)
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   464
            st = st + " fill: %s;" % self.style['fill']
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1670
diff changeset
   465
            text = transformNode(self.doc, "text",
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1670
diff changeset
   466
                x=x, y=y, style=st,
3635
5e6f12790777 more support for passing stuff through to SVG
rgbecker
parents: 3632
diff changeset
   467
                transform="translate(0,%d) scale(1,-1)" % (2*y),
5e6f12790777 more support for passing stuff through to SVG
rgbecker
parents: 3632
diff changeset
   468
                **_svgAttrs
5e6f12790777 more support for passing stuff through to SVG
rgbecker
parents: 3632
diff changeset
   469
                )
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   470
            content = self.doc.createTextNode(s)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   471
            text.appendChild(content)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   472
3114
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   473
            if link_info:
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   474
                text = self._add_link(text, link_info)
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   475
    
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   476
            self.currGroup.appendChild(text)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   477
3114
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   478
    def drawCentredString(self, s, x, y, angle=0, text_anchor='middle', link_info=None):
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3644
diff changeset
   479
        if self.verbose: print("+++ SVGCanvas.drawCentredString")
2574
d81949596070 reportlab: changes to accomodate barcodes
rgbecker
parents: 2553
diff changeset
   480
d81949596070 reportlab: changes to accomodate barcodes
rgbecker
parents: 2553
diff changeset
   481
        if self._fillColor != None:
d81949596070 reportlab: changes to accomodate barcodes
rgbecker
parents: 2553
diff changeset
   482
            if not text_anchor in ['start', 'inherited']:
d81949596070 reportlab: changes to accomodate barcodes
rgbecker
parents: 2553
diff changeset
   483
                textLen = stringWidth(s,self._font,self._fontSize)
d81949596070 reportlab: changes to accomodate barcodes
rgbecker
parents: 2553
diff changeset
   484
                if text_anchor=='end':
d81949596070 reportlab: changes to accomodate barcodes
rgbecker
parents: 2553
diff changeset
   485
                    x -= textLen
d81949596070 reportlab: changes to accomodate barcodes
rgbecker
parents: 2553
diff changeset
   486
                elif text_anchor=='middle':
d81949596070 reportlab: changes to accomodate barcodes
rgbecker
parents: 2553
diff changeset
   487
                    x -= textLen/2.
3219
b28d6eef8227 reportlab: add support for String anchor 'numeric'
rgbecker
parents: 3128
diff changeset
   488
                elif text_anchor=='numeric':
b28d6eef8227 reportlab: add support for String anchor 'numeric'
rgbecker
parents: 3128
diff changeset
   489
                    x -= numericXShift(text_anchor,s,textLen,self._font,self._fontSize)
2574
d81949596070 reportlab: changes to accomodate barcodes
rgbecker
parents: 2553
diff changeset
   490
                else:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3644
diff changeset
   491
                    raise ValueError('bad value for text_anchor ' + str(text_anchor))
4474
066480f7a206 improve log axis ticking; version --> 3.5.11
robin <robin@reportlab.com>
parents: 4385
diff changeset
   492
        self.drawString(s,x,y,angle=angle, link_info=link_info)
2574
d81949596070 reportlab: changes to accomodate barcodes
rgbecker
parents: 2553
diff changeset
   493
3114
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   494
    def drawRightString(self, text, x, y, angle=0, link_info=None):
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   495
        self.drawCentredString(text,x,y,angle=angle,text_anchor='end', link_info=link_info)
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   496
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   497
    def comment(self, data):
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   498
        "Add a comment."
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   499
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   500
        comment = self.doc.createComment(data)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   501
        # self.currGroup.appendChild(comment)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   502
4303
1dbe6269e831 improved support for images in renderPM/renderSVG bug report from Claude Paroz; version --> 3.3.26
robin
parents: 4283
diff changeset
   503
    def drawImage(self, image, x, y, width, height, embed=True):
1dbe6269e831 improved support for images in renderPM/renderSVG bug report from Claude Paroz; version --> 3.3.26
robin
parents: 4283
diff changeset
   504
        buf = getBytesIO()
1dbe6269e831 improved support for images in renderPM/renderSVG bug report from Claude Paroz; version --> 3.3.26
robin
parents: 4283
diff changeset
   505
        image.save(buf,'png')
1dbe6269e831 improved support for images in renderPM/renderSVG bug report from Claude Paroz; version --> 3.3.26
robin
parents: 4283
diff changeset
   506
        buf = asNative(base64.b64encode(buf.getvalue()))
1dbe6269e831 improved support for images in renderPM/renderSVG bug report from Claude Paroz; version --> 3.3.26
robin
parents: 4283
diff changeset
   507
        self.currGroup.appendChild(
1dbe6269e831 improved support for images in renderPM/renderSVG bug report from Claude Paroz; version --> 3.3.26
robin
parents: 4283
diff changeset
   508
                transformNode(self.doc,'image',
1dbe6269e831 improved support for images in renderPM/renderSVG bug report from Claude Paroz; version --> 3.3.26
robin
parents: 4283
diff changeset
   509
                    x=x,y=y,width=width,height=height,
1dbe6269e831 improved support for images in renderPM/renderSVG bug report from Claude Paroz; version --> 3.3.26
robin
parents: 4283
diff changeset
   510
                    href="data:image/png;base64,"+buf,
1dbe6269e831 improved support for images in renderPM/renderSVG bug report from Claude Paroz; version --> 3.3.26
robin
parents: 4283
diff changeset
   511
                    )
1dbe6269e831 improved support for images in renderPM/renderSVG bug report from Claude Paroz; version --> 3.3.26
robin
parents: 4283
diff changeset
   512
                )
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   513
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   514
    def line(self, x1, y1, x2, y2):
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   515
        if self._strokeColor != None:
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   516
            if 0: # something is wrong with line in my SVG viewer...
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1670
diff changeset
   517
                line = transformNode(self.doc, "line",
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1670
diff changeset
   518
                    x=x1, y=y1, x2=x2, y2=y2,
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   519
                    style=self._formatStyle(LINE_STYLES))
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   520
                self.currGroup.appendChild(line)
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1670
diff changeset
   521
            path = transformNode(self.doc, "path",
4385
e4da72e381d5 allow fp_str rendering in renderSVG
robin <robin@reportlab.com>
parents: 4367
diff changeset
   522
                d="M %s L %s Z" % (self.cfp_str(x1,y1),self.cfp_str(x2,y2)),
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   523
                style=self._formatStyle(LINE_STYLES))
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   524
            self.currGroup.appendChild(path)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   525
3114
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   526
    def ellipse(self, x1, y1, x2, y2, link_info=None):
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   527
        """Draw an orthogonal ellipse inscribed within the rectangle x1,y1,x2,y2.
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1670
diff changeset
   528
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   529
        These should have x1<x2 and y1<y2.
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   530
        """
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1670
diff changeset
   531
        ellipse = transformNode(self.doc, "ellipse",
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1670
diff changeset
   532
            cx=(x1+x2)/2.0, cy=(y1+y2)/2.0, rx=(x2-x1)/2.0, ry=(y2-y1)/2.0,
3370
0783797d9871 graphics.py: adjust renderPM test and fix renderSVG PolyLine
rgbecker
parents: 3358
diff changeset
   533
            style=self._formatStyle(AREA_STYLES))
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   534
3114
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   535
        if link_info:
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   536
            ellipse = self._add_link(ellipse, link_info)
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   537
            
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   538
        self.currGroup.appendChild(ellipse)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   539
3114
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   540
    def circle(self, xc, yc, r, link_info=None):
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1670
diff changeset
   541
        circle = transformNode(self.doc, "circle",
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1670
diff changeset
   542
            cx=xc, cy=yc, r=r,
3370
0783797d9871 graphics.py: adjust renderPM test and fix renderSVG PolyLine
rgbecker
parents: 3358
diff changeset
   543
            style=self._formatStyle(AREA_STYLES))
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   544
3114
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   545
        if link_info:
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   546
            circle = self._add_link(circle, link_info)
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   547
        
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   548
        self.currGroup.appendChild(circle)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   549
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   550
    def drawCurve(self, x1, y1, x2, y2, x3, y3, x4, y4, closed=0):
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   551
        pass
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   552
        return
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   553
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   554
        codeline = '%s m %s curveto'
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   555
        data = (fp_str(x1, y1), fp_str(x2, y2, x3, y3, x4, y4))
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   556
        if self._fillColor != None:
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   557
            self.code.append((codeline % data) + ' eofill')
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   558
        if self._strokeColor != None:
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   559
            self.code.append((codeline % data)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   560
                            + ((closed and ' closepath') or '')
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   561
                            + ' stroke')
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   562
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   563
    def drawArc(self, x1,y1, x2,y2, startAng=0, extent=360, fromcenter=0):
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   564
        """Draw a partial ellipse inscribed within the rectangle x1,y1,x2,y2.
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   565
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1670
diff changeset
   566
        Starting at startAng degrees and covering extent degrees. Angles
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   567
        start with 0 to the right (+x) and increase counter-clockwise.
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   568
        These should have x1<x2 and y1<y2.
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   569
        """
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   570
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   571
        cx, cy = (x1+x2)/2.0, (y1+y2)/2.0
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   572
        rx, ry = (x2-x1)/2.0, (y2-y1)/2.0
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   573
        mx = rx * cos(startAng*pi/180) + cx
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   574
        my = ry * sin(startAng*pi/180) + cy
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   575
        ax = rx * cos((startAng+extent)*pi/180) + cx
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   576
        ay = ry * sin((startAng+extent)*pi/180) + cy
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   577
4385
e4da72e381d5 allow fp_str rendering in renderSVG
robin <robin@reportlab.com>
parents: 4367
diff changeset
   578
        cfp_str = self.cfp_str
e4da72e381d5 allow fp_str rendering in renderSVG
robin <robin@reportlab.com>
parents: 4367
diff changeset
   579
        s = [].append
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   580
        if fromcenter:
4385
e4da72e381d5 allow fp_str rendering in renderSVG
robin <robin@reportlab.com>
parents: 4367
diff changeset
   581
            s("M %s L %s" % (cfp_str(cx, cy), cfp_str(ax, ay)))
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   582
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   583
        if fromcenter:
4385
e4da72e381d5 allow fp_str rendering in renderSVG
robin <robin@reportlab.com>
parents: 4367
diff changeset
   584
            s("A %s %d %d %d %s" % \
e4da72e381d5 allow fp_str rendering in renderSVG
robin <robin@reportlab.com>
parents: 4367
diff changeset
   585
              (cfp_str(rx, ry), 0, extent>=180, 0, cfp_str(mx, my)))
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   586
        else:
4385
e4da72e381d5 allow fp_str rendering in renderSVG
robin <robin@reportlab.com>
parents: 4367
diff changeset
   587
            s("M %s A %s %d %d %d %s Z" % \
e4da72e381d5 allow fp_str rendering in renderSVG
robin <robin@reportlab.com>
parents: 4367
diff changeset
   588
              (cfp_str(mx, my), cfp_str(rx, ry), 0, extent>=180, 0, cfp_str(mx, my)))
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   589
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   590
        if fromcenter:
4385
e4da72e381d5 allow fp_str rendering in renderSVG
robin <robin@reportlab.com>
parents: 4367
diff changeset
   591
            s("L %s Z" % cfp_str(cx, cy))
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   592
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1670
diff changeset
   593
        path = transformNode(self.doc, "path",
4385
e4da72e381d5 allow fp_str rendering in renderSVG
robin <robin@reportlab.com>
parents: 4367
diff changeset
   594
            d=' '.join(s.__self__), style=self._formatStyle())
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   595
        self.currGroup.appendChild(path)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   596
3114
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   597
    def polygon(self, points, closed=0, link_info=None):
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   598
        assert len(points) >= 2, 'Polygon must have 2 or more points'
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   599
4325
fc03e6396da5 add support for fillMode in drawing stack; version-->3.3.34
robin <robin@reportlab.com>
parents: 4306
diff changeset
   600
        if self._strokeColor!=None or self._fillColor!=None:
4385
e4da72e381d5 allow fp_str rendering in renderSVG
robin <robin@reportlab.com>
parents: 4367
diff changeset
   601
            pts = ', '.join([fp_str(*p) for p in points])
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1670
diff changeset
   602
            polyline = transformNode(self.doc, "polygon",
3370
0783797d9871 graphics.py: adjust renderPM test and fix renderSVG PolyLine
rgbecker
parents: 3358
diff changeset
   603
                points=pts, style=self._formatStyle(AREA_STYLES))
3114
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   604
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   605
            if link_info:
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   606
                polyline = self._add_link(polyline, link_info)
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   607
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   608
            self.currGroup.appendChild(polyline)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   609
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   610
        # self._fillAndStroke(polyCode)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   611
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   612
    def lines(self, lineList, color=None, width=None):
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   613
        # print "### lineList", lineList
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   614
        return
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   615
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   616
        if self._strokeColor != None:
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   617
            codeline = '%s m %s l stroke'
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   618
            for line in lineList:
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   619
                self.code.append(codeline % (fp_str(line[0]), fp_str(line[1])))
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   620
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   621
    def polyLine(self, points):
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   622
        assert len(points) >= 1, 'Polyline must have 1 or more points'
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   623
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   624
        if self._strokeColor != None:
4385
e4da72e381d5 allow fp_str rendering in renderSVG
robin <robin@reportlab.com>
parents: 4367
diff changeset
   625
            pts = ', '.join([fp_str(*p) for p in points])
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1670
diff changeset
   626
            polyline = transformNode(self.doc, "polyline",
3370
0783797d9871 graphics.py: adjust renderPM test and fix renderSVG PolyLine
rgbecker
parents: 3358
diff changeset
   627
                points=pts, style=self._formatStyle(AREA_STYLES,fill=None))
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   628
            self.currGroup.appendChild(polyline)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   629
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   630
    ### groups ###
4474
066480f7a206 improve log axis ticking; version --> 3.5.11
robin <robin@reportlab.com>
parents: 4385
diff changeset
   631
    def startGroup(self,attrDict=dict(transform="")):
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3644
diff changeset
   632
        if self.verbose: print("+++ begin SVGCanvas.startGroup")
4474
066480f7a206 improve log axis ticking; version --> 3.5.11
robin <robin@reportlab.com>
parents: 4385
diff changeset
   633
        currGroup = self.currGroup
066480f7a206 improve log axis ticking; version --> 3.5.11
robin <robin@reportlab.com>
parents: 4385
diff changeset
   634
        group = transformNode(self.doc, "g", **attrDict)
1648
64ffdd1963a7 Apparent fix for transform problem
rgbecker
parents: 1644
diff changeset
   635
        currGroup.appendChild(group)
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   636
        self.currGroup = group
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3644
diff changeset
   637
        if self.verbose: print("+++ end SVGCanvas.startGroup")
1648
64ffdd1963a7 Apparent fix for transform problem
rgbecker
parents: 1644
diff changeset
   638
        return currGroup
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   639
1648
64ffdd1963a7 Apparent fix for transform problem
rgbecker
parents: 1644
diff changeset
   640
    def endGroup(self,currGroup):
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3644
diff changeset
   641
        if self.verbose: print("+++ begin SVGCanvas.endGroup")
1648
64ffdd1963a7 Apparent fix for transform problem
rgbecker
parents: 1644
diff changeset
   642
        self.currGroup = currGroup
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3644
diff changeset
   643
        if self.verbose: print("+++ end SVGCanvas.endGroup")
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   644
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   645
    def transform(self, a, b, c, d, e, f):
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3644
diff changeset
   646
        if self.verbose: print("!!! begin SVGCanvas.transform", a, b, c, d, e, f)
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   647
        tr = self.currGroup.getAttribute("transform")
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   648
        if (a, b, c, d, e, f) != (1, 0, 0, 1, 0, 0):
4385
e4da72e381d5 allow fp_str rendering in renderSVG
robin <robin@reportlab.com>
parents: 4367
diff changeset
   649
            t = 'matrix(%s)' % self.cfp_str(a,b,c,d,e,f)
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   650
            self.currGroup.setAttribute("transform", "%s %s" % (tr, t))
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   651
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   652
    def translate(self, x, y):
4474
066480f7a206 improve log axis ticking; version --> 3.5.11
robin <robin@reportlab.com>
parents: 4385
diff changeset
   653
        if (x,y) != (0,0):
066480f7a206 improve log axis ticking; version --> 3.5.11
robin <robin@reportlab.com>
parents: 4385
diff changeset
   654
            self.currGroup.setAttribute("transform", "%s %s"
066480f7a206 improve log axis ticking; version --> 3.5.11
robin <robin@reportlab.com>
parents: 4385
diff changeset
   655
                % (self.currGroup.getAttribute("transform"),
066480f7a206 improve log axis ticking; version --> 3.5.11
robin <robin@reportlab.com>
parents: 4385
diff changeset
   656
                    'translate(%s)' % self.cfp_str(x,y)))
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   657
4474
066480f7a206 improve log axis ticking; version --> 3.5.11
robin <robin@reportlab.com>
parents: 4385
diff changeset
   658
    def scale(self, sx, sy):
066480f7a206 improve log axis ticking; version --> 3.5.11
robin <robin@reportlab.com>
parents: 4385
diff changeset
   659
        if (sx,sy) != (1,1):
066480f7a206 improve log axis ticking; version --> 3.5.11
robin <robin@reportlab.com>
parents: 4385
diff changeset
   660
            self.currGroup.setAttribute("transform", "%s %s" 
066480f7a206 improve log axis ticking; version --> 3.5.11
robin <robin@reportlab.com>
parents: 4385
diff changeset
   661
                    % (self.groups[-1].getAttribute("transform"),
066480f7a206 improve log axis ticking; version --> 3.5.11
robin <robin@reportlab.com>
parents: 4385
diff changeset
   662
                        'scale(%s)' % self.cfp_str(sx, sy)))
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   663
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   664
    ### paths ###
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   665
    def moveTo(self, x, y):
4385
e4da72e381d5 allow fp_str rendering in renderSVG
robin <robin@reportlab.com>
parents: 4367
diff changeset
   666
        self.path = self.path + 'M %s ' % self.fp_str(x, y)
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   667
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   668
    def lineTo(self, x, y):
4385
e4da72e381d5 allow fp_str rendering in renderSVG
robin <robin@reportlab.com>
parents: 4367
diff changeset
   669
        self.path = self.path + 'L %s ' % self.fp_str(x, y)
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   670
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   671
    def curveTo(self, x1, y1, x2, y2, x3, y3):
4385
e4da72e381d5 allow fp_str rendering in renderSVG
robin <robin@reportlab.com>
parents: 4367
diff changeset
   672
        self.path = self.path + 'C %s ' % self.fp_str(x1, y1, x2, y2, x3, y3)
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   673
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   674
    def closePath(self):
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   675
        self.path = self.path + 'Z '
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   676
2360
0fbaee224de1 rl_config add _unset_, graphics.renderxxx refactoring
rgbecker
parents: 1744
diff changeset
   677
    def saveState(self):
0fbaee224de1 rl_config add _unset_, graphics.renderxxx refactoring
rgbecker
parents: 1744
diff changeset
   678
        pass
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   679
2360
0fbaee224de1 rl_config add _unset_, graphics.renderxxx refactoring
rgbecker
parents: 1744
diff changeset
   680
    def restoreState(self):
0fbaee224de1 rl_config add _unset_, graphics.renderxxx refactoring
rgbecker
parents: 1744
diff changeset
   681
        pass
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   682
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   683
class _SVGRenderer(Renderer):
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   684
    """This draws onto an SVG document.
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   685
    """
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   686
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   687
    def __init__(self):
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   688
        self.verbose = 0
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   689
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   690
    def drawNode(self, node):
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   691
        """This is the recursive method called for each node in the tree.
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   692
        """
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   693
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3644
diff changeset
   694
        if self.verbose: print("### begin _SVGRenderer.drawNode(%r)" % node)
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   695
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3219
diff changeset
   696
        self._canvas.comment('begin node %r'%node)
3114
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   697
        style = self._canvas.style.copy()
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   698
        if not (isinstance(node, Path) and node.isClipPath):
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   699
            pass # self._canvas.saveState()
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   700
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   701
        #apply state changes
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   702
        deltas = getStateDelta(node)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   703
        self._tracker.push(deltas)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   704
        self.applyStateChanges(deltas, {})
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   705
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   706
        #draw the object, or recurse
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   707
        self.drawNodeDispatcher(node)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   708
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   709
        rDeltas = self._tracker.pop()
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   710
        if not (isinstance(node, Path) and node.isClipPath):
3114
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   711
            pass #self._canvas.restoreState()
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3219
diff changeset
   712
        self._canvas.comment('end node %r'%node)
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   713
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   714
        #restore things we might have lost (without actually doing anything).
3723
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   715
        for k, v in rDeltas.items():
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3219
diff changeset
   716
            if k in self._restores:
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   717
                setattr(self._canvas,self._restores[k],v)
3114
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   718
        self._canvas.style = style
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   719
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3644
diff changeset
   720
        if self.verbose: print("### end _SVGRenderer.drawNode(%r)" % node)
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   721
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   722
    _restores = {'strokeColor':'_strokeColor','strokeWidth': '_lineWidth','strokeLineCap':'_lineCap',
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   723
                'strokeLineJoin':'_lineJoin','fillColor':'_fillColor','fontName':'_font',
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   724
                'fontSize':'_fontSize'}
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   725
3114
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   726
    def _get_link_info_dict(self, obj):
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   727
        #We do not want None or False as the link, even if it is the
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   728
        #attribute's value - use the empty string instead.
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   729
        url = getattr(obj, "hrefURL", "") or ""
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   730
        title = getattr(obj, "hrefTitle", "") or ""
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   731
        if url :
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   732
            #Is it valid to have a link with no href?  The XML requires
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   733
            #the xlink:href to be present, but you might just want a
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   734
            #tool tip shown (via the xlink:title attribute).  Note that
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   735
            #giving an href of "" is equivalent to "the current page"
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   736
            #(a relative link saying go nowhere).
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   737
            return {"xlink:href":url, "xlink:title":title, "target":"_top"}
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   738
            #Currently of all the mainstream browsers I have tested, only Safari/webkit
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   739
            #will show  SVG images embedded in HTML using a simple <img src="..." /> tag.
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   740
            #However, the links don't work (Safari 3.2.1 on the Mac).
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   741
            #
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   742
            #Therefore I use the following, which also works for Firefox, Opera, and
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   743
            #IE 6.0 with Adobe SVG Viewer 6 beta:
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   744
            #<object data="..." type="image/svg+xml" width="430" height="150" class="img">
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   745
            #
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   746
            #Once displayed, Firefox and Safari treat the SVG like a frame, and
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   747
            #by default clicking on links acts "in frame" and replaces the image.
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   748
            #Opera does what I expect, and replaces the whole page with the link.
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   749
            #
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   750
            #Therefore I use target="_top" to force the links to replace the whole page.
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   751
            #This now works as expected on Safari 3.2.1, Firefox 3.0.6, Opera 9.20. 
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   752
            #Perhaps the target attribute should be an option, perhaps defaulting to
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   753
            #"_top" as used here?
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   754
        else :
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   755
            return None
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   756
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   757
    def drawGroup(self, group):
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3644
diff changeset
   758
        if self.verbose: print("### begin _SVGRenderer.drawGroup")
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   759
1648
64ffdd1963a7 Apparent fix for transform problem
rgbecker
parents: 1644
diff changeset
   760
        currGroup = self._canvas.startGroup()
3056
3ce50e421931 reportlab.graphics.renderSVG: Fixed bug 704.
jonas
parents: 3032
diff changeset
   761
        a, b, c, d, e, f = self._tracker.getState()['transform']
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   762
        for childNode in group.getContents():
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   763
            if isinstance(childNode, UserNode):
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   764
                node2 = childNode.provideNode()
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   765
            else:
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   766
                node2 = childNode
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   767
            self.drawNode(node2)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   768
        self._canvas.transform(a, b, c, d, e, f)
1648
64ffdd1963a7 Apparent fix for transform problem
rgbecker
parents: 1644
diff changeset
   769
        self._canvas.endGroup(currGroup)
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   770
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3644
diff changeset
   771
        if self.verbose: print("### end _SVGRenderer.drawGroup")
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   772
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   773
    def drawRect(self, rect):
3114
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   774
        link_info = self._get_link_info_dict(rect)
3632
401542b8679b support for passing attributes into the svg renderer
rgbecker
parents: 3631
diff changeset
   775
        svgAttrs = getattr(rect,'_svgAttrs',{})
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   776
        if rect.rx == rect.ry == 0:
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   777
            #plain old rectangle
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   778
            self._canvas.rect(
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   779
                    rect.x, rect.y,
3632
401542b8679b support for passing attributes into the svg renderer
rgbecker
parents: 3631
diff changeset
   780
                    rect.x+rect.width, rect.y+rect.height, link_info=link_info, **svgAttrs)
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   781
        else:
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   782
            #cheat and assume ry = rx; better to generalize
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   783
            #pdfgen roundRect function.  TODO
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   784
            self._canvas.roundRect(
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   785
                    rect.x, rect.y,
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1670
diff changeset
   786
                    rect.x+rect.width, rect.y+rect.height,
3114
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   787
                    rect.rx, rect.ry,
3632
401542b8679b support for passing attributes into the svg renderer
rgbecker
parents: 3631
diff changeset
   788
                    link_info=link_info, **svgAttrs)
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   789
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   790
    def drawString(self, stringObj):
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   791
        if self._canvas._fillColor:
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   792
            S = self._tracker.getState()
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   793
            text_anchor, x, y, text = S['textAnchor'], stringObj.x, stringObj.y, stringObj.text
3219
b28d6eef8227 reportlab: add support for String anchor 'numeric'
rgbecker
parents: 3128
diff changeset
   794
            if not text_anchor in ('start', 'inherited'):
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1670
diff changeset
   795
                font, fontSize = S['fontName'], S['fontSize']
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   796
                textLen = stringWidth(text, font,fontSize)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   797
                if text_anchor=='end':
3219
b28d6eef8227 reportlab: add support for String anchor 'numeric'
rgbecker
parents: 3128
diff changeset
   798
                    x -= textLen
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   799
                elif text_anchor=='middle':
3219
b28d6eef8227 reportlab: add support for String anchor 'numeric'
rgbecker
parents: 3128
diff changeset
   800
                    x -= textLen/2
b28d6eef8227 reportlab: add support for String anchor 'numeric'
rgbecker
parents: 3128
diff changeset
   801
                elif text_anchor=='numeric':
b28d6eef8227 reportlab: add support for String anchor 'numeric'
rgbecker
parents: 3128
diff changeset
   802
                    x -= numericXShift(text_anchor,text,textLen,font,fontSize)
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   803
                else:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3644
diff changeset
   804
                    raise ValueError('bad value for text_anchor ' + str(text_anchor))
3635
5e6f12790777 more support for passing stuff through to SVG
rgbecker
parents: 3632
diff changeset
   805
            self._canvas.drawString(text,x,y,link_info=self._get_link_info_dict(stringObj),**getattr(stringObj,'_svgAttrs',{}))
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   806
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   807
    def drawLine(self, line):
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   808
        if self._canvas._strokeColor:
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   809
            self._canvas.line(line.x1, line.y1, line.x2, line.y2)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   810
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   811
    def drawCircle(self, circle):
3114
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   812
        self._canvas.circle( circle.cx, circle.cy, circle.r, link_info=self._get_link_info_dict(circle))
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   813
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   814
    def drawWedge(self, wedge):
4132
28379377462b fix doughnut chart special case and how it is drawn; bump to 3.1.31
robin
parents: 3986
diff changeset
   815
        yradius, radius1, yradius1 = wedge._xtraRadii()
28379377462b fix doughnut chart special case and how it is drawn; bump to 3.1.31
robin
parents: 3986
diff changeset
   816
        if (radius1==0 or radius1 is None) and (yradius1==0 or yradius1 is None) and not wedge.annular:
28379377462b fix doughnut chart special case and how it is drawn; bump to 3.1.31
robin
parents: 3986
diff changeset
   817
            centerx, centery, radius, startangledegrees, endangledegrees = \
28379377462b fix doughnut chart special case and how it is drawn; bump to 3.1.31
robin
parents: 3986
diff changeset
   818
             wedge.centerx, wedge.centery, wedge.radius, wedge.startangledegrees, wedge.endangledegrees
28379377462b fix doughnut chart special case and how it is drawn; bump to 3.1.31
robin
parents: 3986
diff changeset
   819
            yradius = wedge.yradius or wedge.radius
28379377462b fix doughnut chart special case and how it is drawn; bump to 3.1.31
robin
parents: 3986
diff changeset
   820
            (x1, y1) = (centerx-radius, centery-yradius)
28379377462b fix doughnut chart special case and how it is drawn; bump to 3.1.31
robin
parents: 3986
diff changeset
   821
            (x2, y2) = (centerx+radius, centery+yradius)
28379377462b fix doughnut chart special case and how it is drawn; bump to 3.1.31
robin
parents: 3986
diff changeset
   822
            extent = endangledegrees - startangledegrees
28379377462b fix doughnut chart special case and how it is drawn; bump to 3.1.31
robin
parents: 3986
diff changeset
   823
            self._canvas.drawArc(x1, y1, x2, y2, startangledegrees, extent, fromcenter=1)
28379377462b fix doughnut chart special case and how it is drawn; bump to 3.1.31
robin
parents: 3986
diff changeset
   824
        else:
28379377462b fix doughnut chart special case and how it is drawn; bump to 3.1.31
robin
parents: 3986
diff changeset
   825
            P = wedge.asPolygon()
28379377462b fix doughnut chart special case and how it is drawn; bump to 3.1.31
robin
parents: 3986
diff changeset
   826
            if isinstance(P,Path):
28379377462b fix doughnut chart special case and how it is drawn; bump to 3.1.31
robin
parents: 3986
diff changeset
   827
                self.drawPath(P)
28379377462b fix doughnut chart special case and how it is drawn; bump to 3.1.31
robin
parents: 3986
diff changeset
   828
            else:
28379377462b fix doughnut chart special case and how it is drawn; bump to 3.1.31
robin
parents: 3986
diff changeset
   829
                self.drawPolygon(P)
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   830
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   831
    def drawPolyLine(self, p):
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   832
        if self._canvas._strokeColor:
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   833
            self._canvas.polyLine(_pointsFromList(p.points))
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   834
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   835
    def drawEllipse(self, ellipse):
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   836
        #need to convert to pdfgen's bounding box representation
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   837
        x1 = ellipse.cx - ellipse.rx
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   838
        x2 = ellipse.cx + ellipse.rx
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   839
        y1 = ellipse.cy - ellipse.ry
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   840
        y2 = ellipse.cy + ellipse.ry
3114
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   841
        self._canvas.ellipse(x1,y1,x2,y2, link_info=self._get_link_info_dict(ellipse))
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   842
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   843
    def drawPolygon(self, p):
3114
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   844
        self._canvas.polygon(_pointsFromList(p.points), closed=1, link_info=self._get_link_info_dict(p))
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   845
4306
8ffb2ffc283b support for Path autoclose & fillMode; version --> 3.3.29
robin
parents: 4303
diff changeset
   846
    def drawPath(self, path, fillMode=None):
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   847
        # print "### drawPath", path.points
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   848
        from reportlab.graphics.shapes import _renderPath
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   849
        c = self._canvas
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   850
        drawFuncs = (c.moveTo, c.lineTo, c.curveTo, c.closePath)
4306
8ffb2ffc283b support for Path autoclose & fillMode; version --> 3.3.29
robin
parents: 4303
diff changeset
   851
        if fillMode is None:
8ffb2ffc283b support for Path autoclose & fillMode; version --> 3.3.29
robin
parents: 4303
diff changeset
   852
            fillMode = getattr(path,'fillMode',None)
8ffb2ffc283b support for Path autoclose & fillMode; version --> 3.3.29
robin
parents: 4303
diff changeset
   853
        link_info = self._get_link_info_dict(path)
8ffb2ffc283b support for Path autoclose & fillMode; version --> 3.3.29
robin
parents: 4303
diff changeset
   854
        autoclose = getattr(path,'autoclose','')
8ffb2ffc283b support for Path autoclose & fillMode; version --> 3.3.29
robin
parents: 4303
diff changeset
   855
        def rP(**kwds):
8ffb2ffc283b support for Path autoclose & fillMode; version --> 3.3.29
robin
parents: 4303
diff changeset
   856
            return _renderPath(path, drawFuncs, **kwds)
8ffb2ffc283b support for Path autoclose & fillMode; version --> 3.3.29
robin
parents: 4303
diff changeset
   857
        if autoclose=='svg':
8ffb2ffc283b support for Path autoclose & fillMode; version --> 3.3.29
robin
parents: 4303
diff changeset
   858
            rP()
8ffb2ffc283b support for Path autoclose & fillMode; version --> 3.3.29
robin
parents: 4303
diff changeset
   859
            c._fillAndStroke([], clip=path.isClipPath, link_info=link_info, fillMode=fillMode)
8ffb2ffc283b support for Path autoclose & fillMode; version --> 3.3.29
robin
parents: 4303
diff changeset
   860
        elif autoclose=='pdf':
8ffb2ffc283b support for Path autoclose & fillMode; version --> 3.3.29
robin
parents: 4303
diff changeset
   861
            rP(forceClose=True)
8ffb2ffc283b support for Path autoclose & fillMode; version --> 3.3.29
robin
parents: 4303
diff changeset
   862
            c._fillAndStroke([], clip=path.isClipPath, link_info=link_info, fillMode=fillMode)
8ffb2ffc283b support for Path autoclose & fillMode; version --> 3.3.29
robin
parents: 4303
diff changeset
   863
        else:
8ffb2ffc283b support for Path autoclose & fillMode; version --> 3.3.29
robin
parents: 4303
diff changeset
   864
            isClosed = rP()
8ffb2ffc283b support for Path autoclose & fillMode; version --> 3.3.29
robin
parents: 4303
diff changeset
   865
            if not isClosed:
8ffb2ffc283b support for Path autoclose & fillMode; version --> 3.3.29
robin
parents: 4303
diff changeset
   866
                ofc = c._fillColor
8ffb2ffc283b support for Path autoclose & fillMode; version --> 3.3.29
robin
parents: 4303
diff changeset
   867
                c.setFillColor(None)
8ffb2ffc283b support for Path autoclose & fillMode; version --> 3.3.29
robin
parents: 4303
diff changeset
   868
                try:
8ffb2ffc283b support for Path autoclose & fillMode; version --> 3.3.29
robin
parents: 4303
diff changeset
   869
                    link_info = None
8ffb2ffc283b support for Path autoclose & fillMode; version --> 3.3.29
robin
parents: 4303
diff changeset
   870
                    c._fillAndStroke([], clip=path.isClipPath, link_info=link_info, fillMode=fillMode)
8ffb2ffc283b support for Path autoclose & fillMode; version --> 3.3.29
robin
parents: 4303
diff changeset
   871
                finally:
8ffb2ffc283b support for Path autoclose & fillMode; version --> 3.3.29
robin
parents: 4303
diff changeset
   872
                    c.setFillColor(ofc)
8ffb2ffc283b support for Path autoclose & fillMode; version --> 3.3.29
robin
parents: 4303
diff changeset
   873
            else:
8ffb2ffc283b support for Path autoclose & fillMode; version --> 3.3.29
robin
parents: 4303
diff changeset
   874
                c._fillAndStroke([], clip=path.isClipPath, link_info=link_info, fillMode=fillMode)
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   875
4303
1dbe6269e831 improved support for images in renderPM/renderSVG bug report from Claude Paroz; version --> 3.3.26
robin
parents: 4283
diff changeset
   876
    def drawImage(self, image):
1dbe6269e831 improved support for images in renderPM/renderSVG bug report from Claude Paroz; version --> 3.3.26
robin
parents: 4283
diff changeset
   877
        path = image.path
1dbe6269e831 improved support for images in renderPM/renderSVG bug report from Claude Paroz; version --> 3.3.26
robin
parents: 4283
diff changeset
   878
        if isinstance(path,str):
1dbe6269e831 improved support for images in renderPM/renderSVG bug report from Claude Paroz; version --> 3.3.26
robin
parents: 4283
diff changeset
   879
            if not (path and os.path.isfile(path)): return
1dbe6269e831 improved support for images in renderPM/renderSVG bug report from Claude Paroz; version --> 3.3.26
robin
parents: 4283
diff changeset
   880
            im = _getImage().open(path)
1dbe6269e831 improved support for images in renderPM/renderSVG bug report from Claude Paroz; version --> 3.3.26
robin
parents: 4283
diff changeset
   881
        elif hasattr(path,'convert'):
1dbe6269e831 improved support for images in renderPM/renderSVG bug report from Claude Paroz; version --> 3.3.26
robin
parents: 4283
diff changeset
   882
            im = path
1dbe6269e831 improved support for images in renderPM/renderSVG bug report from Claude Paroz; version --> 3.3.26
robin
parents: 4283
diff changeset
   883
        else:
1dbe6269e831 improved support for images in renderPM/renderSVG bug report from Claude Paroz; version --> 3.3.26
robin
parents: 4283
diff changeset
   884
            return
1dbe6269e831 improved support for images in renderPM/renderSVG bug report from Claude Paroz; version --> 3.3.26
robin
parents: 4283
diff changeset
   885
        srcW, srcH = im.size
1dbe6269e831 improved support for images in renderPM/renderSVG bug report from Claude Paroz; version --> 3.3.26
robin
parents: 4283
diff changeset
   886
        dstW, dstH = image.width, image.height
1dbe6269e831 improved support for images in renderPM/renderSVG bug report from Claude Paroz; version --> 3.3.26
robin
parents: 4283
diff changeset
   887
        if dstW is None: dstW = srcW
1dbe6269e831 improved support for images in renderPM/renderSVG bug report from Claude Paroz; version --> 3.3.26
robin
parents: 4283
diff changeset
   888
        if dstH is None: dstH = srcH
1dbe6269e831 improved support for images in renderPM/renderSVG bug report from Claude Paroz; version --> 3.3.26
robin
parents: 4283
diff changeset
   889
        self._canvas.drawImage(im, image.x, image.y, dstW, dstH, embed=True)
1dbe6269e831 improved support for images in renderPM/renderSVG bug report from Claude Paroz; version --> 3.3.26
robin
parents: 4283
diff changeset
   890
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   891
    def applyStateChanges(self, delta, newState):
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   892
        """This takes a set of states, and outputs the operators
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   893
        needed to set those properties"""
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   894
3723
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   895
        for key, value in delta.items():
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   896
            if key == 'transform':
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1670
diff changeset
   897
                pass
1648
64ffdd1963a7 Apparent fix for transform problem
rgbecker
parents: 1644
diff changeset
   898
                #self._canvas.transform(value[0], value[1], value[2], value[3], value[4], value[5])
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   899
            elif key == 'strokeColor':
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   900
                self._canvas.setStrokeColor(value)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   901
            elif key == 'strokeWidth':
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   902
                self._canvas.setLineWidth(value)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   903
            elif key == 'strokeLineCap':  #0,1,2
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   904
                self._canvas.setLineCap(value)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   905
            elif key == 'strokeLineJoin':
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   906
                self._canvas.setLineJoin(value)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   907
            elif key == 'strokeDashArray':
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   908
                if value:
3502
b2c9927314fc color fixes
rgbecker
parents: 3370
diff changeset
   909
                    if isinstance(value,(list,tuple)) and len(value)==2 and isinstance(value[1],(tuple,list)):
b2c9927314fc color fixes
rgbecker
parents: 3370
diff changeset
   910
                        phase = value[0]
b2c9927314fc color fixes
rgbecker
parents: 3370
diff changeset
   911
                        value = value[1]
b2c9927314fc color fixes
rgbecker
parents: 3370
diff changeset
   912
                    else:
b2c9927314fc color fixes
rgbecker
parents: 3370
diff changeset
   913
                        phase = 0
b2c9927314fc color fixes
rgbecker
parents: 3370
diff changeset
   914
                    self._canvas.setDash(value,phase)
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   915
                else:
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   916
                    self._canvas.setDash()
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   917
            elif key == 'fillColor':
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   918
                self._canvas.setFillColor(value)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   919
            elif key in ['fontSize', 'fontName']:
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   920
                fontname = delta.get('fontName', self._canvas._font)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   921
                fontsize = delta.get('fontSize', self._canvas._fontSize)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   922
                self._canvas.setFont(fontname, fontsize)
4325
fc03e6396da5 add support for fillMode in drawing stack; version-->3.3.34
robin <robin@reportlab.com>
parents: 4306
diff changeset
   923
            elif key == 'fillMode':
fc03e6396da5 add support for fillMode in drawing stack; version-->3.3.34
robin <robin@reportlab.com>
parents: 4306
diff changeset
   924
                self._canvas.setFillMode(value)
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   925
3986
b807927d18c9 renderSVG.py: fix drawString & test funcs
robin
parents: 3924
diff changeset
   926
def test(outDir='out-svg'):
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   927
    # print all drawings and their doc strings from the test
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   928
    # file
3986
b807927d18c9 renderSVG.py: fix drawString & test funcs
robin
parents: 3924
diff changeset
   929
    if not os.path.isdir(outDir):
b807927d18c9 renderSVG.py: fix drawString & test funcs
robin
parents: 3924
diff changeset
   930
        os.mkdir(outDir)
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   931
    #grab all drawings from the test module
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   932
    from reportlab.graphics import testshapes
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   933
    drawings = []
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   934
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   935
    for funcname in dir(testshapes):
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   936
        if funcname[0:10] == 'getDrawing':
4551
d357e2acc856 improve usage of eval/exec; version --> 3.5.32
robin
parents: 4474
diff changeset
   937
            func = getattr(testshapes,funcname)
d357e2acc856 improve usage of eval/exec; version --> 3.5.32
robin
parents: 4474
diff changeset
   938
            drawing = func()
d357e2acc856 improve usage of eval/exec; version --> 3.5.32
robin
parents: 4474
diff changeset
   939
            docstring = getattr(func,'__doc__','')
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   940
            drawings.append((drawing, docstring))
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   941
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   942
    i = 0
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   943
    for (d, docstring) in drawings:
3986
b807927d18c9 renderSVG.py: fix drawString & test funcs
robin
parents: 3924
diff changeset
   944
        filename = os.path.join(outDir,'renderSVG_%d.svg' % i)
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   945
        drawToFile(d, filename)
3114
3e5d70c382c3 renderSVG.py: add in PJACock's pacth and fix a couple of bugs
rgbecker
parents: 3096
diff changeset
   946
        i += 1
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   947
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   948
    from reportlab.graphics.testshapes import getDrawing01
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   949
    d = getDrawing01()
3986
b807927d18c9 renderSVG.py: fix drawString & test funcs
robin
parents: 3924
diff changeset
   950
    drawToFile(d, os.path.join(outDir,"test.svg"))
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   951
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   952
    from reportlab.lib.corp import RL_CorpLogo
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   953
    from reportlab.graphics.shapes import Drawing
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   954
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   955
    rl = RL_CorpLogo()
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   956
    d = Drawing(rl.width,rl.height)
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   957
    d.add(rl)
3986
b807927d18c9 renderSVG.py: fix drawString & test funcs
robin
parents: 3924
diff changeset
   958
    drawToFile(d, os.path.join(outDir,"corplogo.svg"))
1607
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   959
ab51672c5abf Initial checkin.
dinu_gherman
parents:
diff changeset
   960
if __name__=='__main__':
3986
b807927d18c9 renderSVG.py: fix drawString & test funcs
robin
parents: 3924
diff changeset
   961
    test()