~ubuntu-branches/ubuntu/utopic/python-chaco/utopic

« back to all changes in this revision

Viewing changes to chaco/pdf_graphics_context.py

  • Committer: Package Import Robot
  • Author(s): Andrew Starr-Bochicchio
  • Date: 2014-06-01 17:04:08 UTC
  • mfrom: (7.2.5 sid)
  • Revision ID: package-import@ubuntu.com-20140601170408-m86xvdjd83a4qon0
Tags: 4.4.1-1ubuntu1
* Merge from Debian unstable. Remaining Ubuntu changes:
 - Let the binary-predeb target work on the usr/lib/python* directory
   as we don't have usr/share/pyshared anymore.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
 
2
 
 
3
2
# Major library imports
4
3
import warnings
5
4
 
6
5
try:
7
6
# PDF imports from reportlab
8
7
    from reportlab.pdfgen.canvas import Canvas
9
 
    from reportlab.lib.pagesizes import letter, A4
 
8
    from reportlab.lib.pagesizes import letter, A4, landscape
10
9
    from reportlab.lib.units import inch, cm, mm, pica
11
10
 
12
11
except ImportError:
15
14
 
16
15
from kiva.pdf import GraphicsContext
17
16
 
 
17
 
 
18
PAGE_DPI = 72.0
 
19
 
18
20
PAGE_SIZE_MAP = {
19
 
        "letter": letter,
20
 
        "A4": A4,
21
 
        }
 
21
    "letter": letter,
 
22
    "A4": A4,
 
23
    "landscape_letter": landscape(letter),
 
24
    "landscape_A4": landscape(A4)
 
25
}
22
26
 
23
27
UNITS_MAP = {
24
 
        "inch": inch,
25
 
        "cm": cm,
26
 
        "mm": mm,
27
 
        "pica": pica,
28
 
        }
 
28
    "inch": inch,
 
29
    "cm": cm,
 
30
    "mm": mm,
 
31
    "pica": pica,
 
32
}
29
33
 
30
34
if Canvas is not None:
31
35
    class PdfPlotGraphicsContext(GraphicsContext):
40
44
        pagesize = "letter"  # Enum("letter", "A4")
41
45
 
42
46
        # A tuple (x, y, width, height) specifying the box into which the plot
43
 
        # should be rendered.  **x** and **y** correspond to the lower-left hand
44
 
        # coordinates of the box in the coordinates of the page (i.e. 0,0 is at the
45
 
        # lower left).  **width** and **height** can be positive or negative;
 
47
        # should be rendered.  **x** and **y** correspond to the lower-left
 
48
        # hand coordinates of the box in the coordinates of the page
 
49
        # (i.e. 0,0 is at the lower left).  **width** and **height** can be
 
50
        # positive or negative;
46
51
        # if they are positive, they are interpreted as distances from (x,y);
47
 
        # if they are negative, they are interpreted as distances from the right
48
 
        # and top of the page, respectively.
 
52
        # if they are negative, they are interpreted as distances from the
 
53
        # right and top of the page, respectively.
49
54
        dest_box = (0.5, 0.5, -0.5, -0.5)
50
55
 
51
56
        # The units of the values in dest_box
52
57
        dest_box_units = "inch"   # Enum("inch", "cm", "mm", "pica")
53
58
 
54
 
 
55
59
        def __init__(self, pdf_canvas=None, filename=None, pagesize=None,
56
60
                     dest_box=None, dest_box_units=None):
57
61
            if filename:
63
67
            if dest_box_units:
64
68
                self.dest_box_units = dest_box_units
65
69
 
66
 
            if pdf_canvas == None:
 
70
            if pdf_canvas is None:
67
71
                pdf_canvas = self._create_new_canvas()
68
72
 
69
73
            GraphicsContext.__init__(self, pdf_canvas)
70
74
 
 
75
        def add_page(self):
 
76
            """ Adds a new page to the PDF canvas and makes that the current
 
77
            drawing target.
 
78
            """
 
79
            if self.gc is None:
 
80
                warnings.warn("PDF Canvas has not been created yet.")
 
81
                return
 
82
 
 
83
            # Add the new page
 
84
            self.gc.showPage()
 
85
 
 
86
            # We'll need to call _initialize_page() before drawing
 
87
            self._page_initialized = False
71
88
 
72
89
        def render_component(self, component, container_coords=False,
73
90
                             halign="center", valign="top"):
74
 
            """ Erases the current contents of the graphics context and renders the
75
 
            given component at the maximum possible scaling while preserving aspect
76
 
            ratio.
 
91
            """ Erases the current contents of the graphics context and renders
 
92
            the given component at the maximum possible scaling while
 
93
            preserving aspect ratio.
77
94
 
78
95
            Parameters
79
96
            ----------
82
99
            container_coords : Boolean
83
100
                Whether to use coordinates of the component's container
84
101
            halign : "center", "left", "right"
85
 
                Determines the position of the component if it is narrower than the
86
 
                graphics context area (after scaling)
 
102
                Determines the position of the component if it is narrower than
 
103
                the graphics context area (after scaling)
87
104
            valign : "center", "top", "bottom"
88
 
                Determiens the position of the component if it is shorter than the
89
 
                graphics context area (after scaling)
 
105
                Determiens the position of the component if it is shorter than
 
106
                the graphics context area (after scaling)
90
107
 
91
108
            Description
92
109
            -----------
93
110
            If *container_coords* is False, then the (0,0) coordinate of this
94
111
            graphics context corresponds to the lower-left corner of the
95
 
            component's **outer_bounds**. If *container_coords* is True, then the
96
 
            method draws the component as it appears inside its container, i.e., it
97
 
            treats (0,0) of the graphics context as the lower-left corner of the
98
 
            container's outer bounds.
 
112
            component's **outer_bounds**. If *container_coords* is True, then
 
113
            the method draws the component as it appears inside its container,
 
114
            i.e., it treats (0, 0) of the graphics context as the lower-left
 
115
            corner of the container's outer bounds.
99
116
            """
100
117
 
 
118
            if not self._page_initialized:
 
119
                # Make sure the origin is set up as before.
 
120
                self._initialize_page(self.gc)
 
121
 
101
122
            x, y = component.outer_position
102
123
            if container_coords:
103
124
                width, height = component.container.bounds
106
127
                y = -y
107
128
                width, height = component.outer_bounds
108
129
 
109
 
            # Compute the correct scaling to fit the component into the available
110
 
            # canvas space while preserving aspect ratio.
 
130
            # Compute the correct scaling to fit the component into the
 
131
            # available canvas space while preserving aspect ratio.
111
132
            units = UNITS_MAP[self.dest_box_units]
112
133
            pagesize = PAGE_SIZE_MAP[self.pagesize]
113
134
 
155
176
 
156
177
            self.translate_ctm(trans_x, trans_y)
157
178
            self.scale_ctm(scale, scale)
158
 
            self.clip_to_rect(0, 0, width, height)
 
179
            self.clip_to_rect(-x, -y, width, height)
159
180
            old_bb_setting = component.use_backbuffer
160
181
            component.use_backbuffer = False
161
182
            component.draw(self, view_bounds=(0, 0, width, height))
166
187
            self.gc.save()
167
188
 
168
189
        def _create_new_canvas(self):
 
190
            """ Create the PDF canvas context.
 
191
            """
 
192
            x, y, w, h, = self._get_bounding_box()
 
193
            if w < 0 or h < 0:
 
194
                self.gc = None
 
195
                return
 
196
 
169
197
            pagesize = PAGE_SIZE_MAP[self.pagesize]
170
 
            units = UNITS_MAP[self.dest_box_units]
171
198
            gc = Canvas(filename=self.filename, pagesize=pagesize)
172
 
 
173
 
            width = pagesize[0] * units * inch / 72.0
174
 
            height = pagesize[1] * units * inch / 72.0
 
199
            self._initialize_page(gc)
 
200
 
 
201
            return gc
 
202
 
 
203
        def _get_bounding_box(self):
 
204
            """ Compute the bounding rect of a page.
 
205
            """
 
206
            pagesize = PAGE_SIZE_MAP[self.pagesize]
 
207
            units = UNITS_MAP[self.dest_box_units]
 
208
 
175
209
            x = self.dest_box[0] * units
176
210
            y = self.dest_box[1] * units
177
211
            w = self.dest_box[2] * units
178
212
            h = self.dest_box[3] * units
179
213
 
180
214
            if w < 0:
181
 
                w += width
 
215
                w += pagesize[0] * units * inch / PAGE_DPI
182
216
            if h < 0:
183
 
                h += height
 
217
                h += pagesize[1] * units * inch / PAGE_DPI
184
218
 
185
219
            if w < 0 or h < 0:
186
220
                warnings.warn("Margins exceed page dimensions.")
187
 
                self.gc = None
188
 
                return
189
 
 
190
 
            gc.translate(x,y)
 
221
 
 
222
            return x, y, w, h
 
223
 
 
224
        def _initialize_page(self, gc):
 
225
            """ Make sure the origin is set to something consistent.
 
226
            """
 
227
            x, y, w, h, = self._get_bounding_box()
 
228
 
 
229
            gc.translate(x, y)
 
230
 
191
231
            path = gc.beginPath()
192
232
            path.rect(0, 0, w, h)
193
233
            gc.clipPath(path, stroke=0, fill=0)
194
 
            return gc
195
234
 
 
235
            self._page_initialized = True