summaryrefslogtreecommitdiff
path: root/report/viewer/render.py
blob: 0934c39c4cd98ca8e19c4fd71d83216ddc6514bf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
from reportlab.pdfgen import canvas
from reportlab.lib.colors import black, gray, white, magenta, Color
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib.units import cm, inch
from reportlab.platypus import SimpleDocTemplate, Spacer, Paragraph
from reportlab.platypus.flowables import Flowable
import re

class Alignment(Flowable):
    def __init__(self, x_words, y_words, alignment, x_font, y_font, ptsize, unit, scale=True, colours=None):
        self._x_words = x_words
        self._y_words = y_words
        self._alignment = alignment
        self._unit = unit*cm
        self._x_font = x_font
        self._y_font = y_font
        self._ptsize = ptsize
        self._scale = 1
        self._do_scale = scale
        self._colours = colours
        if not colours:
            self._colours = {'S':black, 'P':gray, 'N':magenta}

    def wrap(self, rw, rh):
        xws = [self.canv.stringWidth(w, self._x_font, self._ptsize)
               for w in self._x_words]
        yws = [self.canv.stringWidth(w, self._y_font, self._ptsize)
               for w in self._y_words]
        width = (len(self._x_words) + 0.22)* self._unit + max(yws)
        height = (len(self._y_words) + 0.22)* self._unit + max(xws)
        
        if self._do_scale:
            self._scale = min(rw / width, 1.5)
            width *= self._scale
            height *= self._scale

        return (width, height)

    def draw(self):
        c = self.canv
        print c.getAvailableFonts()

        X=len(self._x_words)
        Y=len(self._y_words)

        c.saveState()
        c.scale(self._scale, self._scale)

        for (x, y), conf in self._alignment.items():
            col = self._colours[conf]
            if isinstance(col, Color):
                c.setFillColor(col)
                c.rect((0.02 + x)*self._unit, (0.02+Y-y-1)*self._unit,
                       self._unit, self._unit, 0, 1)
            else:
                bl = (x*self._unit, (Y-y-1)*self._unit)
                tl = (x*self._unit, (Y-y)*self._unit)
                tr = ((x+1)*self._unit, (Y-y)*self._unit)
                br = ((x+1)*self._unit, (Y-y-1)*self._unit)

                p = c.beginPath()
                p.moveTo(*br)
                p.lineTo(*tr)
                p.lineTo(*tl)
                c.setFillColor(col[0])
                c.drawPath(p, fill=1)
                p = c.beginPath()
                p.moveTo(*br)
                p.lineTo(*bl)
                p.lineTo(*tl)
                c.setFillColor(col[1])
                c.drawPath(p, fill=1)

        c.setStrokeColor(black)
        c.grid(map(lambda x: (0.02+x)*self._unit, range(X+1)),
               map(lambda y: (0.02+y)*self._unit, range(Y+1)))

        c.setFont(self._x_font, self._ptsize)
        c.setFillColor(black)
        for x, word in enumerate(self._x_words):
            c.saveState()
            c.translate((x+0.52)*self._unit, (Y+0.22)*self._unit)
            c.rotate(60)
            c.drawString(0, 0, word)
            c.restoreState()

        c.setFont(self._y_font, self._ptsize)
        for y, word in enumerate(self._y_words):
            c.drawString((X+0.22)*self._unit, (Y-y+0.42-1)*self._unit, word)

        c.restoreState()

class Document:
    def __init__(self, filename):
        self._styles = getSampleStyleSheet()
        self._doc = SimpleDocTemplate(filename)
        self._story = []

    def append(self, flowable):
        self._story.append(flowable)
        self._story.append(Spacer(1, 1*cm))

    def render(self):
        self._doc.build(self._story[:-1])

class Canvas:
    def __init__(self, filename):
        self._filename = filename
        self._canvas = canvas.Canvas('.' + filename, A4)
        self._size = A4
        self._body = None

    def append(self, flowable):
        if self._body:
            print >>sys.stderr, 'WARNING: replacing existing flowable' 
        self._body = flowable

    def render(self):
        self._body.canv = self._canvas
        width, height = self._body.wrap(*self._size)
        width *= 1.02
        height *= 1.02

        self._canvas = canvas.Canvas(self._filename, (width, height))
        self._body.canv = self._canvas
        self._body.draw()
        self._canvas.save()