src/reportlab/pdfgen/pycanvas.py
author rgbecker
Wed, 03 Sep 2008 17:22:41 +0000
changeset 2967 ea62529bd1df
parent 2966 c9df63ccabdf
child 3032 22224b1b4d24
permissions -rw-r--r--
reportlab-2.2: first stage changes in on the trunk
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1777
48870c5f865a Jerome's New improved hasher
rgbecker
parents: 1771
diff changeset
     1
# a Pythonesque Canvas v0.8
1738
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
     2
# Author : Jerome Alet - <alet@librelogiciel.com>
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
     3
# License : ReportLab's license
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
     4
#
2966
c9df63ccabdf reportlab-2.2: major changes to make tests run
rgbecker
parents: 2964
diff changeset
     5
# $Id$
1777
48870c5f865a Jerome's New improved hasher
rgbecker
parents: 1771
diff changeset
     6
#
1738
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
     7
__doc__ = """pycanvas.Canvas : a Canvas class which can also output Python source code.
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
     8
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
     9
pycanvas.Canvas class works exactly like canvas.Canvas, but you can
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    10
call str() on pycanvas.Canvas instances. Doing so will return the
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    11
Python source code equivalent to your own program, which would, when
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    12
run, produce the same PDF document as your original program.
1742
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
    13
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    14
Generated Python source code defines a doIt() function which accepts
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    15
a filename or file-like object as its first parameter, and an
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    16
optional boolean parameter named "regenerate".
1738
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
    17
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    18
The doIt() function will generate a PDF document and save it in the
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    19
file you specified in this argument. If the regenerate parameter is
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    20
set then it will also return an automatically generated equivalent
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    21
Python source code as a string of text, which you can run again to
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    22
produce the very same PDF document and the Python source code, which
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    23
you can run again... ad nauseam ! If the regenerate parameter is
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    24
unset or not used at all (it then defaults to being unset) then None
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    25
is returned and the doIt() function is much much faster, it is also
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    26
much faster than the original non-serialized program.
1738
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
    27
2967
ea62529bd1df reportlab-2.2: first stage changes in on the trunk
rgbecker
parents: 2966
diff changeset
    28
the tests/test_pdfgen_pycanvas.py program is the test suite
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    29
for pycanvas, you can do the following to run it :
1738
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
    30
1740
71f51fea9301 Latest, well commented source
andy_robinson
parents: 1739
diff changeset
    31
    First set verbose=1 in reportlab/rl_config.py
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    32
1740
71f51fea9301 Latest, well commented source
andy_robinson
parents: 1739
diff changeset
    33
    then from the command interpreter :
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    34
2967
ea62529bd1df reportlab-2.2: first stage changes in on the trunk
rgbecker
parents: 2966
diff changeset
    35
    $ cd tests
1738
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
    36
    $ python test_pdfgen_pycanvas.py >n1.py
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    37
1738
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
    38
    this will produce both n1.py and test_pdfgen_pycanvas.pdf
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    39
1738
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
    40
    then :
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    41
1738
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
    42
    $ python n1.py n1.pdf >n2.py
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
    43
    $ python n2.py n2.pdf >n3.py
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
    44
    $ ...
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    45
1738
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
    46
    n1.py, n2.py, n3.py and so on will be identical files.
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    47
    they eventually may end being a bit different because of
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    48
    rounding problems, mostly in the comments, but this
1742
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
    49
    doesn't matter since the values really are the same
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
    50
    (e.g. 0 instead of 0.0, or .53 instead of 0.53)
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    51
1738
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
    52
    n1.pdf, n2.pdf, n3.pdf and so on will be PDF files
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
    53
    similar to test_pdfgen_pycanvas.pdf.
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    54
1738
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
    55
Alternatively you can import n1.py (or n3.py, or n16384.py if you prefer)
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
    56
in your own program, and then call its doIt function :
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
    57
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
    58
    import n1
1742
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
    59
    pythonsource = n1.doIt("myfile.pdf", regenerate=1)
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    60
1742
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
    61
Or if you don't need the python source code and want a faster result :
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
    62
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
    63
    import n1
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
    64
    n1.doIt("myfile.pdf")
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    65
1742
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
    66
When the generated source code is run directly as an independant program,
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
    67
then the equivalent python source code is printed to stdout, e.g. :
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
    68
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    69
    python n1.py
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    70
1742
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
    71
    will print the python source code equivalent to n1.py
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
    72
1738
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
    73
Why would you want to use such a beast ?
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    74
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    75
    - To linearize (serialize?) a program : optimizing some complex
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    76
      parts for example.
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    77
1740
71f51fea9301 Latest, well commented source
andy_robinson
parents: 1739
diff changeset
    78
    - To debug : reading the generated Python source code may help you or
71f51fea9301 Latest, well commented source
andy_robinson
parents: 1739
diff changeset
    79
      the ReportLab team to diagnose problems. The generated code is now
71f51fea9301 Latest, well commented source
andy_robinson
parents: 1739
diff changeset
    80
      clearly commented and shows nesting levels, page numbers, and so
71f51fea9301 Latest, well commented source
andy_robinson
parents: 1739
diff changeset
    81
      on. You can use the generated script when asking for support : we
71f51fea9301 Latest, well commented source
andy_robinson
parents: 1739
diff changeset
    82
      can see the results you obtain without needing your datas or complete
71f51fea9301 Latest, well commented source
andy_robinson
parents: 1739
diff changeset
    83
      application.
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    84
1738
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
    85
    - To create standalone scripts : say your program uses a high level
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    86
      environment to generate its output (databases, RML, etc...), using
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    87
      this class would give you an equivalent program but with complete
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    88
      independance from the high level environment (e.g. if you don't
1740
71f51fea9301 Latest, well commented source
andy_robinson
parents: 1739
diff changeset
    89
      have Oracle).
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    90
1740
71f51fea9301 Latest, well commented source
andy_robinson
parents: 1739
diff changeset
    91
    - To contribute some nice looking PDF documents to the ReportLab website
71f51fea9301 Latest, well commented source
andy_robinson
parents: 1739
diff changeset
    92
      without having to send a complete application you don't want to
71f51fea9301 Latest, well commented source
andy_robinson
parents: 1739
diff changeset
    93
      distribute.
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    94
1738
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
    95
    - ... Insert your own ideas here ...
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
    96
1738
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
    97
    - For fun because you can do it !
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
    98
"""
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
    99
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   100
import cStringIO
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   101
from reportlab.pdfgen import canvas
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   102
from reportlab.pdfgen import pathobject
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   103
from reportlab.pdfgen import textobject
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   104
1740
71f51fea9301 Latest, well commented source
andy_robinson
parents: 1739
diff changeset
   105
PyHeader = '''#! /usr/bin/env python
1738
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   106
1742
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   107
#
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   108
# This code was entirely generated by ReportLab (http://www.reportlab.com)
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   109
#
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   110
1738
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   111
import sys
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   112
from reportlab.pdfgen import pathobject
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   113
from reportlab.pdfgen import textobject
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   114
from reportlab.lib.colors import Color
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   115
1742
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   116
def doIt(file, regenerate=0) :
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   117
    """Generates a PDF document, save it into file.
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
   118
1740
71f51fea9301 Latest, well commented source
andy_robinson
parents: 1739
diff changeset
   119
       file : either a filename or a file-like object.
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
   120
1742
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   121
       regenerate : if set then this function returns the Python source
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   122
                    code which when run will produce the same result.
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   123
                    if unset then this function returns None, and is
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   124
                    much faster.
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   125
    """
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   126
    if regenerate :
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   127
        from reportlab.pdfgen.pycanvas import Canvas
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   128
    else :
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   129
        from reportlab.pdfgen.canvas import Canvas
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   130
'''
1738
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   131
1740
71f51fea9301 Latest, well commented source
andy_robinson
parents: 1739
diff changeset
   132
PyFooter = '''
1742
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   133
    # if we want the equivalent Python source code, then send it back
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   134
    if regenerate :
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   135
        return str(c)
1738
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   136
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   137
if __name__ == "__main__" :
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   138
    if len(sys.argv) != 2 :
1740
71f51fea9301 Latest, well commented source
andy_robinson
parents: 1739
diff changeset
   139
        # second argument must be the name of the PDF file to create
1738
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   140
        sys.stderr.write("%s needs one and only one argument\\n" % sys.argv[0])
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   141
        sys.exit(-1)
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   142
    else :
1740
71f51fea9301 Latest, well commented source
andy_robinson
parents: 1739
diff changeset
   143
        # we've got a filename, we can proceed.
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
   144
        print doIt(sys.argv[1], regenerate=1)
1742
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   145
        sys.exit(0)'''
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
   146
1738
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   147
def buildargs(*args, **kwargs) :
1742
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   148
    """Constructs a printable list of arguments suitable for use in source function calls."""
1738
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   149
    arguments = ""
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   150
    for arg in args :
1746
bc04484b8111 Fixed 1.5 compat (+=)
rgbecker
parents: 1742
diff changeset
   151
        arguments = arguments + ("%s, " % repr(arg))
1738
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   152
    for (kw, val) in kwargs.items() :
1746
bc04484b8111 Fixed 1.5 compat (+=)
rgbecker
parents: 1742
diff changeset
   153
        arguments = arguments+ ("%s=%s, " % (kw, repr(val)))
1738
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   154
    if arguments[-2:] == ", " :
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   155
        arguments = arguments[:-2]
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
   156
    return arguments
1738
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   157
1739
9ee6c04932fa Jerome's latest version, refactored he says
andy_robinson
parents: 1738
diff changeset
   158
class PDFAction :
1742
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   159
    """Base class to fake method calls or attributes on PDF objects (Canvas, PDFPathObject, PDFTextObject)."""
1739
9ee6c04932fa Jerome's latest version, refactored he says
andy_robinson
parents: 1738
diff changeset
   160
    def __init__(self, parent, action) :
1742
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   161
        """Saves a pointer to the parent object, and the method name."""
1739
9ee6c04932fa Jerome's latest version, refactored he says
andy_robinson
parents: 1738
diff changeset
   162
        self._parent = parent
9ee6c04932fa Jerome's latest version, refactored he says
andy_robinson
parents: 1738
diff changeset
   163
        self._action = action
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
   164
1739
9ee6c04932fa Jerome's latest version, refactored he says
andy_robinson
parents: 1738
diff changeset
   165
    def __getattr__(self, name) :
1742
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   166
        """Probably a method call on an attribute, returns the real one."""
1739
9ee6c04932fa Jerome's latest version, refactored he says
andy_robinson
parents: 1738
diff changeset
   167
        return getattr(getattr(self._parent._object, self._action), name)
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
   168
1739
9ee6c04932fa Jerome's latest version, refactored he says
andy_robinson
parents: 1738
diff changeset
   169
    def __call__(self, *args, **kwargs) :
1742
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   170
        """The fake method is called, print it then call the real one."""
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   171
        if not self._parent._parent._in :
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   172
            self._precomment()
1739
9ee6c04932fa Jerome's latest version, refactored he says
andy_robinson
parents: 1738
diff changeset
   173
            self._parent._parent._PyWrite("    %s.%s(%s)" % (self._parent._name, self._action, apply(buildargs, args, kwargs)))
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
   174
            self._postcomment()
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
   175
        self._parent._parent._in = self._parent._parent._in + 1
1739
9ee6c04932fa Jerome's latest version, refactored he says
andy_robinson
parents: 1738
diff changeset
   176
        retcode = apply(getattr(self._parent._object, self._action), args, kwargs)
1756
ad131d58acab Applied Jerome Alet's patch (submitted on Mon 07/10/2002).
johnprecedo
parents: 1746
diff changeset
   177
        self._parent._parent._in = self._parent._parent._in - 1
1739
9ee6c04932fa Jerome's latest version, refactored he says
andy_robinson
parents: 1738
diff changeset
   178
        return retcode
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
   179
1777
48870c5f865a Jerome's New improved hasher
rgbecker
parents: 1771
diff changeset
   180
    def __hash__(self) :
48870c5f865a Jerome's New improved hasher
rgbecker
parents: 1771
diff changeset
   181
        return hash(getattr(self._parent._object, self._action))
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
   182
1756
ad131d58acab Applied Jerome Alet's patch (submitted on Mon 07/10/2002).
johnprecedo
parents: 1746
diff changeset
   183
    def __coerce__(self, other) :
1777
48870c5f865a Jerome's New improved hasher
rgbecker
parents: 1771
diff changeset
   184
        """Needed."""
1756
ad131d58acab Applied Jerome Alet's patch (submitted on Mon 07/10/2002).
johnprecedo
parents: 1746
diff changeset
   185
        return coerce(getattr(self._parent._object, self._action), other)
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
   186
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
   187
    def _precomment(self) :
1742
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   188
        """To be overriden."""
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   189
        pass
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
   190
1742
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   191
    def _postcomment(self) :
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   192
        """To be overriden."""
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   193
        pass
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
   194
1739
9ee6c04932fa Jerome's latest version, refactored he says
andy_robinson
parents: 1738
diff changeset
   195
class PDFObject :
1742
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   196
    """Base class for PDF objects like PDFPathObject and PDFTextObject."""
1740
71f51fea9301 Latest, well commented source
andy_robinson
parents: 1739
diff changeset
   197
    _number = 0
1739
9ee6c04932fa Jerome's latest version, refactored he says
andy_robinson
parents: 1738
diff changeset
   198
    def __init__(self, parent) :
1742
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   199
        """Saves a pointer to the parent Canvas."""
1739
9ee6c04932fa Jerome's latest version, refactored he says
andy_robinson
parents: 1738
diff changeset
   200
        self._parent = parent
9ee6c04932fa Jerome's latest version, refactored he says
andy_robinson
parents: 1738
diff changeset
   201
        self._initdone = 0
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
   202
1739
9ee6c04932fa Jerome's latest version, refactored he says
andy_robinson
parents: 1738
diff changeset
   203
    def __getattr__(self, name) :
1742
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   204
        """The user's programs wants to call one of our methods or get an attribute, fake it."""
1739
9ee6c04932fa Jerome's latest version, refactored he says
andy_robinson
parents: 1738
diff changeset
   205
        return PDFAction(self, name)
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
   206
1739
9ee6c04932fa Jerome's latest version, refactored he says
andy_robinson
parents: 1738
diff changeset
   207
    def __repr__(self) :
1742
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   208
        """Returns the name used in the generated source code (e.g. 'p' or 't')."""
1739
9ee6c04932fa Jerome's latest version, refactored he says
andy_robinson
parents: 1738
diff changeset
   209
        return self._name
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
   210
1739
9ee6c04932fa Jerome's latest version, refactored he says
andy_robinson
parents: 1738
diff changeset
   211
    def __call__(self, *args, **kwargs) :
1742
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   212
        """Real object initialisation is made here, because now we've got the arguments."""
1739
9ee6c04932fa Jerome's latest version, refactored he says
andy_robinson
parents: 1738
diff changeset
   213
        if not self._initdone :
1746
bc04484b8111 Fixed 1.5 compat (+=)
rgbecker
parents: 1742
diff changeset
   214
            self.__class__._number = self.__class__._number + 1
1739
9ee6c04932fa Jerome's latest version, refactored he says
andy_robinson
parents: 1738
diff changeset
   215
            methodname = apply(self._postinit, args, kwargs)
1740
71f51fea9301 Latest, well commented source
andy_robinson
parents: 1739
diff changeset
   216
            self._parent._PyWrite("\n    # create PDF%sObject number %i\n    %s = %s.%s(%s)" % (methodname[5:], self.__class__._number, self._name, self._parent._name, methodname, apply(buildargs, args, kwargs)))
1739
9ee6c04932fa Jerome's latest version, refactored he says
andy_robinson
parents: 1738
diff changeset
   217
            self._initdone = 1
9ee6c04932fa Jerome's latest version, refactored he says
andy_robinson
parents: 1738
diff changeset
   218
        return self
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
   219
1739
9ee6c04932fa Jerome's latest version, refactored he says
andy_robinson
parents: 1738
diff changeset
   220
class Canvas :
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
   221
    """Our fake Canvas class, which will intercept each and every method or attribute access."""
1739
9ee6c04932fa Jerome's latest version, refactored he says
andy_robinson
parents: 1738
diff changeset
   222
    class TextObject(PDFObject) :
9ee6c04932fa Jerome's latest version, refactored he says
andy_robinson
parents: 1738
diff changeset
   223
        _name = "t"
9ee6c04932fa Jerome's latest version, refactored he says
andy_robinson
parents: 1738
diff changeset
   224
        def _postinit(self, *args, **kwargs) :
9ee6c04932fa Jerome's latest version, refactored he says
andy_robinson
parents: 1738
diff changeset
   225
            self._object = apply(textobject.PDFTextObject, (self._parent, ) + args, kwargs)
9ee6c04932fa Jerome's latest version, refactored he says
andy_robinson
parents: 1738
diff changeset
   226
            return "beginText"
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
   227
1739
9ee6c04932fa Jerome's latest version, refactored he says
andy_robinson
parents: 1738
diff changeset
   228
    class PathObject(PDFObject) :
9ee6c04932fa Jerome's latest version, refactored he says
andy_robinson
parents: 1738
diff changeset
   229
        _name = "p"
9ee6c04932fa Jerome's latest version, refactored he says
andy_robinson
parents: 1738
diff changeset
   230
        def _postinit(self, *args, **kwargs) :
9ee6c04932fa Jerome's latest version, refactored he says
andy_robinson
parents: 1738
diff changeset
   231
            self._object = apply(pathobject.PDFPathObject, args, kwargs)
9ee6c04932fa Jerome's latest version, refactored he says
andy_robinson
parents: 1738
diff changeset
   232
            return "beginPath"
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
   233
1739
9ee6c04932fa Jerome's latest version, refactored he says
andy_robinson
parents: 1738
diff changeset
   234
    class Action(PDFAction) :
1742
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   235
        """Class called for every Canvas method call."""
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   236
        def _precomment(self) :
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   237
            """Outputs comments before the method call."""
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   238
            if self._action == "showPage" :
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   239
                self._parent._PyWrite("\n    # Ends page %i" % self._parent._pagenumber)
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
   240
            elif self._action == "saveState" :
1742
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   241
                state = {}
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   242
                d = self._parent._object.__dict__
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   243
                for name in self._parent._object.STATE_ATTRIBUTES:
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
   244
                    state[name] = d[name]
1742
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   245
                self._parent._PyWrite("\n    # Saves context level %i %s" % (self._parent._contextlevel, state))
1746
bc04484b8111 Fixed 1.5 compat (+=)
rgbecker
parents: 1742
diff changeset
   246
                self._parent._contextlevel = self._parent._contextlevel + 1
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
   247
            elif self._action == "restoreState" :
1756
ad131d58acab Applied Jerome Alet's patch (submitted on Mon 07/10/2002).
johnprecedo
parents: 1746
diff changeset
   248
                self._parent._contextlevel = self._parent._contextlevel - 1
1742
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   249
                self._parent._PyWrite("\n    # Restores context level %i %s" % (self._parent._contextlevel, self._parent._object.state_stack[-1]))
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
   250
            elif self._action == "beginForm" :
1746
bc04484b8111 Fixed 1.5 compat (+=)
rgbecker
parents: 1742
diff changeset
   251
                self._parent._formnumber = self._parent._formnumber + 1
1742
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   252
                self._parent._PyWrite("\n    # Begins form %i" % self._parent._formnumber)
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
   253
            elif self._action == "endForm" :
1742
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   254
                self._parent._PyWrite("\n    # Ends form %i" % self._parent._formnumber)
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
   255
            elif self._action == "save" :
1742
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   256
                self._parent._PyWrite("\n    # Saves the PDF document to disk")
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
   257
1742
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   258
        def _postcomment(self) :
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   259
            """Outputs comments after the method call."""
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   260
            if self._action == "showPage" :
1746
bc04484b8111 Fixed 1.5 compat (+=)
rgbecker
parents: 1742
diff changeset
   261
                self._parent._pagenumber = self._parent._pagenumber + 1
1742
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   262
                self._parent._PyWrite("\n    # Begins page %i" % self._parent._pagenumber)
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
   263
            elif self._action in [ "endForm", "drawPath", "clipPath" ] :
1742
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   264
                self._parent._PyWrite("")
1738
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   265
1739
9ee6c04932fa Jerome's latest version, refactored he says
andy_robinson
parents: 1738
diff changeset
   266
    _name = "c"
1738
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   267
    def __init__(self, *args, **kwargs) :
1742
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   268
        """Initialize and begins source code."""
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   269
        self._parent = self     # nice trick, isn't it ?
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   270
        self._in = 0
1740
71f51fea9301 Latest, well commented source
andy_robinson
parents: 1739
diff changeset
   271
        self._contextlevel = 0
71f51fea9301 Latest, well commented source
andy_robinson
parents: 1739
diff changeset
   272
        self._pagenumber = 1
71f51fea9301 Latest, well commented source
andy_robinson
parents: 1739
diff changeset
   273
        self._formnumber = 0
1738
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   274
        self._footerpresent = 0
1739
9ee6c04932fa Jerome's latest version, refactored he says
andy_robinson
parents: 1738
diff changeset
   275
        self._object = apply(canvas.Canvas, args, kwargs)
1738
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   276
        self._pyfile = cStringIO.StringIO()
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   277
        self._PyWrite(PyHeader)
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   278
        try :
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   279
            del kwargs["filename"]
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
   280
        except KeyError :
1738
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   281
            pass
1742
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   282
        self._PyWrite("    # create the PDF document\n    %s = Canvas(file, %s)\n\n    # Begins page 1" % (self._name, apply(buildargs, args[1:], kwargs)))
1738
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   283
1742
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   284
    def __nonzero__(self) :
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   285
        """This is needed by platypus' tables."""
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   286
        return 1
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
   287
1738
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   288
    def __str__(self) :
1742
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   289
        """Returns the equivalent Python source code."""
1738
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   290
        if not self._footerpresent :
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   291
            self._PyWrite(PyFooter)
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   292
            self._footerpresent = 1
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   293
        return self._pyfile.getvalue()
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   294
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   295
    def __getattr__(self, name) :
1742
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   296
        """Method or attribute access."""
1738
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   297
        if name == "beginPath" :
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   298
            return self.PathObject(self)
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   299
        elif name == "beginText" :
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   300
            return self.TextObject(self)
1771
105572a4222f Whitespace and tab character cleanup
andy_robinson
parents: 1756
diff changeset
   301
        else :
1738
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   302
            return self.Action(self, name)
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   303
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   304
    def _PyWrite(self, pycode) :
1742
1dac293eabff Jerome's Patch added by Robin
rgbecker
parents: 1740
diff changeset
   305
        """Outputs the source code with a trailing newline."""
1738
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   306
        self._pyfile.write("%s\n" % pycode)
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   307
64f2ccdb91b9 Jerome Alet's Macro-recording canvas
andy_robinson
parents:
diff changeset
   308
if __name__ == '__main__':
2967
ea62529bd1df reportlab-2.2: first stage changes in on the trunk
rgbecker
parents: 2966
diff changeset
   309
    print 'For test scripts, look in tests'