src/reportlab/graphics/shapes.py
author rptlab
Tue, 30 Apr 2013 14:28:14 +0100
branchpy33
changeset 3723 99aa837b6703
parent 3721 0c93dd8ff567
child 3762 4817e577522d
permissions -rw-r--r--
second stage of port to Python 3.3; working hello world
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
3617
ae5744e97c42 reportlab: copyright date changes
robin
parents: 3543
diff changeset
     1
#Copyright ReportLab Europe Ltd. 2000-2012
814
ca2bfda4b1ab Made Drawings inherit from Group
rgbecker
parents: 810
diff changeset
     2
#see license.txt for license details
2332
2a7ab4405e18 Remove $Header:, fix CopyRight & history
rgbecker
parents: 2321
diff changeset
     3
#history http://www.reportlab.co.uk/cgi-bin/viewcvs.cgi/public/reportlab/trunk/reportlab/graphics/shapes.py
3032
22224b1b4d24 New docstrings mainly for module titles
damian
parents: 2964
diff changeset
     4
2321
3454f5b41760 Unicode and UTF8 support changes
andy
parents: 2306
diff changeset
     5
__version__=''' $Id$ '''
3032
22224b1b4d24 New docstrings mainly for module titles
damian
parents: 2964
diff changeset
     6
__doc__='''Core of the graphics library - defines Drawing and Shapes'''
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
     7
1194
4a39ee514a72 Fixed up save to use poutDir wrt sys.argv[0]
rgbecker
parents: 1184
diff changeset
     8
import string, os, sys
3541
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
     9
from math import pi, cos, sin, tan, sqrt
1411
7ce14dbd7578 Added .py save format for Drawings, seems to work
rgbecker
parents: 1388
diff changeset
    10
from types import FloatType, IntType, ListType, TupleType, StringType, InstanceType
759
f68f95c44f77 Improved Auto class.
dinu_gherman
parents: 747
diff changeset
    11
from pprint import pprint
f68f95c44f77 Improved Auto class.
dinu_gherman
parents: 747
diff changeset
    12
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
    13
from reportlab.platypus import Flowable
3368
afa025c34493 reportlab: new base font mechanism more fully applied
rgbecker
parents: 3364
diff changeset
    14
from reportlab.rl_config import shapeChecking, verbose, defaultGraphicsFontName as _baseGFontName, _unset_
1176
4ef49823ccc7 Moved saved method from Andy's datacharts.py
rgbecker
parents: 1175
diff changeset
    15
from reportlab.lib import logger
759
f68f95c44f77 Improved Auto class.
dinu_gherman
parents: 747
diff changeset
    16
from reportlab.lib import colors
909
a5ee7d2bdb17 Extracted validator functions into lib.validators.
dinu_gherman
parents: 892
diff changeset
    17
from reportlab.lib.validators import *
3280
2ac121cd0ee5 shapes.py: fix behaviour of opacity versus colour alphas
rgbecker
parents: 3272
diff changeset
    18
isOpacity = NoneOr(isNumberInRange(0,1))
948
2531b35adf85 New AttrMap emplacement
rgbecker
parents: 947
diff changeset
    19
from reportlab.lib.attrmap import *
1411
7ce14dbd7578 Added .py save format for Drawings, seems to work
rgbecker
parents: 1388
diff changeset
    20
from reportlab.lib.utils import fp_str
818
d2472224bc8b Added stringWidth import
rgbecker
parents: 816
diff changeset
    21
from reportlab.pdfbase.pdfmetrics import stringWidth
3368
afa025c34493 reportlab: new base font mechanism more fully applied
rgbecker
parents: 3364
diff changeset
    22
from reportlab.lib.fonts import tt2ps
afa025c34493 reportlab: new base font mechanism more fully applied
rgbecker
parents: 3364
diff changeset
    23
_baseGFontNameB = tt2ps(_baseGFontName,1,0)
afa025c34493 reportlab: new base font mechanism more fully applied
rgbecker
parents: 3364
diff changeset
    24
_baseGFontNameI = tt2ps(_baseGFontName,0,1)
afa025c34493 reportlab: new base font mechanism more fully applied
rgbecker
parents: 3364
diff changeset
    25
_baseGFontNameBI = tt2ps(_baseGFontName,1,1)
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
    26
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
    27
class NotImplementedError(Exception):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    28
    pass
759
f68f95c44f77 Improved Auto class.
dinu_gherman
parents: 747
diff changeset
    29
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
    30
# two constants for filling rules
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
    31
NON_ZERO_WINDING = 'Non-Zero Winding'
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
    32
EVEN_ODD = 'Even-Odd'
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
    33
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
    34
## these can be overridden at module level before you start
572
bed68d67d5d0 typos fixed
johnprecedo
parents: 568
diff changeset
    35
#creating shapes.  So, if using a special color model,
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
    36
#this provides support for the rendering mechanism.
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
    37
#you can change defaults globally before you start
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
    38
#making shapes; one use is to substitute another
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
    39
#color model cleanly throughout the drawing.
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
    40
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    41
STATE_DEFAULTS = {   # sensible defaults for all
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    42
    'transform': (1,0,0,1,0,0),
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
    43
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    44
    # styles follow SVG naming
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    45
    'strokeColor': colors.black,
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    46
    'strokeWidth': 1,
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    47
    'strokeLineCap': 0,
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    48
    'strokeLineJoin': 0,
3234
070271955526 graphics: add in some line properties
rgbecker
parents: 3224
diff changeset
    49
    'strokeMiterLimit' : 10,    # don't know yet so let bomb here
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    50
    'strokeDashArray': None,
3280
2ac121cd0ee5 shapes.py: fix behaviour of opacity versus colour alphas
rgbecker
parents: 3272
diff changeset
    51
    'strokeOpacity': None, #100%
2ac121cd0ee5 shapes.py: fix behaviour of opacity versus colour alphas
rgbecker
parents: 3272
diff changeset
    52
    'fillOpacity': None,
3198
683ca9eb6b18 reportlab: added in support for Overprint/Opacity & Separated colours (Opacity inspired by Simon King)
rgbecker
parents: 3032
diff changeset
    53
    'fillOverprint': False,
683ca9eb6b18 reportlab: added in support for Overprint/Opacity & Separated colours (Opacity inspired by Simon King)
rgbecker
parents: 3032
diff changeset
    54
    'strokeOverprint': False,
3417
6b2786216805 graphics: add support for overprintMask
rgbecker
parents: 3405
diff changeset
    55
    'overprintMask': 0,
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
    56
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    57
    'fillColor': colors.black,   #...or text will be invisible
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    58
    #'fillRule': NON_ZERO_WINDING, - these can be done later
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
    59
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    60
    'fontSize': 10,
3368
afa025c34493 reportlab: new base font mechanism more fully applied
rgbecker
parents: 3364
diff changeset
    61
    'fontName': _baseGFontName,
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    62
    'textAnchor':  'start' # can be start, middle, end, inherited
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    63
    }
574
27d5643a5851 Collection based piechart amd support for it.
andy_robinson
parents: 572
diff changeset
    64
759
f68f95c44f77 Improved Auto class.
dinu_gherman
parents: 747
diff changeset
    65
947
9abe8716acc7 Removal of the Auto Thing
rgbecker
parents: 940
diff changeset
    66
####################################################################
9abe8716acc7 Removal of the Auto Thing
rgbecker
parents: 940
diff changeset
    67
# math utilities.  These could probably be moved into lib
9abe8716acc7 Removal of the Auto Thing
rgbecker
parents: 940
diff changeset
    68
# somewhere.
9abe8716acc7 Removal of the Auto Thing
rgbecker
parents: 940
diff changeset
    69
####################################################################
759
f68f95c44f77 Improved Auto class.
dinu_gherman
parents: 747
diff changeset
    70
578
f797bf806ee5 Added group tests, fixed font bug, resynched with Dinu
andy_robinson
parents: 574
diff changeset
    71
# constructors for matrices:
f797bf806ee5 Added group tests, fixed font bug, resynched with Dinu
andy_robinson
parents: 574
diff changeset
    72
def nullTransform():
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    73
    return (1, 0, 0, 1, 0, 0)
578
f797bf806ee5 Added group tests, fixed font bug, resynched with Dinu
andy_robinson
parents: 574
diff changeset
    74
f797bf806ee5 Added group tests, fixed font bug, resynched with Dinu
andy_robinson
parents: 574
diff changeset
    75
def translate(dx, dy):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    76
    return (1, 0, 0, 1, dx, dy)
578
f797bf806ee5 Added group tests, fixed font bug, resynched with Dinu
andy_robinson
parents: 574
diff changeset
    77
f797bf806ee5 Added group tests, fixed font bug, resynched with Dinu
andy_robinson
parents: 574
diff changeset
    78
def scale(sx, sy):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    79
    return (sx, 0, 0, sy, 0, 0)
578
f797bf806ee5 Added group tests, fixed font bug, resynched with Dinu
andy_robinson
parents: 574
diff changeset
    80
f797bf806ee5 Added group tests, fixed font bug, resynched with Dinu
andy_robinson
parents: 574
diff changeset
    81
def rotate(angle):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    82
    a = angle * pi/180
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    83
    return (cos(a), sin(a), -sin(a), cos(a), 0, 0)
578
f797bf806ee5 Added group tests, fixed font bug, resynched with Dinu
andy_robinson
parents: 574
diff changeset
    84
f797bf806ee5 Added group tests, fixed font bug, resynched with Dinu
andy_robinson
parents: 574
diff changeset
    85
def skewX(angle):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    86
    a = angle * pi/180
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    87
    return (1, 0, tan(a), 1, 0, 0)
578
f797bf806ee5 Added group tests, fixed font bug, resynched with Dinu
andy_robinson
parents: 574
diff changeset
    88
f797bf806ee5 Added group tests, fixed font bug, resynched with Dinu
andy_robinson
parents: 574
diff changeset
    89
def skewY(angle):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    90
    a = angle * pi/180
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    91
    return (1, tan(a), 0, 1, 0, 0)
578
f797bf806ee5 Added group tests, fixed font bug, resynched with Dinu
andy_robinson
parents: 574
diff changeset
    92
f797bf806ee5 Added group tests, fixed font bug, resynched with Dinu
andy_robinson
parents: 574
diff changeset
    93
def mmult(A, B):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    94
    "A postmultiplied by B"
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    95
    # I checked this RGB
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    96
    # [a0 a2 a4]    [b0 b2 b4]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    97
    # [a1 a3 a5] *  [b1 b3 b5]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    98
    # [      1 ]    [      1 ]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
    99
    #
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   100
    return (A[0]*B[0] + A[2]*B[1],
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   101
            A[1]*B[0] + A[3]*B[1],
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   102
            A[0]*B[2] + A[2]*B[3],
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   103
            A[1]*B[2] + A[3]*B[3],
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   104
            A[0]*B[4] + A[2]*B[5] + A[4],
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   105
            A[1]*B[4] + A[3]*B[5] + A[5])
578
f797bf806ee5 Added group tests, fixed font bug, resynched with Dinu
andy_robinson
parents: 574
diff changeset
   106
f797bf806ee5 Added group tests, fixed font bug, resynched with Dinu
andy_robinson
parents: 574
diff changeset
   107
def inverse(A):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   108
    "For A affine 2D represented as 6vec return 6vec version of A**(-1)"
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   109
    # I checked this RGB
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   110
    det = float(A[0]*A[3] - A[2]*A[1])
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   111
    R = [A[3]/det, -A[1]/det, -A[2]/det, A[0]/det]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   112
    return tuple(R+[-R[0]*A[4]-R[2]*A[5],-R[1]*A[4]-R[3]*A[5]])
578
f797bf806ee5 Added group tests, fixed font bug, resynched with Dinu
andy_robinson
parents: 574
diff changeset
   113
f797bf806ee5 Added group tests, fixed font bug, resynched with Dinu
andy_robinson
parents: 574
diff changeset
   114
def zTransformPoint(A,v):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   115
    "Apply the homogenous part of atransformation a to vector v --> A*v"
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   116
    return (A[0]*v[0]+A[2]*v[1],A[1]*v[0]+A[3]*v[1])
578
f797bf806ee5 Added group tests, fixed font bug, resynched with Dinu
andy_robinson
parents: 574
diff changeset
   117
f797bf806ee5 Added group tests, fixed font bug, resynched with Dinu
andy_robinson
parents: 574
diff changeset
   118
def transformPoint(A,v):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   119
    "Apply transformation a to vector v --> A*v"
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   120
    return (A[0]*v[0]+A[2]*v[1]+A[4],A[1]*v[0]+A[3]*v[1]+A[5])
578
f797bf806ee5 Added group tests, fixed font bug, resynched with Dinu
andy_robinson
parents: 574
diff changeset
   121
f797bf806ee5 Added group tests, fixed font bug, resynched with Dinu
andy_robinson
parents: 574
diff changeset
   122
def transformPoints(matrix, V):
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3636
diff changeset
   123
    return list(map(transformPoint, V))
578
f797bf806ee5 Added group tests, fixed font bug, resynched with Dinu
andy_robinson
parents: 574
diff changeset
   124
f797bf806ee5 Added group tests, fixed font bug, resynched with Dinu
andy_robinson
parents: 574
diff changeset
   125
def zTransformPoints(matrix, V):
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3636
diff changeset
   126
    return list(map(lambda x,matrix=matrix: zTransformPoint(matrix,x), V))
578
f797bf806ee5 Added group tests, fixed font bug, resynched with Dinu
andy_robinson
parents: 574
diff changeset
   127
810
14e70b554fa5 Added _textBoxLimits
rgbecker
parents: 759
diff changeset
   128
def _textBoxLimits(text, font, fontSize, leading, textAnchor, boxAnchor):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   129
    w = 0
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   130
    for t in text:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   131
        w = max(w,stringWidth(t,font, fontSize))
810
14e70b554fa5 Added _textBoxLimits
rgbecker
parents: 759
diff changeset
   132
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   133
    h = len(text)*leading
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   134
    yt = fontSize
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   135
    if boxAnchor[0]=='s':
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   136
        yb = -h
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   137
        yt = yt - h
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   138
    elif boxAnchor[0]=='n':
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   139
        yb = 0
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   140
    else:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   141
        yb = -h/2.0
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   142
        yt = yt + yb
810
14e70b554fa5 Added _textBoxLimits
rgbecker
parents: 759
diff changeset
   143
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   144
    if boxAnchor[-1]=='e':
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   145
        xb = -w
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   146
        if textAnchor=='end': xt = 0
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   147
        elif textAnchor=='start': xt = -w
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   148
        else: xt = -w/2.0
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   149
    elif boxAnchor[-1]=='w':
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   150
        xb = 0
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   151
        if textAnchor=='end': xt = w
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   152
        elif textAnchor=='start': xt = 0
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   153
        else: xt = w/2.0
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   154
    else:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   155
        xb = -w/2.0
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   156
        if textAnchor=='end': xt = -xb
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   157
        elif textAnchor=='start': xt = xb
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   158
        else: xt = 0
810
14e70b554fa5 Added _textBoxLimits
rgbecker
parents: 759
diff changeset
   159
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   160
    return xb, yb, w, h, xt, yt
810
14e70b554fa5 Added _textBoxLimits
rgbecker
parents: 759
diff changeset
   161
578
f797bf806ee5 Added group tests, fixed font bug, resynched with Dinu
andy_robinson
parents: 574
diff changeset
   162
def _rotatedBoxLimits( x, y, w, h, angle):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   163
    '''
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   164
    Find the corner points of the rotated w x h sized box at x,y
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   165
    return the corner points and the min max points in the original space
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   166
    '''
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   167
    C = zTransformPoints(rotate(angle),((x,y),(x+w,y),(x+w,y+h),(x,y+h)))
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3636
diff changeset
   168
    X = [x[0] for x in C]
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3636
diff changeset
   169
    Y = [x[1] for x in C]
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   170
    return min(X), max(X), min(Y), max(Y), C
578
f797bf806ee5 Added group tests, fixed font bug, resynched with Dinu
andy_robinson
parents: 574
diff changeset
   171
759
f68f95c44f77 Improved Auto class.
dinu_gherman
parents: 747
diff changeset
   172
1665
c2ce87221cf7 Changes to allow flaky _drawTimeResize
rgbecker
parents: 1609
diff changeset
   173
class _DrawTimeResizeable:
2004
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   174
    '''Addin class to provide the horribleness of _drawTimeResize'''
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   175
    def _drawTimeResize(self,w,h):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   176
        if hasattr(self,'_canvas'):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   177
            canvas = self._canvas
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   178
            drawing = canvas._drawing
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   179
            drawing.width, drawing.height = w, h
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   180
            if hasattr(canvas,'_drawTimeResize'):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   181
                canvas._drawTimeResize(w,h)
976
47930c35c069 Correct names and factorise some behaviour
rgbecker
parents: 952
diff changeset
   182
1795
b8a2cf14a5b1 Added class _SetKeyWordArgs
rgbecker
parents: 1791
diff changeset
   183
class _SetKeyWordArgs:
b8a2cf14a5b1 Added class _SetKeyWordArgs
rgbecker
parents: 1791
diff changeset
   184
    def __init__(self, keywords={}):
b8a2cf14a5b1 Added class _SetKeyWordArgs
rgbecker
parents: 1791
diff changeset
   185
        """In general properties may be supplied to the constructor."""
3723
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   186
        for key, value in keywords.items():
1795
b8a2cf14a5b1 Added class _SetKeyWordArgs
rgbecker
parents: 1791
diff changeset
   187
            setattr(self, key, value)
b8a2cf14a5b1 Added class _SetKeyWordArgs
rgbecker
parents: 1791
diff changeset
   188
2004
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   189
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   190
#################################################################
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   191
#
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   192
#    Helper functions for working out bounds
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   193
#
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   194
#################################################################
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   195
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   196
def getRectsBounds(rectList):
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   197
    # filter out any None objects, e.g. empty groups
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3636
diff changeset
   198
    L = [x for x in rectList if x is not None]
2287
192d157c1f53 Fix problem with empty charts
rgbecker
parents: 2146
diff changeset
   199
    if not L: return None
2005
7429e51e3afb Slight efficiency saving & code reuse
rgbecker
parents: 2004
diff changeset
   200
2287
192d157c1f53 Fix problem with empty charts
rgbecker
parents: 2146
diff changeset
   201
    xMin, yMin, xMax, yMax = L[0]
192d157c1f53 Fix problem with empty charts
rgbecker
parents: 2146
diff changeset
   202
    for (x1, y1, x2, y2) in L[1:]:
2004
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   203
        if x1 < xMin:
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   204
            xMin = x1
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   205
        if x2 > xMax:
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   206
            xMax = x2
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   207
        if y1 < yMin:
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   208
            yMin = y1
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   209
        if y2 > yMax:
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   210
            yMax = y2
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   211
    return (xMin, yMin, xMax, yMax)
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   212
3541
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   213
def _getBezierExtrema(y0,y1,y2,y3):
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   214
    '''
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   215
    this is used to find if a curveTo path operator has extrema in its range
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   216
    The curveTo operator is defined by the points y0, y1, y2, y3
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   217
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   218
        B(t):=(1-t)^3*y0+3*(1-t)^2*t*y1+3*(1-t)*t^2*y2+t^3*y3
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   219
            :=t^3*(y3-3*y2+3*y1-y0)+t^2*(3*y2-6*y1+3*y0)+t*(3*y1-3*y0)+y0
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   220
    and is a cubic bezier curve.
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   221
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   222
    The differential is a quadratic
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   223
        t^2*(3*y3-9*y2+9*y1-3*y0)+t*(6*y2-12*y1+6*y0)+3*y1-3*y0
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   224
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   225
    The extrema must be at real roots, r, of the above which lie in 0<=r<=1
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   226
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   227
    The quadratic coefficients are
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   228
        a=3*y3-9*y2+9*y1-3*y0 b=6*y2-12*y1+6*y0 c=3*y1-3*y0
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   229
    or
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   230
        a=y3-3*y2+3*y1-y0 b=2*y2-4*y1+2*y0 c=y1-y0  (remove common factor of 3)
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   231
    or
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   232
        a=y3-3*(y2-y1)-y0 b=2*(y2-2*y1+y0) c=y1-y0
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   233
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   234
    The returned value is [y0,x1,x2,y3] where if found x1, x2 are any extremals that were found;
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   235
    there can be 0, 1 or 2 extremals
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   236
    '''
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   237
    a=y3-3*(y2-y1)-y0
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   238
    b=2*(y2-2*y1+y0)
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   239
    c=y1-y0
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   240
    Y = [y0] #the set of points
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   241
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   242
    #standard method to find roots of quadratic
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   243
    d = b*b - 4*a*c
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   244
    if d>=0:
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   245
        d = sqrt(d)
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   246
        if b<0: d = -d
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   247
        q = -0.5*(b+d)
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   248
        R = []
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   249
        try:
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   250
            R.append(q/a)
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   251
        except:
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   252
            pass
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   253
        try:
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   254
            R.append(c/q)
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   255
        except:
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   256
            pass
3543
7c2dc409f359 shapes.py: _getBezierExtrema minor efficiency saving
rgbecker
parents: 3541
diff changeset
   257
        b *= 1.5
7c2dc409f359 shapes.py: _getBezierExtrema minor efficiency saving
rgbecker
parents: 3541
diff changeset
   258
        c *= 3
3541
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   259
        for t in R:
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   260
            if 0<=t<=1:
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   261
                #real root in range evaluate spline there and add to X
3543
7c2dc409f359 shapes.py: _getBezierExtrema minor efficiency saving
rgbecker
parents: 3541
diff changeset
   262
                Y.append(t*(t*(t*a+b)+c)+y0)
3541
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   263
    Y.append(y3)
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   264
    return Y
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   265
2005
7429e51e3afb Slight efficiency saving & code reuse
rgbecker
parents: 2004
diff changeset
   266
def getPathBounds(points):
7429e51e3afb Slight efficiency saving & code reuse
rgbecker
parents: 2004
diff changeset
   267
    n = len(points)
7429e51e3afb Slight efficiency saving & code reuse
rgbecker
parents: 2004
diff changeset
   268
    f = lambda i,p = points: p[i]
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3636
diff changeset
   269
    xs = list(map(f,range(0,n,2)))
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3636
diff changeset
   270
    ys = list(map(f,range(1,n,2)))
2005
7429e51e3afb Slight efficiency saving & code reuse
rgbecker
parents: 2004
diff changeset
   271
    return (min(xs), min(ys), max(xs), max(ys))
7429e51e3afb Slight efficiency saving & code reuse
rgbecker
parents: 2004
diff changeset
   272
2004
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   273
def getPointsBounds(pointList):
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   274
    "Helper function for list of points"
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   275
    first = pointList[0]
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   276
    if type(first) in (ListType, TupleType):
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3636
diff changeset
   277
        xs = [xy[0] for xy in pointList]
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3636
diff changeset
   278
        ys = [xy[1] for xy in pointList]
2005
7429e51e3afb Slight efficiency saving & code reuse
rgbecker
parents: 2004
diff changeset
   279
        return (min(xs), min(ys), max(xs), max(ys))
2004
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   280
    else:
2005
7429e51e3afb Slight efficiency saving & code reuse
rgbecker
parents: 2004
diff changeset
   281
        return getPathBounds(pointList)
2004
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   282
1665
c2ce87221cf7 Changes to allow flaky _drawTimeResize
rgbecker
parents: 1609
diff changeset
   283
#################################################################
c2ce87221cf7 Changes to allow flaky _drawTimeResize
rgbecker
parents: 1609
diff changeset
   284
#
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   285
#    And now the shapes themselves....
1665
c2ce87221cf7 Changes to allow flaky _drawTimeResize
rgbecker
parents: 1609
diff changeset
   286
#
c2ce87221cf7 Changes to allow flaky _drawTimeResize
rgbecker
parents: 1609
diff changeset
   287
#################################################################
1795
b8a2cf14a5b1 Added class _SetKeyWordArgs
rgbecker
parents: 1791
diff changeset
   288
class Shape(_SetKeyWordArgs,_DrawTimeResizeable):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   289
    """Base class for all nodes in the tree. Nodes are simply
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   290
    packets of data to be created, stored, and ultimately
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   291
    rendered - they don't do anything active.  They provide
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   292
    convenience methods for verification but do not
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   293
    check attribiute assignments or use any clever setattr
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   294
    tricks this time."""
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   295
    _attrMap = AttrMap()
759
f68f95c44f77 Improved Auto class.
dinu_gherman
parents: 747
diff changeset
   296
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   297
    def copy(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   298
        """Return a clone of this shape."""
759
f68f95c44f77 Improved Auto class.
dinu_gherman
parents: 747
diff changeset
   299
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   300
        # implement this in the descendants as they need the right init methods.
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3636
diff changeset
   301
        raise NotImplementedError("No copy method implemented for %s" % self.__class__.__name__)
976
47930c35c069 Correct names and factorise some behaviour
rgbecker
parents: 952
diff changeset
   302
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   303
    def getProperties(self,recur=1):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   304
        """Interface to make it easy to extract automatic
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   305
        documentation"""
759
f68f95c44f77 Improved Auto class.
dinu_gherman
parents: 747
diff changeset
   306
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   307
        #basic nodes have no children so this is easy.
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   308
        #for more complex objects like widgets you
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   309
        #may need to override this.
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   310
        props = {}
3723
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   311
        for key, value in self.__dict__.items():
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3280
diff changeset
   312
            if key[0:1] != '_':
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   313
                props[key] = value
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   314
        return props
976
47930c35c069 Correct names and factorise some behaviour
rgbecker
parents: 952
diff changeset
   315
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   316
    def setProperties(self, props):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   317
        """Supports the bulk setting if properties from,
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   318
        for example, a GUI application or a config file."""
759
f68f95c44f77 Improved Auto class.
dinu_gherman
parents: 747
diff changeset
   319
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   320
        self.__dict__.update(props)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   321
        #self.verify()
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
   322
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   323
    def dumpProperties(self, prefix=""):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   324
        """Convenience. Lists them on standard output.  You
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   325
        may provide a prefix - mostly helps to generate code
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   326
        samples for documentation."""
759
f68f95c44f77 Improved Auto class.
dinu_gherman
parents: 747
diff changeset
   327
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3636
diff changeset
   328
        propList = list(self.getProperties().items())
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   329
        propList.sort()
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   330
        if prefix:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   331
            prefix = prefix + '.'
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   332
        for (name, value) in propList:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3636
diff changeset
   333
            print('%s%s = %s' % (prefix, name, value))
976
47930c35c069 Correct names and factorise some behaviour
rgbecker
parents: 952
diff changeset
   334
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   335
    def verify(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   336
        """If the programmer has provided the optional
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   337
        _attrMap attribute, this checks all expected
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   338
        attributes are present; no unwanted attributes
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   339
        are present; and (if a checking function is found)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   340
        checks each attribute.  Either succeeds or raises
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   341
        an informative exception."""
759
f68f95c44f77 Improved Auto class.
dinu_gherman
parents: 747
diff changeset
   342
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   343
        if self._attrMap is not None:
3723
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   344
            for key in self.__dict__.keys():
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3280
diff changeset
   345
                if key[0] != '_':
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3280
diff changeset
   346
                    assert key in self._attrMap, "Unexpected attribute %s found in %s" % (key, self)
3723
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   347
            for attr, metavalue in self._attrMap.items():
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   348
                assert hasattr(self, attr), "Missing attribute %s from %s" % (attr, self)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   349
                value = getattr(self, attr)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   350
                assert metavalue.validate(value), "Invalid value %s for attribute %s in class %s" % (value, attr, self.__class__.__name__)
698
864265047890 Changed attribute postponed to _postponed in doctemplate.py.
dinu_gherman
parents: 592
diff changeset
   351
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   352
    if shapeChecking:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   353
        """This adds the ability to check every attribute assignment as it is made.
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   354
        It slows down shapes but is a big help when developing. It does not
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   355
        get defined if rl_config.shapeChecking = 0"""
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   356
        def __setattr__(self, attr, value):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   357
            """By default we verify.  This could be off
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   358
            in some parallel base classes."""
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   359
            validateSetattr(self,attr,value)    #from reportlab.lib.attrmap
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
   360
2004
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   361
    def getBounds(self):
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   362
        "Returns bounding rectangle of object as (x1,y1,x2,y2)"
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   363
        raise NotImplementedError("Shapes and widgets must implement getBounds")
2005
7429e51e3afb Slight efficiency saving & code reuse
rgbecker
parents: 2004
diff changeset
   364
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
   365
class Group(Shape):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   366
    """Groups elements together.  May apply a transform
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   367
    to its contents.  Has a publicly accessible property
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   368
    'contents' which may be used to iterate over contents.
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   369
    In addition, child nodes may be given a name in which
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   370
    case they are subsequently accessible as properties."""
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
   371
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   372
    _attrMap = AttrMap(
3269
87f51df3bc0b attributes changed to advanced usage level
meitham
parents: 3251
diff changeset
   373
        transform = AttrMapValue(isTransform,desc="Coordinate transformation to apply",advancedUsage=1),
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   374
        contents = AttrMapValue(isListOfShapes,desc="Contained drawable elements"),
3224
6f750cb5b21f fix spelling
rgbecker
parents: 3223
diff changeset
   375
        strokeOverprint = AttrMapValue(isBoolean,desc='Turn on stroke overprinting'),
3269
87f51df3bc0b attributes changed to advanced usage level
meitham
parents: 3251
diff changeset
   376
        fillOverprint = AttrMapValue(isBoolean,desc='Turn on fill overprinting',advancedUsage=1),
3417
6b2786216805 graphics: add support for overprintMask
rgbecker
parents: 3405
diff changeset
   377
        overprintMask = AttrMapValue(isBoolean,desc='overprinting for ordinary CMYK',advancedUsage=1),
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   378
        )
976
47930c35c069 Correct names and factorise some behaviour
rgbecker
parents: 952
diff changeset
   379
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   380
    def __init__(self, *elements, **keywords):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   381
        """Initial lists of elements may be provided to allow
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   382
        compact definitions in literal Python code.  May or
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   383
        may not be useful."""
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
   384
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   385
        # Groups need _attrMap to be an instance rather than
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   386
        # a class attribute, as it may be extended at run time.
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   387
        self._attrMap = self._attrMap.clone()
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   388
        self.contents = []
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   389
        self.transform = (1,0,0,1,0,0)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   390
        for elt in elements:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   391
            self.add(elt)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   392
        # this just applies keywords; do it at the end so they
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   393
        #don;t get overwritten
2004
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   394
        _SetKeyWordArgs.__init__(self, keywords)
976
47930c35c069 Correct names and factorise some behaviour
rgbecker
parents: 952
diff changeset
   395
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   396
    def _addNamedNode(self,name,node):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   397
        'if name is not None add an attribute pointing to node and add to the attrMap'
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   398
        if name:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3636
diff changeset
   399
            if name not in list(self._attrMap.keys()):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   400
                self._attrMap[name] = AttrMapValue(isValidChild)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   401
            setattr(self, name, node)
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
   402
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   403
    def add(self, node, name=None):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   404
        """Appends non-None child node to the 'contents' attribute. In addition,
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   405
        if a name is provided, it is subsequently accessible by name
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   406
        """
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   407
        # propagates properties down
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   408
        if node is not None:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   409
            assert isValidChild(node), "Can only add Shape or UserNode objects to a Group"
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   410
            self.contents.append(node)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   411
            self._addNamedNode(name,node)
819
1f7e1ffd4578 Added Group insert method
rgbecker
parents: 818
diff changeset
   412
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   413
    def _nn(self,node):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   414
        self.add(node)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   415
        return self.contents[-1]
1411
7ce14dbd7578 Added .py save format for Drawings, seems to work
rgbecker
parents: 1388
diff changeset
   416
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   417
    def insert(self, i, n, name=None):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   418
        'Inserts sub-node n in contents at specified location'
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   419
        if n is not None:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   420
            assert isValidChild(n), "Can only insert Shape or UserNode objects in a Group"
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   421
            if i<0:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   422
                self.contents[i:i] =[n]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   423
            else:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   424
                self.contents.insert(i,n)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   425
            self._addNamedNode(name,n)
592
35f70c45f74c Fixed user node rendering bug, added barchart1
andy_robinson
parents: 590
diff changeset
   426
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   427
    def expandUserNodes(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   428
        """Return a new object which only contains primitive shapes."""
592
35f70c45f74c Fixed user node rendering bug, added barchart1
andy_robinson
parents: 590
diff changeset
   429
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   430
        # many limitations - shared nodes become multiple ones,
1836
60f5cd36ac43 Attempted fix for problems with expandUserNodes
rgbecker
parents: 1832
diff changeset
   431
        obj = isinstance(self,Drawing) and Drawing(self.width,self.height) or Group()
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   432
        obj._attrMap = self._attrMap.clone()
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   433
        if hasattr(obj,'transform'): obj.transform = self.transform[:]
976
47930c35c069 Correct names and factorise some behaviour
rgbecker
parents: 952
diff changeset
   434
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   435
        self_contents = self.contents
1832
cbbe247d0b6e Small change to fix _copyNamedContents
rgbecker
parents: 1795
diff changeset
   436
        a = obj.contents.append
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   437
        for child in self_contents:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   438
            if isinstance(child, UserNode):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   439
                newChild = child.provideNode()
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   440
            elif isinstance(child, Group):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   441
                newChild = child.expandUserNodes()
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   442
            else:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   443
                newChild = child.copy()
1832
cbbe247d0b6e Small change to fix _copyNamedContents
rgbecker
parents: 1795
diff changeset
   444
            a(newChild)
592
35f70c45f74c Fixed user node rendering bug, added barchart1
andy_robinson
parents: 590
diff changeset
   445
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   446
        self._copyNamedContents(obj)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   447
        return obj
976
47930c35c069 Correct names and factorise some behaviour
rgbecker
parents: 952
diff changeset
   448
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   449
    def _explode(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   450
        ''' return a fully expanded object'''
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   451
        from reportlab.graphics.widgetbase import Widget
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   452
        obj = Group()
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   453
        if hasattr(obj,'transform'): obj.transform = self.transform[:]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   454
        P = self.contents[:]    # pending nodes
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   455
        while P:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   456
            n = P.pop(0)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   457
            if isinstance(n, UserNode):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   458
                P.append(n.provideNode())
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   459
            elif isinstance(n, Group):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   460
                n = n._explode()
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   461
                if n.transform==(1,0,0,1,0,0):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   462
                    obj.contents.extend(n.contents)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   463
                else:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   464
                    obj.add(n)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   465
            else:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   466
                obj.add(n)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   467
        return obj
1318
394927c4a99c Added symbolic definePath function
rgbecker
parents: 1262
diff changeset
   468
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   469
    def _copyContents(self,obj):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   470
        for child in self.contents:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   471
            obj.contents.append(child)
1084
b5aae6e2da9a Fixed up copying. Drawings should really be Groups with dimensions
rgbecker
parents: 1082
diff changeset
   472
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   473
    def _copyNamedContents(self,obj,aKeys=None,noCopy=('contents',)):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   474
        from copy import copy
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   475
        self_contents = self.contents
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3636
diff changeset
   476
        if not aKeys: aKeys = list(self._attrMap.keys())
3723
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   477
        for k, v in self.__dict__.items():
1832
cbbe247d0b6e Small change to fix _copyNamedContents
rgbecker
parents: 1795
diff changeset
   478
            if v in self_contents:
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   479
                pos = self_contents.index(v)
1832
cbbe247d0b6e Small change to fix _copyNamedContents
rgbecker
parents: 1795
diff changeset
   480
                setattr(obj, k, obj.contents[pos])
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   481
            elif k in aKeys and k not in noCopy:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   482
                setattr(obj, k, copy(v))
1084
b5aae6e2da9a Fixed up copying. Drawings should really be Groups with dimensions
rgbecker
parents: 1082
diff changeset
   483
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   484
    def _copy(self,obj):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   485
        """copies to obj"""
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   486
        obj._attrMap = self._attrMap.clone()
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   487
        self._copyContents(obj)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   488
        self._copyNamedContents(obj)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   489
        return obj
592
35f70c45f74c Fixed user node rendering bug, added barchart1
andy_robinson
parents: 590
diff changeset
   490
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   491
    def copy(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   492
        """returns a copy"""
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   493
        return self._copy(self.__class__())
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
   494
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   495
    def rotate(self, theta):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   496
        """Convenience to help you set transforms"""
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   497
        self.transform = mmult(self.transform, rotate(theta))
976
47930c35c069 Correct names and factorise some behaviour
rgbecker
parents: 952
diff changeset
   498
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   499
    def translate(self, dx, dy):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   500
        """Convenience to help you set transforms"""
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   501
        self.transform = mmult(self.transform, translate(dx, dy))
976
47930c35c069 Correct names and factorise some behaviour
rgbecker
parents: 952
diff changeset
   502
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   503
    def scale(self, sx, sy):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   504
        """Convenience to help you set transforms"""
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   505
        self.transform = mmult(self.transform, scale(sx, sy))
976
47930c35c069 Correct names and factorise some behaviour
rgbecker
parents: 952
diff changeset
   506
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
   507
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   508
    def skew(self, kx, ky):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   509
        """Convenience to help you set transforms"""
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   510
        self.transform = mmult(mmult(self.transform, skewX(kx)),skewY(ky))
814
ca2bfda4b1ab Made Drawings inherit from Group
rgbecker
parents: 810
diff changeset
   511
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   512
    def shift(self, x, y):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   513
        '''Convenience function to set the origin arbitrarily'''
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   514
        self.transform = self.transform[:-2]+(x,y)
1117
9000bfc45cd5 Added Group.shift method
rgbecker
parents: 1116
diff changeset
   515
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   516
    def asDrawing(self, width, height):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   517
        """ Convenience function to make a drawing from a group
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   518
            After calling this the instance will be a drawing!
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   519
        """
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   520
        self.__class__ = Drawing
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   521
        self._attrMap.update(self._xtraAttrMap)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   522
        self.width = width
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   523
        self.height = height
814
ca2bfda4b1ab Made Drawings inherit from Group
rgbecker
parents: 810
diff changeset
   524
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   525
    def getContents(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   526
        '''Return the list of things to be rendered
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   527
        override to get more complicated behaviour'''
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   528
        b = getattr(self,'background',None)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   529
        C = self.contents
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   530
        if b and b not in C: C = [b]+C
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   531
        return C
1082
53caef7f1366 Added getContents methods
rgbecker
parents: 1071
diff changeset
   532
2004
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   533
    def getBounds(self):
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   534
        if self.contents:
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   535
            b = []
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   536
            for elem in self.contents:
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   537
                b.append(elem.getBounds())
2287
192d157c1f53 Fix problem with empty charts
rgbecker
parents: 2146
diff changeset
   538
            x1 = getRectsBounds(b)
192d157c1f53 Fix problem with empty charts
rgbecker
parents: 2146
diff changeset
   539
            if x1 is None: return None
192d157c1f53 Fix problem with empty charts
rgbecker
parents: 2146
diff changeset
   540
            x1, y1, x2, y2 = x1
2004
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   541
            trans = self.transform
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   542
            corners = [[x1,y1], [x1, y2], [x2, y1], [x2,y2]]
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   543
            newCorners = []
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   544
            for corner in corners:
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   545
                newCorners.append(transformPoint(trans, corner))
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   546
            return getPointsBounds(newCorners)
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   547
        else:
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   548
            #empty group needs a sane default; this
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   549
            #will happen when interactively creating a group
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   550
            #nothing has been added to yet.  The alternative is
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   551
            #to handle None as an allowed return value everywhere.
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   552
            return None
2005
7429e51e3afb Slight efficiency saving & code reuse
rgbecker
parents: 2004
diff changeset
   553
1757
97a30ce781ee Fix for tuple case in definePath
rgbecker
parents: 1706
diff changeset
   554
def _addObjImport(obj,I,n=None):
2306
5370ae88b2ab Make a couple of files emacs font-lock friendly
jjlee
parents: 2287
diff changeset
   555
    '''add an import of obj's class to a dictionary of imports''' #'
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   556
    from inspect import getmodule
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   557
    c = obj.__class__
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   558
    m = getmodule(c).__name__
1757
97a30ce781ee Fix for tuple case in definePath
rgbecker
parents: 1706
diff changeset
   559
    n = n or c.__name__
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3280
diff changeset
   560
    if m not in I:
1757
97a30ce781ee Fix for tuple case in definePath
rgbecker
parents: 1706
diff changeset
   561
        I[m] = [n]
97a30ce781ee Fix for tuple case in definePath
rgbecker
parents: 1706
diff changeset
   562
    elif n not in I[m]:
97a30ce781ee Fix for tuple case in definePath
rgbecker
parents: 1706
diff changeset
   563
        I[m].append(n)
1411
7ce14dbd7578 Added .py save format for Drawings, seems to work
rgbecker
parents: 1388
diff changeset
   564
7ce14dbd7578 Added .py save format for Drawings, seems to work
rgbecker
parents: 1388
diff changeset
   565
def _repr(self,I=None):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   566
    '''return a repr style string with named fixed args first, then keywords'''
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   567
    if type(self) is InstanceType:
1757
97a30ce781ee Fix for tuple case in definePath
rgbecker
parents: 1706
diff changeset
   568
        if self is EmptyClipPath:
97a30ce781ee Fix for tuple case in definePath
rgbecker
parents: 1706
diff changeset
   569
            _addObjImport(self,I,'EmptyClipPath')
97a30ce781ee Fix for tuple case in definePath
rgbecker
parents: 1706
diff changeset
   570
            return 'EmptyClipPath'
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   571
        if I: _addObjImport(self,I)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   572
        if isinstance(self,Shape):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   573
            from inspect import getargs
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3636
diff changeset
   574
            args, varargs, varkw = getargs(self.__init__.__func__.__code__)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   575
            P = self.getProperties()
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   576
            s = self.__class__.__name__+'('
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   577
            for n in args[1:]:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   578
                v = P[n]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   579
                del P[n]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   580
                s = s + '%s,' % _repr(v,I)
3723
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   581
            for n,v in P.items():
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   582
                v = P[n]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   583
                s = s + '%s=%s,' % (n, _repr(v,I))
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   584
            return s[:-1]+')'
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   585
        else:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   586
            return repr(self)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   587
    elif type(self) is FloatType:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   588
        return fp_str(self)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   589
    elif type(self) in (ListType,TupleType):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   590
        s = ''
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   591
        for v in self:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   592
            s = s + '%s,' % _repr(v,I)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   593
        if type(self) is ListType:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   594
            return '[%s]' % s[:-1]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   595
        else:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   596
            return '(%s%s)' % (s[:-1],len(self)==1 and ',' or '')
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   597
    else:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   598
        return repr(self)
1411
7ce14dbd7578 Added .py save format for Drawings, seems to work
rgbecker
parents: 1388
diff changeset
   599
7ce14dbd7578 Added .py save format for Drawings, seems to work
rgbecker
parents: 1388
diff changeset
   600
def _renderGroupPy(G,pfx,I,i=0,indent='\t\t'):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   601
    s = ''
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   602
    C = getattr(G,'transform',None)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   603
    if C: s = s + ('%s%s.transform = %s\n' % (indent,pfx,_repr(C)))
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   604
    C  = G.contents
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   605
    for n in C:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   606
        if isinstance(n, Group):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   607
            npfx = 'v%d' % i
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   608
            i = i + 1
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   609
            s = s + '%s%s=%s._nn(Group())\n' % (indent,npfx,pfx)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   610
            s = s + _renderGroupPy(n,npfx,I,i,indent)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   611
            i = i - 1
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   612
        else:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   613
            s = s + '%s%s.add(%s)\n' % (indent,pfx,_repr(n,I))
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   614
    return s
1411
7ce14dbd7578 Added .py save format for Drawings, seems to work
rgbecker
parents: 1388
diff changeset
   615
2453
9f133df197b4 shapes.py: added save renderer specific argument handling
rgbecker
parents: 2341
diff changeset
   616
def _extraKW(self,pfx,**kw):
9f133df197b4 shapes.py: added save renderer specific argument handling
rgbecker
parents: 2341
diff changeset
   617
    kw.update(self.__dict__)
9f133df197b4 shapes.py: added save renderer specific argument handling
rgbecker
parents: 2341
diff changeset
   618
    R = {}
9f133df197b4 shapes.py: added save renderer specific argument handling
rgbecker
parents: 2341
diff changeset
   619
    n = len(pfx)
3723
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   620
    for k in kw.keys():
2453
9f133df197b4 shapes.py: added save renderer specific argument handling
rgbecker
parents: 2341
diff changeset
   621
        if k.startswith(pfx):
9f133df197b4 shapes.py: added save renderer specific argument handling
rgbecker
parents: 2341
diff changeset
   622
            R[k[n:]] = kw[k]
9f133df197b4 shapes.py: added save renderer specific argument handling
rgbecker
parents: 2341
diff changeset
   623
    return R
9f133df197b4 shapes.py: added save renderer specific argument handling
rgbecker
parents: 2341
diff changeset
   624
814
ca2bfda4b1ab Made Drawings inherit from Group
rgbecker
parents: 810
diff changeset
   625
class Drawing(Group, Flowable):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   626
    """Outermost container; the thing a renderer works on.
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   627
    This has no properties except a height, width and list
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   628
    of contents."""
820
0c794f3e9568 Group/Drawing slightly cleaner python
rgbecker
parents: 819
diff changeset
   629
2713
0dae2a4668fb shapes.py: factor out the list of extensions/formats
rgbecker
parents: 2658
diff changeset
   630
    _saveModes=(
0dae2a4668fb shapes.py: factor out the list of extensions/formats
rgbecker
parents: 2658
diff changeset
   631
            'pdf','ps','eps','gif','png','jpg','jpeg','pct',
2811
3062d7ba9d04 reportlab/graphics: add tiffl, tiff1 formats & allow for kwds in asString
rgbecker
parents: 2804
diff changeset
   632
            'pict','tiff','tif','py','bmp','svg','tiffp','tiffl','tiff1',
2713
0dae2a4668fb shapes.py: factor out the list of extensions/formats
rgbecker
parents: 2658
diff changeset
   633
            )
0dae2a4668fb shapes.py: factor out the list of extensions/formats
rgbecker
parents: 2658
diff changeset
   634
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   635
    _xtraAttrMap = AttrMap(
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   636
        width = AttrMapValue(isNumber,desc="Drawing width in points."),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   637
        height = AttrMapValue(isNumber,desc="Drawing height in points."),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   638
        canv = AttrMapValue(None),
3269
87f51df3bc0b attributes changed to advanced usage level
meitham
parents: 3251
diff changeset
   639
        background = AttrMapValue(isValidChildOrNone,desc="Background widget for the drawing e.g. Rect(0,0,width,height)"),
2547
9d13685212f2 datacharts synchronised
andy
parents: 2545
diff changeset
   640
        hAlign = AttrMapValue(OneOf("LEFT", "RIGHT", "CENTER", "CENTRE"), desc="Horizontal alignment within parent document"),
9d13685212f2 datacharts synchronised
andy
parents: 2545
diff changeset
   641
        vAlign = AttrMapValue(OneOf("TOP", "BOTTOM", "CENTER", "CENTRE"), desc="Vertical alignment within parent document"),
9d13685212f2 datacharts synchronised
andy
parents: 2545
diff changeset
   642
        #AR temporary hack to track back up.
9d13685212f2 datacharts synchronised
andy
parents: 2545
diff changeset
   643
        #fontName = AttrMapValue(isStringOrNone),
2544
a6b9aa99b3c3 graphics: added Drawing.renderScale hack for renderer terminal drawing scales
rgbecker
parents: 2536
diff changeset
   644
        renderScale = AttrMapValue(isNumber,desc="Global scaling for rendering"),
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   645
        )
814
ca2bfda4b1ab Made Drawings inherit from Group
rgbecker
parents: 810
diff changeset
   646
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   647
    _attrMap = AttrMap(BASE=Group)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   648
    _attrMap.update(_xtraAttrMap)
976
47930c35c069 Correct names and factorise some behaviour
rgbecker
parents: 952
diff changeset
   649
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   650
    def __init__(self, width=400, height=200, *nodes, **keywords):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   651
        self.background = None
3218
3bb9866ff9a0 shapes.py: add resized method to Drawing class
rgbecker
parents: 3216
diff changeset
   652
        Group.__init__(self,*nodes,**keywords)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   653
        self.width = width
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   654
        self.height = height
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   655
        self.hAlign = 'LEFT'
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   656
        self.vAlign = 'BOTTOM'
2544
a6b9aa99b3c3 graphics: added Drawing.renderScale hack for renderer terminal drawing scales
rgbecker
parents: 2536
diff changeset
   657
        self.renderScale = 1.0
814
ca2bfda4b1ab Made Drawings inherit from Group
rgbecker
parents: 810
diff changeset
   658
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   659
    def _renderPy(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   660
        I = {'reportlab.graphics.shapes': ['_DrawingEditorMixin','Drawing','Group']}
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   661
        G = _renderGroupPy(self._explode(),'self',I)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   662
        n = 'ExplodedDrawing_' + self.__class__.__name__
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   663
        s = '#Autogenerated by ReportLab guiedit do not edit\n'
3723
99aa837b6703 second stage of port to Python 3.3; working hello world
rptlab
parents: 3721
diff changeset
   664
        for m, o in I.items():
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   665
            s = s + 'from %s import %s\n' % (m,string.replace(str(o)[1:-1],"'",""))
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   666
        s = s + '\nclass %s(_DrawingEditorMixin,Drawing):\n' % n
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   667
        s = s + '\tdef __init__(self,width=%s,height=%s,*args,**kw):\n' % (self.width,self.height)
3364
48b859cfd84c shapes.py: fix bad python code
rgbecker
parents: 3326
diff changeset
   668
        s = s + '\t\tDrawing.__init__(self,width,height,*args,**kw)\n'
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   669
        s = s + G
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   670
        s = s + '\n\nif __name__=="__main__": #NORUNTESTS\n\t%s().save(formats=[\'pdf\'],outDir=\'.\',fnRoot=None)\n' % n
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   671
        return s
1411
7ce14dbd7578 Added .py save format for Drawings, seems to work
rgbecker
parents: 1388
diff changeset
   672
2553
a880f43d10bd reprotlab/graphics: fix so renderScale is used properly
rgbecker
parents: 2552
diff changeset
   673
    def draw(self,showBoundary=_unset_):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   674
        """This is used by the Platypus framework to let the document
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   675
        draw itself in a story.  It is specific to PDF and should not
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   676
        be used directly."""
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3636
diff changeset
   677
        from . import renderPDF
2553
a880f43d10bd reprotlab/graphics: fix so renderScale is used properly
rgbecker
parents: 2552
diff changeset
   678
        renderPDF.draw(self, self.canv, 0, 0, showBoundary=showBoundary)
814
ca2bfda4b1ab Made Drawings inherit from Group
rgbecker
parents: 810
diff changeset
   679
2554
35a49dcef1fb shapes.py: fix wrap for Drawings to take account of renderScale
rgbecker
parents: 2553
diff changeset
   680
    def wrap(self, availWidth, availHeight):
35a49dcef1fb shapes.py: fix wrap for Drawings to take account of renderScale
rgbecker
parents: 2553
diff changeset
   681
        width = self.width
35a49dcef1fb shapes.py: fix wrap for Drawings to take account of renderScale
rgbecker
parents: 2553
diff changeset
   682
        height = self.height
35a49dcef1fb shapes.py: fix wrap for Drawings to take account of renderScale
rgbecker
parents: 2553
diff changeset
   683
        renderScale = self.renderScale
35a49dcef1fb shapes.py: fix wrap for Drawings to take account of renderScale
rgbecker
parents: 2553
diff changeset
   684
        if renderScale!=1.0:
35a49dcef1fb shapes.py: fix wrap for Drawings to take account of renderScale
rgbecker
parents: 2553
diff changeset
   685
            width *= renderScale
35a49dcef1fb shapes.py: fix wrap for Drawings to take account of renderScale
rgbecker
parents: 2553
diff changeset
   686
            height *= renderScale
35a49dcef1fb shapes.py: fix wrap for Drawings to take account of renderScale
rgbecker
parents: 2553
diff changeset
   687
        return width, height
35a49dcef1fb shapes.py: fix wrap for Drawings to take account of renderScale
rgbecker
parents: 2553
diff changeset
   688
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   689
    def expandUserNodes(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   690
        """Return a new drawing which only contains primitive shapes."""
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   691
        obj = Group.expandUserNodes(self)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   692
        obj.width = self.width
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   693
        obj.height = self.height
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   694
        return obj
814
ca2bfda4b1ab Made Drawings inherit from Group
rgbecker
parents: 810
diff changeset
   695
2544
a6b9aa99b3c3 graphics: added Drawing.renderScale hack for renderer terminal drawing scales
rgbecker
parents: 2536
diff changeset
   696
    def copy(self):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   697
        """Returns a copy"""
2552
0ce835bc29df shapes.py: make copy use derived class if not overridden
rgbecker
parents: 2551
diff changeset
   698
        return self._copy(self.__class__(self.width, self.height))
1033
038b7cb785aa Bug fix self. was wrong added _copy and asGroup to Drawing
rgbecker
parents: 1032
diff changeset
   699
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   700
    def asGroup(self,*args,**kw):
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3280
diff changeset
   701
        return self._copy(Group(*args,**kw))
1033
038b7cb785aa Bug fix self. was wrong added _copy and asGroup to Drawing
rgbecker
parents: 1032
diff changeset
   702
2453
9f133df197b4 shapes.py: added save renderer specific argument handling
rgbecker
parents: 2341
diff changeset
   703
    def save(self, formats=None, verbose=None, fnRoot=None, outDir=None, title='', **kw):
1862
11f6cd4b0f07 Drawings can now do asString(format)
andy_robinson
parents: 1843
diff changeset
   704
        """Saves copies of self in desired location and formats.
2453
9f133df197b4 shapes.py: added save renderer specific argument handling
rgbecker
parents: 2341
diff changeset
   705
        Multiple formats can be supported in one call
1862
11f6cd4b0f07 Drawings can now do asString(format)
andy_robinson
parents: 1843
diff changeset
   706
2453
9f133df197b4 shapes.py: added save renderer specific argument handling
rgbecker
parents: 2341
diff changeset
   707
        the extra keywords can be of the form
9f133df197b4 shapes.py: added save renderer specific argument handling
rgbecker
parents: 2341
diff changeset
   708
        _renderPM_dpi=96 (which passes dpi=96 to renderPM)
9f133df197b4 shapes.py: added save renderer specific argument handling
rgbecker
parents: 2341
diff changeset
   709
        """
3405
b4495d447cd9 shapes.py: allow seqNumber keyword argument in save
rgbecker
parents: 3400
diff changeset
   710
        genFmt = kw.pop('seqNumber','')
b4495d447cd9 shapes.py: allow seqNumber keyword argument in save
rgbecker
parents: 3400
diff changeset
   711
        if isinstance(genFmt,int):
b4495d447cd9 shapes.py: allow seqNumber keyword argument in save
rgbecker
parents: 3400
diff changeset
   712
            genFmt = '%4d: ' % genFmt
b4495d447cd9 shapes.py: allow seqNumber keyword argument in save
rgbecker
parents: 3400
diff changeset
   713
        else:
b4495d447cd9 shapes.py: allow seqNumber keyword argument in save
rgbecker
parents: 3400
diff changeset
   714
            genFmt = ''
b4495d447cd9 shapes.py: allow seqNumber keyword argument in save
rgbecker
parents: 3400
diff changeset
   715
        genFmt += 'generating %s file %s'
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   716
        from reportlab import rl_config
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   717
        ext = ''
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   718
        if not fnRoot:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   719
            fnRoot = getattr(self,'fileNamePattern',(self.__class__.__name__+'%03d'))
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   720
            chartId = getattr(self,'chartId',0)
3400
f18eb3f0f32b shapes.py: allow chartId to be a callable
rgbecker
parents: 3393
diff changeset
   721
            if hasattr(chartId,'__call__'):
f18eb3f0f32b shapes.py: allow chartId to be a callable
rgbecker
parents: 3393
diff changeset
   722
                chartId = chartId(self)
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3280
diff changeset
   723
            if hasattr(fnRoot,'__call__'):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   724
                fnRoot = fnRoot(chartId)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   725
            else:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   726
                try:
3400
f18eb3f0f32b shapes.py: allow chartId to be a callable
rgbecker
parents: 3393
diff changeset
   727
                    fnRoot = fnRoot % chartId
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3636
diff changeset
   728
                except TypeError as err:
2504
a733c3398bcd generalized a rarely-used error message handler which changed in 2.3
andy
parents: 2453
diff changeset
   729
                    #the exact error message changed from 2.2 to 2.3 so we need to
a733c3398bcd generalized a rarely-used error message handler which changed in 2.3
andy
parents: 2453
diff changeset
   730
                    #check a substring
a733c3398bcd generalized a rarely-used error message handler which changed in 2.3
andy
parents: 2453
diff changeset
   731
                    if str(err).find('not all arguments converted') < 0: raise
1232
3bcff47c0ead Modified save filename calcs
rgbecker
parents: 1230
diff changeset
   732
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   733
        if os.path.isabs(fnRoot):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   734
            outDir, fnRoot = os.path.split(fnRoot)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   735
        else:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   736
            outDir = outDir or getattr(self,'outDir','.')
2586
1cfd7c468127 shapes.py: merged stable 2843:2844 minor fix to outDir handling in Drawing.save
rgbecker
parents: 2575
diff changeset
   737
        outDir = outDir.rstrip().rstrip(os.sep)
1cfd7c468127 shapes.py: merged stable 2843:2844 minor fix to outDir handling in Drawing.save
rgbecker
parents: 2575
diff changeset
   738
        if not outDir: outDir = '.'
2551
da6f3e86fcfb shapes.py: allow override for CWD
rgbecker
parents: 2547
diff changeset
   739
        if not os.path.isabs(outDir): outDir = os.path.join(getattr(self,'_override_CWD',os.path.dirname(sys.argv[0])),outDir)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   740
        if not os.path.isdir(outDir): os.makedirs(outDir)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   741
        fnroot = os.path.normpath(os.path.join(outDir,fnRoot))
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   742
        plotMode = os.path.splitext(fnroot)
2713
0dae2a4668fb shapes.py: factor out the list of extensions/formats
rgbecker
parents: 2658
diff changeset
   743
        if string.lower(plotMode[1][1:]) in self._saveModes:
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   744
            fnroot = plotMode[0]
1176
4ef49823ccc7 Moved saved method from Andy's datacharts.py
rgbecker
parents: 1175
diff changeset
   745
3216
ada999992832 shapes.py: fix problem when extensions specified in unicode
rgbecker
parents: 3198
diff changeset
   746
        plotMode = [x.lower() for x in (formats or getattr(self,'formats',['pdf']))]
2658
a5bab09f188d shapes.py: allow upper case formats in Drawing.save
rgbecker
parents: 2586
diff changeset
   747
        verbose = (verbose is not None and (verbose,) or (getattr(self,'verbose',verbose),))[0]
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   748
        _saved = logger.warnOnce.enabled, logger.infoOnce.enabled
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   749
        logger.warnOnce.enabled = logger.infoOnce.enabled = verbose
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   750
        if 'pdf' in plotMode:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   751
            from reportlab.graphics import renderPDF
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   752
            filename = fnroot+'.pdf'
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3636
diff changeset
   753
            if verbose: print(genFmt % ('PDF',filename))
2453
9f133df197b4 shapes.py: added save renderer specific argument handling
rgbecker
parents: 2341
diff changeset
   754
            renderPDF.drawToFile(self, filename, title, showBoundary=getattr(self,'showBorder',rl_config.showBoundary),**_extraKW(self,'_renderPDF_',**kw))
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   755
            ext = ext +  '/.pdf'
1973
48084797a6b7 If a PDF is made on a mac (ie OS 9 rather than OX X), now adds the correct
johnprecedo
parents: 1952
diff changeset
   756
            if sys.platform=='mac':
48084797a6b7 If a PDF is made on a mac (ie OS 9 rather than OX X), now adds the correct
johnprecedo
parents: 1952
diff changeset
   757
                import macfs, macostools
48084797a6b7 If a PDF is made on a mac (ie OS 9 rather than OX X), now adds the correct
johnprecedo
parents: 1952
diff changeset
   758
                macfs.FSSpec(filename).SetCreatorType("CARO", "PDF ")
48084797a6b7 If a PDF is made on a mac (ie OS 9 rather than OX X), now adds the correct
johnprecedo
parents: 1952
diff changeset
   759
                macostools.touched(filename)
1176
4ef49823ccc7 Moved saved method from Andy's datacharts.py
rgbecker
parents: 1175
diff changeset
   760
2811
3062d7ba9d04 reportlab/graphics: add tiffl, tiff1 formats & allow for kwds in asString
rgbecker
parents: 2804
diff changeset
   761
        for bmFmt in ('gif','png','tif','jpg','tiff','pct','pict', 'bmp','tiffp','tiffl','tiff1'):
1863
086d685ad0cb Space saving optimisation
rgbecker
parents: 1862
diff changeset
   762
            if bmFmt in plotMode:
086d685ad0cb Space saving optimisation
rgbecker
parents: 1862
diff changeset
   763
                from reportlab.graphics import renderPM
086d685ad0cb Space saving optimisation
rgbecker
parents: 1862
diff changeset
   764
                filename = '%s.%s' % (fnroot,bmFmt)
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3636
diff changeset
   765
                if verbose: print(genFmt % (bmFmt,filename))
3388
793d353cbc08 shapes.py, utils.py more support for draw time collector
rgbecker
parents: 3383
diff changeset
   766
                dtc = getattr(self,'_drawTimeCollector',None)
793d353cbc08 shapes.py, utils.py more support for draw time collector
rgbecker
parents: 3383
diff changeset
   767
                if dtc:
3393
1a1c9637d79f graphics: minor changes to drawTimeCollector support
rgbecker
parents: 3390
diff changeset
   768
                    dtcfmts = getattr(dtc,'formats',[bmFmt])
1a1c9637d79f graphics: minor changes to drawTimeCollector support
rgbecker
parents: 3390
diff changeset
   769
                    if bmFmt in dtcfmts and not getattr(dtc,'disabled',0):
3388
793d353cbc08 shapes.py, utils.py more support for draw time collector
rgbecker
parents: 3383
diff changeset
   770
                        dtc.clear()
793d353cbc08 shapes.py, utils.py more support for draw time collector
rgbecker
parents: 3383
diff changeset
   771
                    else:
793d353cbc08 shapes.py, utils.py more support for draw time collector
rgbecker
parents: 3383
diff changeset
   772
                        dtc = None
2453
9f133df197b4 shapes.py: added save renderer specific argument handling
rgbecker
parents: 2341
diff changeset
   773
                renderPM.drawToFile(self, filename,fmt=bmFmt,showBoundary=getattr(self,'showBorder',rl_config.showBoundary),**_extraKW(self,'_renderPM_',**kw))
1863
086d685ad0cb Space saving optimisation
rgbecker
parents: 1862
diff changeset
   774
                ext = ext + '/.' + bmFmt
3636
13fddc3b90c4 shapes.py: pass filename into dtc.save not fnRoot
rgbecker
parents: 3617
diff changeset
   775
                if dtc: dtc.save(filename)
1176
4ef49823ccc7 Moved saved method from Andy's datacharts.py
rgbecker
parents: 1175
diff changeset
   776
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   777
        if 'eps' in plotMode:
2722
f2e2b2901e8c reportlab/graphics: fix rlextra dependency
rgbecker
parents: 2713
diff changeset
   778
            try:
f2e2b2901e8c reportlab/graphics: fix rlextra dependency
rgbecker
parents: 2713
diff changeset
   779
                from rlextra.graphics import renderPS_SEP as renderPS
2723
c3c3e87588d6 shapes.py: make import error check specific
rgbecker
parents: 2722
diff changeset
   780
            except ImportError:
2722
f2e2b2901e8c reportlab/graphics: fix rlextra dependency
rgbecker
parents: 2713
diff changeset
   781
                from reportlab.graphics import renderPS
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   782
            filename = fnroot+'.eps'
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3636
diff changeset
   783
            if verbose: print(genFmt % ('EPS',filename))
2722
f2e2b2901e8c reportlab/graphics: fix rlextra dependency
rgbecker
parents: 2713
diff changeset
   784
            renderPS.drawToFile(self,
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   785
                                filename,
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   786
                                title = fnroot,
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   787
                                dept = getattr(self,'EPS_info',['Testing'])[0],
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   788
                                company = getattr(self,'EPS_info',['','ReportLab'])[1],
2787
0fbc57094aaa rl_config.py: add eps_preview & eps_ttf_embed
rgbecker
parents: 2756
diff changeset
   789
                                preview = getattr(self,'preview',rl_config.eps_preview),
0fbc57094aaa rl_config.py: add eps_preview & eps_ttf_embed
rgbecker
parents: 2756
diff changeset
   790
                                showBoundary=getattr(self,'showBorder',rl_config.showBoundary),
0fbc57094aaa rl_config.py: add eps_preview & eps_ttf_embed
rgbecker
parents: 2756
diff changeset
   791
                                ttf_embed=getattr(self,'ttf_embed',rl_config.eps_ttf_embed),
0fbc57094aaa rl_config.py: add eps_preview & eps_ttf_embed
rgbecker
parents: 2756
diff changeset
   792
                                **_extraKW(self,'_renderPS_',**kw))
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   793
            ext = ext +  '/.eps'
1176
4ef49823ccc7 Moved saved method from Andy's datacharts.py
rgbecker
parents: 1175
diff changeset
   794
2545
107f45cde70c reportlab: add defaultGraphicsFontName, svg saving
rgbecker
parents: 2544
diff changeset
   795
        if 'svg' in plotMode:
107f45cde70c reportlab: add defaultGraphicsFontName, svg saving
rgbecker
parents: 2544
diff changeset
   796
            from reportlab.graphics import renderSVG
107f45cde70c reportlab: add defaultGraphicsFontName, svg saving
rgbecker
parents: 2544
diff changeset
   797
            filename = fnroot+'.svg'
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3636
diff changeset
   798
            if verbose: print(genFmt % ('SVG',filename))
2545
107f45cde70c reportlab: add defaultGraphicsFontName, svg saving
rgbecker
parents: 2544
diff changeset
   799
            renderSVG.drawToFile(self,
107f45cde70c reportlab: add defaultGraphicsFontName, svg saving
rgbecker
parents: 2544
diff changeset
   800
                                filename,
107f45cde70c reportlab: add defaultGraphicsFontName, svg saving
rgbecker
parents: 2544
diff changeset
   801
                                showBoundary=getattr(self,'showBorder',rl_config.showBoundary),**_extraKW(self,'_renderSVG_',**kw))
107f45cde70c reportlab: add defaultGraphicsFontName, svg saving
rgbecker
parents: 2544
diff changeset
   802
            ext = ext +  '/.svg'
107f45cde70c reportlab: add defaultGraphicsFontName, svg saving
rgbecker
parents: 2544
diff changeset
   803
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   804
        if 'ps' in plotMode:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   805
            from reportlab.graphics import renderPS
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   806
            filename = fnroot+'.ps'
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3636
diff changeset
   807
            if verbose: print(genFmt % ('EPS',filename))
2453
9f133df197b4 shapes.py: added save renderer specific argument handling
rgbecker
parents: 2341
diff changeset
   808
            renderPS.drawToFile(self, filename, showBoundary=getattr(self,'showBorder',rl_config.showBoundary),**_extraKW(self,'_renderPS_',**kw))
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   809
            ext = ext +  '/.ps'
1176
4ef49823ccc7 Moved saved method from Andy's datacharts.py
rgbecker
parents: 1175
diff changeset
   810
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   811
        if 'py' in plotMode:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   812
            filename = fnroot+'.py'
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3636
diff changeset
   813
            if verbose: print(genFmt % ('py',filename))
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   814
            open(filename,'w').write(self._renderPy())
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   815
            ext = ext +  '/.py'
1411
7ce14dbd7578 Added .py save format for Drawings, seems to work
rgbecker
parents: 1388
diff changeset
   816
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   817
        logger.warnOnce.enabled, logger.infoOnce.enabled = _saved
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   818
        if hasattr(self,'saveLogger'):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   819
            self.saveLogger(fnroot,ext)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   820
        return ext and fnroot+ext[1:] or ''
1176
4ef49823ccc7 Moved saved method from Andy's datacharts.py
rgbecker
parents: 1175
diff changeset
   821
2811
3062d7ba9d04 reportlab/graphics: add tiffl, tiff1 formats & allow for kwds in asString
rgbecker
parents: 2804
diff changeset
   822
    def asString(self, format, verbose=None, preview=0, **kw):
1862
11f6cd4b0f07 Drawings can now do asString(format)
andy_robinson
parents: 1843
diff changeset
   823
        """Converts to an 8 bit string in given format."""
2811
3062d7ba9d04 reportlab/graphics: add tiffl, tiff1 formats & allow for kwds in asString
rgbecker
parents: 2804
diff changeset
   824
        assert format in ('pdf','ps','eps','gif','png','jpg','jpeg','bmp','ppm','tiff','tif','py','pict','pct','tiffp','tiffl','tiff1'), 'Unknown file format "%s"' % format
1862
11f6cd4b0f07 Drawings can now do asString(format)
andy_robinson
parents: 1843
diff changeset
   825
        from reportlab import rl_config
11f6cd4b0f07 Drawings can now do asString(format)
andy_robinson
parents: 1843
diff changeset
   826
        #verbose = verbose is not None and (verbose,) or (getattr(self,'verbose',verbose),)[0]
11f6cd4b0f07 Drawings can now do asString(format)
andy_robinson
parents: 1843
diff changeset
   827
        if format == 'pdf':
11f6cd4b0f07 Drawings can now do asString(format)
andy_robinson
parents: 1843
diff changeset
   828
            from reportlab.graphics import renderPDF
11f6cd4b0f07 Drawings can now do asString(format)
andy_robinson
parents: 1843
diff changeset
   829
            return renderPDF.drawToString(self)
2811
3062d7ba9d04 reportlab/graphics: add tiffl, tiff1 formats & allow for kwds in asString
rgbecker
parents: 2804
diff changeset
   830
        elif format in ('gif','png','tif','tiff','jpg','pct','pict','bmp','ppm','tiffp','tiffl','tiff1'):
1862
11f6cd4b0f07 Drawings can now do asString(format)
andy_robinson
parents: 1843
diff changeset
   831
            from reportlab.graphics import renderPM
2811
3062d7ba9d04 reportlab/graphics: add tiffl, tiff1 formats & allow for kwds in asString
rgbecker
parents: 2804
diff changeset
   832
            return renderPM.drawToString(self, fmt=format,showBoundary=getattr(self,'showBorder',
3062d7ba9d04 reportlab/graphics: add tiffl, tiff1 formats & allow for kwds in asString
rgbecker
parents: 2804
diff changeset
   833
                            rl_config.showBoundary),**_extraKW(self,'_renderPM_',**kw))
1862
11f6cd4b0f07 Drawings can now do asString(format)
andy_robinson
parents: 1843
diff changeset
   834
        elif format == 'eps':
2722
f2e2b2901e8c reportlab/graphics: fix rlextra dependency
rgbecker
parents: 2713
diff changeset
   835
            try:
f2e2b2901e8c reportlab/graphics: fix rlextra dependency
rgbecker
parents: 2713
diff changeset
   836
                from rlextra.graphics import renderPS_SEP as renderPS
2723
c3c3e87588d6 shapes.py: make import error check specific
rgbecker
parents: 2722
diff changeset
   837
            except ImportError:
2722
f2e2b2901e8c reportlab/graphics: fix rlextra dependency
rgbecker
parents: 2713
diff changeset
   838
                from reportlab.graphics import renderPS
f2e2b2901e8c reportlab/graphics: fix rlextra dependency
rgbecker
parents: 2713
diff changeset
   839
f2e2b2901e8c reportlab/graphics: fix rlextra dependency
rgbecker
parents: 2713
diff changeset
   840
            return renderPS.drawToString(self,
2031
804dc4b66daf Andy's fix for turning on or off previews in EPS output.
johnprecedo
parents: 2016
diff changeset
   841
                                preview = preview,
1862
11f6cd4b0f07 Drawings can now do asString(format)
andy_robinson
parents: 1843
diff changeset
   842
                                showBoundary=getattr(self,'showBorder',rl_config.showBoundary))
11f6cd4b0f07 Drawings can now do asString(format)
andy_robinson
parents: 1843
diff changeset
   843
        elif format == 'ps':
11f6cd4b0f07 Drawings can now do asString(format)
andy_robinson
parents: 1843
diff changeset
   844
            from reportlab.graphics import renderPS
11f6cd4b0f07 Drawings can now do asString(format)
andy_robinson
parents: 1843
diff changeset
   845
            return renderPS.drawToString(self, showBoundary=getattr(self,'showBorder',rl_config.showBoundary))
11f6cd4b0f07 Drawings can now do asString(format)
andy_robinson
parents: 1843
diff changeset
   846
        elif format == 'py':
11f6cd4b0f07 Drawings can now do asString(format)
andy_robinson
parents: 1843
diff changeset
   847
            return self._renderPy()
11f6cd4b0f07 Drawings can now do asString(format)
andy_robinson
parents: 1843
diff changeset
   848
3218
3bb9866ff9a0 shapes.py: add resized method to Drawing class
rgbecker
parents: 3216
diff changeset
   849
    def resized(self,kind='fit',lpad=0,rpad=0,bpad=0,tpad=0):
3bb9866ff9a0 shapes.py: add resized method to Drawing class
rgbecker
parents: 3216
diff changeset
   850
        '''return a base class drawing which ensures all the contents fits'''
3bb9866ff9a0 shapes.py: add resized method to Drawing class
rgbecker
parents: 3216
diff changeset
   851
        C = self.getContents()
3bb9866ff9a0 shapes.py: add resized method to Drawing class
rgbecker
parents: 3216
diff changeset
   852
        oW = self.width
3bb9866ff9a0 shapes.py: add resized method to Drawing class
rgbecker
parents: 3216
diff changeset
   853
        oH = self.height
3bb9866ff9a0 shapes.py: add resized method to Drawing class
rgbecker
parents: 3216
diff changeset
   854
        drawing = Drawing(oW,oH,*C)
3bb9866ff9a0 shapes.py: add resized method to Drawing class
rgbecker
parents: 3216
diff changeset
   855
        xL,yL,xH,yH = drawing.getBounds()
3bb9866ff9a0 shapes.py: add resized method to Drawing class
rgbecker
parents: 3216
diff changeset
   856
        if kind=='fit' or (kind=='expand' and (xL<lpad or xH>oW-rpad or yL<bpad or yH>oH-tpad)):
3221
42bed4aac15c shapes.py: add kind=fity,fitx,expandx,expandy in Drawing.resized
rgbecker
parents: 3219
diff changeset
   857
            drawing.width = xH-xL+lpad+rpad
42bed4aac15c shapes.py: add kind=fity,fitx,expandx,expandy in Drawing.resized
rgbecker
parents: 3219
diff changeset
   858
            drawing.height = yH-yL+tpad+bpad
3218
3bb9866ff9a0 shapes.py: add resized method to Drawing class
rgbecker
parents: 3216
diff changeset
   859
            drawing.transform = (1,0,0,1,lpad-xL,bpad-yL)
3221
42bed4aac15c shapes.py: add kind=fity,fitx,expandx,expandy in Drawing.resized
rgbecker
parents: 3219
diff changeset
   860
        elif kind=='fitx' or (kind=='expandx' and (xL<lpad or xH>oW-rpad)):
42bed4aac15c shapes.py: add kind=fity,fitx,expandx,expandy in Drawing.resized
rgbecker
parents: 3219
diff changeset
   861
            drawing.width = xH-xL+lpad+rpad
42bed4aac15c shapes.py: add kind=fity,fitx,expandx,expandy in Drawing.resized
rgbecker
parents: 3219
diff changeset
   862
            drawing.transform = (1,0,0,1,lpad-xL,0)
42bed4aac15c shapes.py: add kind=fity,fitx,expandx,expandy in Drawing.resized
rgbecker
parents: 3219
diff changeset
   863
        elif kind=='fity' or (kind=='expandy' and (yL<bpad or yH>oH-tpad)):
42bed4aac15c shapes.py: add kind=fity,fitx,expandx,expandy in Drawing.resized
rgbecker
parents: 3219
diff changeset
   864
            drawing.height = yH-yL+tpad+bpad
42bed4aac15c shapes.py: add kind=fity,fitx,expandx,expandy in Drawing.resized
rgbecker
parents: 3219
diff changeset
   865
            drawing.transform = (1,0,0,1,0,bpad-yL)
3218
3bb9866ff9a0 shapes.py: add resized method to Drawing class
rgbecker
parents: 3216
diff changeset
   866
        return drawing
3bb9866ff9a0 shapes.py: add resized method to Drawing class
rgbecker
parents: 3216
diff changeset
   867
1015
7589ecd3b446 Added Null _DrawingEditorMixin class
rgbecker
parents: 976
diff changeset
   868
class _DrawingEditorMixin:
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   869
    '''This is a mixin to provide functionality for edited drawings'''
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   870
    def _add(self,obj,value,name=None,validate=None,desc=None,pos=None):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   871
        '''
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   872
        effectively setattr(obj,name,value), but takes care of things with _attrMaps etc
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   873
        '''
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   874
        ivc = isValidChild(value)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   875
        if name and hasattr(obj,'_attrMap'):
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3280
diff changeset
   876
            if '_attrMap' not in obj.__dict__:
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   877
                obj._attrMap = obj._attrMap.clone()
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   878
            if ivc and validate is None: validate = isValidChild
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   879
            obj._attrMap[name] = AttrMapValue(validate,desc)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   880
        if hasattr(obj,'add') and ivc:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   881
            if pos:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   882
                obj.insert(pos,value,name)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   883
            else:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   884
                obj.add(value,name)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   885
        elif name:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   886
            setattr(obj,name,value)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   887
        else:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3636
diff changeset
   888
            raise ValueError("Can't add, need name")
1015
7589ecd3b446 Added Null _DrawingEditorMixin class
rgbecker
parents: 976
diff changeset
   889
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
   890
class LineShape(Shape):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   891
    # base for types of lines
759
f68f95c44f77 Improved Auto class.
dinu_gherman
parents: 747
diff changeset
   892
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   893
    _attrMap = AttrMap(
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   894
        strokeColor = AttrMapValue(isColorOrNone),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   895
        strokeWidth = AttrMapValue(isNumber),
3234
070271955526 graphics: add in some line properties
rgbecker
parents: 3224
diff changeset
   896
        strokeLineCap = AttrMapValue(OneOf(0,1,2),desc="Line cap 0=butt, 1=round & 2=square"),
070271955526 graphics: add in some line properties
rgbecker
parents: 3224
diff changeset
   897
        strokeLineJoin = AttrMapValue(OneOf(0,1,2),desc="Line join 0=miter, 1=round & 2=bevel"),
070271955526 graphics: add in some line properties
rgbecker
parents: 3224
diff changeset
   898
        strokeMiterLimit = AttrMapValue(isNumber,desc="miter limit control miter line joins"),
3269
87f51df3bc0b attributes changed to advanced usage level
meitham
parents: 3251
diff changeset
   899
        strokeDashArray = AttrMapValue(isListOfNumbersOrNone,desc="a sequence of numbers represents on and off, e.g. (2,1)"),
3280
2ac121cd0ee5 shapes.py: fix behaviour of opacity versus colour alphas
rgbecker
parents: 3272
diff changeset
   900
        strokeOpacity = AttrMapValue(isOpacity,desc="The level of transparency of the line, any real number betwen 0 and 1"),
3223
f39aeb52a144 shapes.py: add overprint properties to group and don't ever initialize
rgbecker
parents: 3221
diff changeset
   901
        strokeOverprint = AttrMapValue(isBoolean,desc='Turn on stroke overprinting'),
3417
6b2786216805 graphics: add support for overprintMask
rgbecker
parents: 3405
diff changeset
   902
        overprintMask = AttrMapValue(isBoolean,desc='overprinting for ordinary CMYK',advancedUsage=1),
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   903
        )
759
f68f95c44f77 Improved Auto class.
dinu_gherman
parents: 747
diff changeset
   904
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   905
    def __init__(self, kw):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   906
        self.strokeColor = STATE_DEFAULTS['strokeColor']
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   907
        self.strokeWidth = 1
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   908
        self.strokeLineCap = 0
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   909
        self.strokeLineJoin = 0
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   910
        self.strokeMiterLimit = 0
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   911
        self.strokeDashArray = None
3280
2ac121cd0ee5 shapes.py: fix behaviour of opacity versus colour alphas
rgbecker
parents: 3272
diff changeset
   912
        self.strokeOpacity = None
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   913
        self.setProperties(kw)
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
   914
759
f68f95c44f77 Improved Auto class.
dinu_gherman
parents: 747
diff changeset
   915
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
   916
class Line(LineShape):
1706
3081471a4e9d Experimental ShadedPolygon added
rgbecker
parents: 1697
diff changeset
   917
    _attrMap = AttrMap(BASE=LineShape,
3269
87f51df3bc0b attributes changed to advanced usage level
meitham
parents: 3251
diff changeset
   918
        x1 = AttrMapValue(isNumber,desc=""),
87f51df3bc0b attributes changed to advanced usage level
meitham
parents: 3251
diff changeset
   919
        y1 = AttrMapValue(isNumber,desc=""),
87f51df3bc0b attributes changed to advanced usage level
meitham
parents: 3251
diff changeset
   920
        x2 = AttrMapValue(isNumber,desc=""),
87f51df3bc0b attributes changed to advanced usage level
meitham
parents: 3251
diff changeset
   921
        y2 = AttrMapValue(isNumber,desc=""),
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   922
        )
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
   923
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   924
    def __init__(self, x1, y1, x2, y2, **kw):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   925
        LineShape.__init__(self, kw)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   926
        self.x1 = x1
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   927
        self.y1 = y1
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   928
        self.x2 = x2
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   929
        self.y2 = y2
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
   930
2004
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   931
    def getBounds(self):
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   932
        "Returns bounding rectangle of object as (x1,y1,x2,y2)"
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
   933
        return (self.x1, self.y1, self.x2, self.y2)
2005
7429e51e3afb Slight efficiency saving & code reuse
rgbecker
parents: 2004
diff changeset
   934
1706
3081471a4e9d Experimental ShadedPolygon added
rgbecker
parents: 1697
diff changeset
   935
class SolidShape(LineShape):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   936
    # base for anything with outline and content
759
f68f95c44f77 Improved Auto class.
dinu_gherman
parents: 747
diff changeset
   937
1706
3081471a4e9d Experimental ShadedPolygon added
rgbecker
parents: 1697
diff changeset
   938
    _attrMap = AttrMap(BASE=LineShape,
3269
87f51df3bc0b attributes changed to advanced usage level
meitham
parents: 3251
diff changeset
   939
        fillColor = AttrMapValue(isColorOrNone,desc="filling color of the shape, e.g. red"),
3280
2ac121cd0ee5 shapes.py: fix behaviour of opacity versus colour alphas
rgbecker
parents: 3272
diff changeset
   940
        fillOpacity = AttrMapValue(isOpacity,desc="the level of transparency of the color, any real number between 0 and 1"),
3223
f39aeb52a144 shapes.py: add overprint properties to group and don't ever initialize
rgbecker
parents: 3221
diff changeset
   941
        fillOverprint = AttrMapValue(isBoolean,desc='Turn on fill overprinting'),
3417
6b2786216805 graphics: add support for overprintMask
rgbecker
parents: 3405
diff changeset
   942
        overprintMask = AttrMapValue(isBoolean,desc='overprinting for ordinary CMYK',advancedUsage=1),
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   943
        )
759
f68f95c44f77 Improved Auto class.
dinu_gherman
parents: 747
diff changeset
   944
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   945
    def __init__(self, kw):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   946
        self.fillColor = STATE_DEFAULTS['fillColor']
3280
2ac121cd0ee5 shapes.py: fix behaviour of opacity versus colour alphas
rgbecker
parents: 3272
diff changeset
   947
        self.fillOpacity = None
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   948
        # do this at the end so keywords overwrite
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   949
        #the above settings
1706
3081471a4e9d Experimental ShadedPolygon added
rgbecker
parents: 1697
diff changeset
   950
        LineShape.__init__(self, kw)
976
47930c35c069 Correct names and factorise some behaviour
rgbecker
parents: 952
diff changeset
   951
759
f68f95c44f77 Improved Auto class.
dinu_gherman
parents: 747
diff changeset
   952
1071
eb266be600ed Just van Rossum's path patch
rgbecker
parents: 1056
diff changeset
   953
# path operator  constants
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3636
diff changeset
   954
_MOVETO, _LINETO, _CURVETO, _CLOSEPATH = list(range(4))
1318
394927c4a99c Added symbolic definePath function
rgbecker
parents: 1262
diff changeset
   955
_PATH_OP_ARG_COUNT = (2, 2, 6, 0)  # [moveTo, lineTo, curveTo, closePath]
394927c4a99c Added symbolic definePath function
rgbecker
parents: 1262
diff changeset
   956
_PATH_OP_NAMES=['moveTo','lineTo','curveTo','closePath']
1071
eb266be600ed Just van Rossum's path patch
rgbecker
parents: 1056
diff changeset
   957
eb266be600ed Just van Rossum's path patch
rgbecker
parents: 1056
diff changeset
   958
def _renderPath(path, drawFuncs):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   959
    """Helper function for renderers."""
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   960
    # this could be a method of Path...
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   961
    points = path.points
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   962
    i = 0
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   963
    hadClosePath = 0
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   964
    hadMoveTo = 0
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   965
    for op in path.operators:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   966
        nArgs = _PATH_OP_ARG_COUNT[op]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   967
        func = drawFuncs[op]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   968
        j = i + nArgs
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3280
diff changeset
   969
        func(*points[i:j])
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   970
        i = j
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   971
        if op == _CLOSEPATH:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   972
            hadClosePath = hadClosePath + 1
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   973
        if op == _MOVETO:
3541
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
   974
            hadMoveTo += 1
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   975
    return hadMoveTo == hadClosePath
1071
eb266be600ed Just van Rossum's path patch
rgbecker
parents: 1056
diff changeset
   976
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
   977
class Path(SolidShape):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   978
    """Path, made up of straight lines and bezier curves."""
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1680
diff changeset
   979
1706
3081471a4e9d Experimental ShadedPolygon added
rgbecker
parents: 1697
diff changeset
   980
    _attrMap = AttrMap(BASE=SolidShape,
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   981
        points = AttrMapValue(isListOfNumbers),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   982
        operators = AttrMapValue(isListOfNumbers),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   983
        isClipPath = AttrMapValue(isBoolean),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   984
        )
1071
eb266be600ed Just van Rossum's path patch
rgbecker
parents: 1056
diff changeset
   985
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   986
    def __init__(self, points=None, operators=None, isClipPath=0, **kw):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   987
        SolidShape.__init__(self, kw)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   988
        if points is None:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   989
            points = []
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   990
        if operators is None:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   991
            operators = []
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   992
        assert len(points) % 2 == 0, 'Point list must have even number of elements!'
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   993
        self.points = points
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   994
        self.operators = operators
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   995
        self.isClipPath = isClipPath
1071
eb266be600ed Just van Rossum's path patch
rgbecker
parents: 1056
diff changeset
   996
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   997
    def copy(self):
2552
0ce835bc29df shapes.py: make copy use derived class if not overridden
rgbecker
parents: 2551
diff changeset
   998
        new = self.__class__(self.points[:], self.operators[:])
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
   999
        new.setProperties(self.getProperties())
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1000
        return new
1071
eb266be600ed Just van Rossum's path patch
rgbecker
parents: 1056
diff changeset
  1001
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1002
    def moveTo(self, x, y):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1003
        self.points.extend([x, y])
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1004
        self.operators.append(_MOVETO)
1071
eb266be600ed Just van Rossum's path patch
rgbecker
parents: 1056
diff changeset
  1005
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1006
    def lineTo(self, x, y):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1007
        self.points.extend([x, y])
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1008
        self.operators.append(_LINETO)
1071
eb266be600ed Just van Rossum's path patch
rgbecker
parents: 1056
diff changeset
  1009
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1010
    def curveTo(self, x1, y1, x2, y2, x3, y3):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1011
        self.points.extend([x1, y1, x2, y2, x3, y3])
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1012
        self.operators.append(_CURVETO)
1071
eb266be600ed Just van Rossum's path patch
rgbecker
parents: 1056
diff changeset
  1013
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1014
    def closePath(self):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1015
        self.operators.append(_CLOSEPATH)
759
f68f95c44f77 Improved Auto class.
dinu_gherman
parents: 747
diff changeset
  1016
2004
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
  1017
    def getBounds(self):
3541
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
  1018
        points = self.points
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
  1019
        try:    #in case this complex algorithm is not yet ready :)
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
  1020
            X = []
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
  1021
            aX = X.append
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
  1022
            eX = X.extend
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
  1023
            Y=[]
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
  1024
            aY = Y.append
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
  1025
            eY = Y.extend
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
  1026
            i = 0
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
  1027
            for op in self.operators:
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
  1028
                nArgs = _PATH_OP_ARG_COUNT[op]
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
  1029
                j = i + nArgs
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
  1030
                if nArgs==2:
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
  1031
                    #either moveTo or lineT0
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
  1032
                    aX(points[i])
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
  1033
                    aY(points[i+1])
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
  1034
                elif nArgs==6:
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
  1035
                    #curveTo
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
  1036
                    x1,x2,x3 = points[i:j:2]
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
  1037
                    eX(_getBezierExtrema(X[-1],x1,x2,x3))
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
  1038
                    y1,y2,y3 = points[i+1:j:2]
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
  1039
                    eY(_getBezierExtrema(Y[-1],y1,y2,y3))
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
  1040
                i = j
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
  1041
            return min(X),min(Y),max(X),max(Y)
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
  1042
        except:
a0d3fbb6be84 shapes.py: better bounds for Paths
rgbecker
parents: 3417
diff changeset
  1043
            return getPathBounds(points)
2005
7429e51e3afb Slight efficiency saving & code reuse
rgbecker
parents: 2004
diff changeset
  1044
2016
a816a3167340 Comment problematic PICT code
rgbecker
parents: 2014
diff changeset
  1045
EmptyClipPath=Path()    #special path
a816a3167340 Comment problematic PICT code
rgbecker
parents: 2014
diff changeset
  1046
a816a3167340 Comment problematic PICT code
rgbecker
parents: 2014
diff changeset
  1047
def getArcPoints(centerx, centery, radius, startangledegrees, endangledegrees, yradius=None, degreedelta=None, reverse=None):
2014
d3b7259b90d5 Added getArcPoints & ArcPath
rgbecker
parents: 2005
diff changeset
  1048
    if yradius is None: yradius = radius
d3b7259b90d5 Added getArcPoints & ArcPath
rgbecker
parents: 2005
diff changeset
  1049
    points = []
d3b7259b90d5 Added getArcPoints & ArcPath
rgbecker
parents: 2005
diff changeset
  1050
    from math import sin, cos, pi
d3b7259b90d5 Added getArcPoints & ArcPath
rgbecker
parents: 2005
diff changeset
  1051
    degreestoradians = pi/180.0
d3b7259b90d5 Added getArcPoints & ArcPath
rgbecker
parents: 2005
diff changeset
  1052
    startangle = startangledegrees*degreestoradians
d3b7259b90d5 Added getArcPoints & ArcPath
rgbecker
parents: 2005
diff changeset
  1053
    endangle = endangledegrees*degreestoradians
d3b7259b90d5 Added getArcPoints & ArcPath
rgbecker
parents: 2005
diff changeset
  1054
    while endangle<startangle:
d3b7259b90d5 Added getArcPoints & ArcPath
rgbecker
parents: 2005
diff changeset
  1055
        endangle = endangle+2*pi
2040
a9e8ba06f8c1 Attempt to be slightly cleverer about small segments
rgbecker
parents: 2031
diff changeset
  1056
    angle = float(endangle - startangle)
2536
bcd6fe869387 reportlab: fix small angle addArc & Wedge.asPolygon
rgbecker
parents: 2504
diff changeset
  1057
    a = points.append
2040
a9e8ba06f8c1 Attempt to be slightly cleverer about small segments
rgbecker
parents: 2031
diff changeset
  1058
    if angle>.001:
2536
bcd6fe869387 reportlab: fix small angle addArc & Wedge.asPolygon
rgbecker
parents: 2504
diff changeset
  1059
        degreedelta = min(angle,degreedelta or 1.)
bcd6fe869387 reportlab: fix small angle addArc & Wedge.asPolygon
rgbecker
parents: 2504
diff changeset
  1060
        radiansdelta = degreedelta*degreestoradians
2040
a9e8ba06f8c1 Attempt to be slightly cleverer about small segments
rgbecker
parents: 2031
diff changeset
  1061
        n = max(int(angle/radiansdelta+0.5),1)
a9e8ba06f8c1 Attempt to be slightly cleverer about small segments
rgbecker
parents: 2031
diff changeset
  1062
        radiansdelta = angle/n
2536
bcd6fe869387 reportlab: fix small angle addArc & Wedge.asPolygon
rgbecker
parents: 2504
diff changeset
  1063
        n += 1
bcd6fe869387 reportlab: fix small angle addArc & Wedge.asPolygon
rgbecker
parents: 2504
diff changeset
  1064
    else:
bcd6fe869387 reportlab: fix small angle addArc & Wedge.asPolygon
rgbecker
parents: 2504
diff changeset
  1065
        n = 1
bcd6fe869387 reportlab: fix small angle addArc & Wedge.asPolygon
rgbecker
parents: 2504
diff changeset
  1066
        radiansdelta = 0
bcd6fe869387 reportlab: fix small angle addArc & Wedge.asPolygon
rgbecker
parents: 2504
diff changeset
  1067
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3636
diff changeset
  1068
    for angle in range(n):
2536
bcd6fe869387 reportlab: fix small angle addArc & Wedge.asPolygon
rgbecker
parents: 2504
diff changeset
  1069
        angle = startangle+angle*radiansdelta
bcd6fe869387 reportlab: fix small angle addArc & Wedge.asPolygon
rgbecker
parents: 2504
diff changeset
  1070
        a((centerx+radius*cos(angle),centery+yradius*sin(angle)))
bcd6fe869387 reportlab: fix small angle addArc & Wedge.asPolygon
rgbecker
parents: 2504
diff changeset
  1071
bcd6fe869387 reportlab: fix small angle addArc & Wedge.asPolygon
rgbecker
parents: 2504
diff changeset
  1072
    if reverse: points.reverse()
2014
d3b7259b90d5 Added getArcPoints & ArcPath
rgbecker
parents: 2005
diff changeset
  1073
    return points
d3b7259b90d5 Added getArcPoints & ArcPath
rgbecker
parents: 2005
diff changeset
  1074
d3b7259b90d5 Added getArcPoints & ArcPath
rgbecker
parents: 2005
diff changeset
  1075
class ArcPath(Path):
d3b7259b90d5 Added getArcPoints & ArcPath
rgbecker
parents: 2005
diff changeset
  1076
    '''Path with an addArc method'''
2016
a816a3167340 Comment problematic PICT code
rgbecker
parents: 2014
diff changeset
  1077
    def addArc(self, centerx, centery, radius, startangledegrees, endangledegrees, yradius=None, degreedelta=None, moveTo=None, reverse=None):
a816a3167340 Comment problematic PICT code
rgbecker
parents: 2014
diff changeset
  1078
        P = getArcPoints(centerx, centery, radius, startangledegrees, endangledegrees, yradius=yradius, degreedelta=degreedelta, reverse=reverse)
2014
d3b7259b90d5 Added getArcPoints & ArcPath
rgbecker
parents: 2005
diff changeset
  1079
        if moveTo or not len(self.operators):
d3b7259b90d5 Added getArcPoints & ArcPath
rgbecker
parents: 2005
diff changeset
  1080
            self.moveTo(P[0][0],P[0][1])
d3b7259b90d5 Added getArcPoints & ArcPath
rgbecker
parents: 2005
diff changeset
  1081
            del P[0]
d3b7259b90d5 Added getArcPoints & ArcPath
rgbecker
parents: 2005
diff changeset
  1082
        for x, y in P: self.lineTo(x,y)
d3b7259b90d5 Added getArcPoints & ArcPath
rgbecker
parents: 2005
diff changeset
  1083
1348
2acaf5d2d8d9 Added dx, dy to definePath
rgbecker
parents: 1334
diff changeset
  1084
def definePath(pathSegs=[],isClipPath=0, dx=0, dy=0, **kw):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1085
    O = []
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1086
    P = []
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1087
    for seg in pathSegs:
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1680
diff changeset
  1088
        if type(seg) not in [ListType,TupleType]:
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1089
            opName = seg
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1090
            args = []
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1091
        else:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1092
            opName = seg[0]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1093
            args = seg[1:]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1094
        if opName not in _PATH_OP_NAMES:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3636
diff changeset
  1095
            raise ValueError('bad operator name %s' % opName)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1096
        op = _PATH_OP_NAMES.index(opName)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1097
        if len(args)!=_PATH_OP_ARG_COUNT[op]:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3636
diff changeset
  1098
            raise ValueError('%s bad arguments %s' % (opName,str(args)))
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1099
        O.append(op)
1757
97a30ce781ee Fix for tuple case in definePath
rgbecker
parents: 1706
diff changeset
  1100
        P.extend(list(args))
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1101
    for d,o in (dx,0), (dy,1):
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3636
diff changeset
  1102
        for i in range(o,len(P),2):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1103
            P[i] = P[i]+d
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3280
diff changeset
  1104
    return Path(P,O,isClipPath,**kw)
976
47930c35c069 Correct names and factorise some behaviour
rgbecker
parents: 952
diff changeset
  1105
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
  1106
class Rect(SolidShape):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1107
    """Rectangle, possibly with rounded corners."""
759
f68f95c44f77 Improved Auto class.
dinu_gherman
parents: 747
diff changeset
  1108
1706
3081471a4e9d Experimental ShadedPolygon added
rgbecker
parents: 1697
diff changeset
  1109
    _attrMap = AttrMap(BASE=SolidShape,
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1110
        x = AttrMapValue(isNumber),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1111
        y = AttrMapValue(isNumber),
3269
87f51df3bc0b attributes changed to advanced usage level
meitham
parents: 3251
diff changeset
  1112
        width = AttrMapValue(isNumber,desc="width of the object in points"),
87f51df3bc0b attributes changed to advanced usage level
meitham
parents: 3251
diff changeset
  1113
        height = AttrMapValue(isNumber,desc="height of the objects in points"),
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1114
        rx = AttrMapValue(isNumber),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1115
        ry = AttrMapValue(isNumber),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1116
        )
976
47930c35c069 Correct names and factorise some behaviour
rgbecker
parents: 952
diff changeset
  1117
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1118
    def __init__(self, x, y, width, height, rx=0, ry=0, **kw):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1119
        SolidShape.__init__(self, kw)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1120
        self.x = x
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1121
        self.y = y
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1122
        self.width = width
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1123
        self.height = height
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1124
        self.rx = rx
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1125
        self.ry = ry
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
  1126
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1127
    def copy(self):
2552
0ce835bc29df shapes.py: make copy use derived class if not overridden
rgbecker
parents: 2551
diff changeset
  1128
        new = self.__class__(self.x, self.y, self.width, self.height)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1129
        new.setProperties(self.getProperties())
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1130
        return new
976
47930c35c069 Correct names and factorise some behaviour
rgbecker
parents: 952
diff changeset
  1131
2004
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
  1132
    def getBounds(self):
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
  1133
        return (self.x, self.y, self.x + self.width, self.y + self.height)
2005
7429e51e3afb Slight efficiency saving & code reuse
rgbecker
parents: 2004
diff changeset
  1134
759
f68f95c44f77 Improved Auto class.
dinu_gherman
parents: 747
diff changeset
  1135
1609
34ab63314b38 Added Images shape class, currently only rendered in PDF.
dinu_gherman
parents: 1579
diff changeset
  1136
class Image(SolidShape):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1137
    """Bitmap image."""
1609
34ab63314b38 Added Images shape class, currently only rendered in PDF.
dinu_gherman
parents: 1579
diff changeset
  1138
1706
3081471a4e9d Experimental ShadedPolygon added
rgbecker
parents: 1697
diff changeset
  1139
    _attrMap = AttrMap(BASE=SolidShape,
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1140
        x = AttrMapValue(isNumber),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1141
        y = AttrMapValue(isNumber),
3269
87f51df3bc0b attributes changed to advanced usage level
meitham
parents: 3251
diff changeset
  1142
        width = AttrMapValue(isNumberOrNone,desc="width of the object in points"),
87f51df3bc0b attributes changed to advanced usage level
meitham
parents: 3251
diff changeset
  1143
        height = AttrMapValue(isNumberOrNone,desc="height of the objects in points"),
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1144
        path = AttrMapValue(None),
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1145
        )
1609
34ab63314b38 Added Images shape class, currently only rendered in PDF.
dinu_gherman
parents: 1579
diff changeset
  1146
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1147
    def __init__(self, x, y, width, height, path, **kw):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1148
        SolidShape.__init__(self, kw)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1149
        self.x = x
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1150
        self.y = y
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1151
        self.width = width
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1152
        self.height = height
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1153
        self.path = path
1609
34ab63314b38 Added Images shape class, currently only rendered in PDF.
dinu_gherman
parents: 1579
diff changeset
  1154
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1155
    def copy(self):
2552
0ce835bc29df shapes.py: make copy use derived class if not overridden
rgbecker
parents: 2551
diff changeset
  1156
        new = self.__class__(self.x, self.y, self.width, self.height, self.path)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1157
        new.setProperties(self.getProperties())
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1158
        return new
1609
34ab63314b38 Added Images shape class, currently only rendered in PDF.
dinu_gherman
parents: 1579
diff changeset
  1159
2004
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
  1160
    def getBounds(self):
3251
370eec41c436 added contribution
meitham
parents: 3249
diff changeset
  1161
        # bug fix contributed by Marcel Tromp <mtromp.docbook@gmail.com>
3249
376a7365b223 Bug: String exception raised in pdfdoc.py and Image.getBounds bug
meitham
parents: 3234
diff changeset
  1162
        return (self.x, self.y, self.x + self.width, self.y + self.height)
1609
34ab63314b38 Added Images shape class, currently only rendered in PDF.
dinu_gherman
parents: 1579
diff changeset
  1163
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
  1164
class Circle(SolidShape):
759
f68f95c44f77 Improved Auto class.
dinu_gherman
parents: 747
diff changeset
  1165
1706
3081471a4e9d Experimental ShadedPolygon added
rgbecker
parents: 1697
diff changeset
  1166
    _attrMap = AttrMap(BASE=SolidShape,
3269
87f51df3bc0b attributes changed to advanced usage level
meitham
parents: 3251
diff changeset
  1167
        cx = AttrMapValue(isNumber,desc="x of the centre"),
87f51df3bc0b attributes changed to advanced usage level
meitham
parents: 3251
diff changeset
  1168
        cy = AttrMapValue(isNumber,desc="y of the centre"),
87f51df3bc0b attributes changed to advanced usage level
meitham
parents: 3251
diff changeset
  1169
        r = AttrMapValue(isNumber,desc="radius in points"),
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1170
        )
976
47930c35c069 Correct names and factorise some behaviour
rgbecker
parents: 952
diff changeset
  1171
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1172
    def __init__(self, cx, cy, r, **kw):
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1173
        SolidShape.__init__(self, kw)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1174
        self.cx = cx
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1175
        self.cy = cy
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1176
        self.r = r
568
9cadc5ef53db Added graphics module
andy_robinson
parents:
diff changeset
  1177
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1178
    def copy(self):
2552
0ce835bc29df shapes.py: make copy use derived class if not overridden
rgbecker
parents: 2551
diff changeset
  1179
        new = self.__class__(self.cx, self.cy, self.r)
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1180
        new.setProperties(self.getProperties())
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1665
diff changeset
  1181
        return new
592
35f70c45f74c Fixed user node rendering bug, added barchart1
andy_robinson
parents: 590
diff changeset
  1182
2004
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
  1183
    def getBounds(self):
14a180d2691f Added getBounds() logic throughout graphics hierarchy
andy_robinson
parents: 1973
diff changeset
  1184
        return (self.cx - self.r, self.cy - self.r, self.cx + self.r, self.cy + self.r)
759