~openerp-groupes/openobject-server/6.0-fix-setup-windows

« back to all changes in this revision

Viewing changes to bin/reportlab/lib/codecharts.py

  • Committer: pinky
  • Date: 2006-12-07 13:41:40 UTC
  • Revision ID: pinky-3f10ee12cea3c4c75cef44ab04ad33ef47432907
New trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#Copyright ReportLab Europe Ltd. 2000-2004
 
2
#see license.txt for license details
 
3
#history http://www.reportlab.co.uk/cgi-bin/viewcvs.cgi/public/reportlab/trunk/reportlab/lib/codecharts.py
 
4
#$Header $
 
5
__version__=''' $Id '''
 
6
__doc__="""Routines to print code page (character set) drawings.
 
7
 
 
8
To be sure we can accurately represent characters in various encodings
 
9
and fonts, we need some routines to display all those characters.
 
10
These are defined herein.  The idea is to include flowable, drawable
 
11
and graphic objects for single and multi-byte fonts. """
 
12
import string
 
13
 
 
14
from reportlab.pdfgen.canvas import Canvas
 
15
from reportlab.platypus import Flowable
 
16
from reportlab.pdfbase import pdfmetrics, cidfonts
 
17
from reportlab.graphics.shapes import Drawing, Group, String, Circle, Rect
 
18
from reportlab.graphics.widgetbase import Widget
 
19
from reportlab.lib import colors
 
20
 
 
21
 
 
22
class CodeChartBase(Flowable):
 
23
    """Basic bits of drawing furniture used by
 
24
    single and multi-byte versions: ability to put letters
 
25
    into boxes."""
 
26
 
 
27
    def calcLayout(self):
 
28
        "Work out x and y positions for drawing"
 
29
 
 
30
 
 
31
        rows = self.codePoints * 1.0 / self.charsPerRow
 
32
        if rows == int(rows):
 
33
            self.rows = int(rows)
 
34
        else:
 
35
            self.rows = int(rows) + 1
 
36
        # size allows for a gray column of labels
 
37
        self.width = self.boxSize * (1+self.charsPerRow)
 
38
        self.height = self.boxSize * (1+self.rows)
 
39
 
 
40
        #handy lists
 
41
        self.ylist = []
 
42
        for row in range(self.rows + 2):
 
43
            self.ylist.append(row * self.boxSize)
 
44
        self.xlist = []
 
45
        for col in range(self.charsPerRow + 2):
 
46
            self.xlist.append(col * self.boxSize)
 
47
 
 
48
    def formatByte(self, byt):
 
49
        if self.hex:
 
50
            return '%02X' % byt
 
51
        else:
 
52
            return '%d' % byt
 
53
 
 
54
    def drawChars(self, charList):
 
55
        """Fills boxes in order.  None means skip a box.
 
56
        Empty boxes at end get filled with gray"""
 
57
        extraNeeded = (self.rows * self.charsPerRow - len(charList))
 
58
        for i in range(extraNeeded):
 
59
            charList.append(None)
 
60
        #charList.extend([None] * extraNeeded)
 
61
        row = 0
 
62
        col = 0
 
63
        self.canv.setFont(self.fontName, self.boxSize * 0.75)
 
64
        for ch in charList:  # may be 2 bytes or 1
 
65
            if ch is None:
 
66
                self.canv.setFillGray(0.9)
 
67
                self.canv.rect((1+col) * self.boxSize, (self.rows - row - 1) * self.boxSize,
 
68
                    self.boxSize, self.boxSize, stroke=0, fill=1)
 
69
                self.canv.setFillGray(0.0)
 
70
            else:
 
71
                try:
 
72
                    self.canv.drawCentredString(
 
73
                            (col+1.5) * self.boxSize,
 
74
                            (self.rows - row - 0.875) * self.boxSize,
 
75
                            ch,
 
76
                            )
 
77
                except:
 
78
                    self.canv.setFillGray(0.9)
 
79
                    self.canv.rect((1+col) * self.boxSize, (self.rows - row - 1) * self.boxSize,
 
80
                        self.boxSize, self.boxSize, stroke=0, fill=1)
 
81
                    self.canv.drawCentredString(
 
82
                            (col+1.5) * self.boxSize,
 
83
                            (self.rows - row - 0.875) * self.boxSize,
 
84
                            '?',
 
85
                            )
 
86
                    self.canv.setFillGray(0.0)
 
87
            col = col + 1
 
88
            if col == self.charsPerRow:
 
89
                row = row + 1
 
90
                col = 0
 
91
 
 
92
    def drawLabels(self, topLeft = ''):
 
93
        """Writes little labels in the top row and first column"""
 
94
        self.canv.setFillGray(0.8)
 
95
        self.canv.rect(0, self.ylist[-2], self.width, self.boxSize, fill=1, stroke=0)
 
96
        self.canv.rect(0, 0, self.boxSize, self.ylist[-2], fill=1, stroke=0)
 
97
        self.canv.setFillGray(0.0)
 
98
 
 
99
        #label each row and column
 
100
        self.canv.setFont('Helvetica-Oblique',0.375 * self.boxSize)
 
101
        byt = 0
 
102
        for row in range(self.rows):
 
103
            if self.rowLabels:
 
104
                label = self.rowLabels[row]
 
105
            else: # format start bytes as hex or decimal
 
106
                label = self.formatByte(row * self.charsPerRow)
 
107
            self.canv.drawCentredString(0.5 * self.boxSize,
 
108
                                        (self.rows - row - 0.75) * self.boxSize,
 
109
                                        label
 
110
                                        )
 
111
        for col in range(self.charsPerRow):
 
112
            self.canv.drawCentredString((col + 1.5) * self.boxSize,
 
113
                                        (self.rows + 0.25) * self.boxSize,
 
114
                                        self.formatByte(col)
 
115
                                        )
 
116
 
 
117
        if topLeft:
 
118
            self.canv.setFont('Helvetica-BoldOblique',0.5 * self.boxSize)
 
119
            self.canv.drawCentredString(0.5 * self.boxSize,
 
120
                                        (self.rows + 0.25) * self.boxSize,
 
121
                                        topLeft
 
122
                                        )
 
123
 
 
124
class SingleByteEncodingChart(CodeChartBase):
 
125
    def __init__(self, faceName='Helvetica', encodingName='WinAnsiEncoding',
 
126
                 charsPerRow=16, boxSize=14, hex=1):
 
127
        self.codePoints = 256
 
128
        self.faceName = faceName
 
129
        self.encodingName = encodingName
 
130
        self.fontName = self.faceName + '-' + self.encodingName
 
131
        self.charsPerRow = charsPerRow
 
132
        self.boxSize = boxSize
 
133
        self.hex = hex
 
134
        self.rowLabels = None
 
135
        pdfmetrics.registerFont(pdfmetrics.Font(self.fontName,
 
136
                                                self.faceName,
 
137
                                                self.encodingName)
 
138
                                )
 
139
 
 
140
        self.calcLayout()
 
141
 
 
142
 
 
143
    def draw(self):
 
144
        self.drawLabels()
 
145
        charList = [None] * 32 + map(chr, range(32, 256))
 
146
        self.drawChars(charList)
 
147
        self.canv.grid(self.xlist, self.ylist)
 
148
 
 
149
 
 
150
class KutenRowCodeChart(CodeChartBase):
 
151
    """Formats one 'row' of the 94x94 space used in many Asian encodings.aliases
 
152
 
 
153
    These deliberately resemble the code charts in Ken Lunde's "Understanding
 
154
    CJKV Information Processing", to enable manual checking.  Due to the large
 
155
    numbers of characters, we don't try to make one graphic with 10,000 characters,
 
156
    but rather output a sequence of these."""
 
157
    #would be cleaner if both shared one base class whose job
 
158
    #was to draw the boxes, but never mind...
 
159
    def __init__(self, row, faceName, encodingName):
 
160
        self.row = row
 
161
        self.codePoints = 94
 
162
        self.boxSize = 18
 
163
        self.charsPerRow = 20
 
164
        self.rows = 5
 
165
        self.rowLabels = ['00','20','40','60','80']
 
166
        self.hex = 0
 
167
        self.faceName = faceName
 
168
        self.encodingName = encodingName
 
169
 
 
170
        try:
 
171
            # the dependent files might not be available
 
172
            font = cidfonts.CIDFont(self.faceName, self.encodingName)
 
173
            pdfmetrics.registerFont(font)
 
174
        except:
 
175
            # fall back to English and at least shwo we can draw the boxes
 
176
            self.faceName = 'Helvetica'
 
177
            self.encodingName = 'WinAnsiEncoding'
 
178
        self.fontName = self.faceName + '-' + self.encodingName
 
179
        self.calcLayout()
 
180
 
 
181
    def makeRow(self, row):
 
182
        """Works out the character values for this kuten row"""
 
183
        cells = []
 
184
        if string.find(self.encodingName, 'EUC') > -1:
 
185
            # it is an EUC family encoding.
 
186
            for col in range(1, 95):
 
187
                ch = chr(row + 160) + chr(col+160)
 
188
                cells.append(ch)
 
189
##        elif string.find(self.encodingName, 'GB') > -1:
 
190
##            # it is an EUC family encoding.
 
191
##            for col in range(1, 95):
 
192
##                ch = chr(row + 160) + chr(col+160)
 
193
        else:
 
194
            cells.append([None] * 94)
 
195
        return cells
 
196
 
 
197
    def draw(self):
 
198
        self.drawLabels(topLeft= 'R%d' % self.row)
 
199
 
 
200
        # work out which characters we need for the row
 
201
        #assert string.find(self.encodingName, 'EUC') > -1, 'Only handles EUC encoding today, you gave me %s!' % self.encodingName
 
202
 
 
203
        # pad out by 1 to match Ken Lunde's tables
 
204
        charList = [None] + self.makeRow(self.row)
 
205
        self.drawChars(charList)
 
206
        self.canv.grid(self.xlist, self.ylist)
 
207
 
 
208
 
 
209
class Big5CodeChart(CodeChartBase):
 
210
    """Formats one 'row' of the 94x160 space used in Big 5
 
211
 
 
212
    These deliberately resemble the code charts in Ken Lunde's "Understanding
 
213
    CJKV Information Processing", to enable manual checking."""
 
214
    def __init__(self, row, faceName, encodingName):
 
215
        self.row = row
 
216
        self.codePoints = 160
 
217
        self.boxSize = 18
 
218
        self.charsPerRow = 16
 
219
        self.rows = 10
 
220
        self.hex = 1
 
221
        self.faceName = faceName
 
222
        self.encodingName = encodingName
 
223
        self.rowLabels = ['4','5','6','7','A','B','C','D','E','F']
 
224
        try:
 
225
            # the dependent files might not be available
 
226
            font = cidfonts.CIDFont(self.faceName, self.encodingName)
 
227
            pdfmetrics.registerFont(font)
 
228
        except:
 
229
            # fall back to English and at least shwo we can draw the boxes
 
230
            self.faceName = 'Helvetica'
 
231
            self.encodingName = 'WinAnsiEncoding'
 
232
        self.fontName = self.faceName + '-' + self.encodingName
 
233
        self.calcLayout()
 
234
 
 
235
    def makeRow(self, row):
 
236
        """Works out the character values for this Big5 row.
 
237
        Rows start at 0xA1"""
 
238
        cells = []
 
239
        if string.find(self.encodingName, 'B5') > -1:
 
240
            # big 5, different row size
 
241
            for y in [4,5,6,7,10,11,12,13,14,15]:
 
242
                for x in range(16):
 
243
                    col = y*16+x
 
244
                    ch = chr(row) + chr(col)
 
245
                    cells.append(ch)
 
246
 
 
247
        else:
 
248
            cells.append([None] * 160)
 
249
        return cells
 
250
 
 
251
    def draw(self):
 
252
        self.drawLabels(topLeft='%02X' % self.row)
 
253
 
 
254
        charList = self.makeRow(self.row)
 
255
        self.drawChars(charList)
 
256
        self.canv.grid(self.xlist, self.ylist)
 
257
 
 
258
 
 
259
def hBoxText(msg, canvas, x, y, faceName, encName):
 
260
    """Helper for stringwidth tests on Asian fonts.
 
261
 
 
262
    Registers font if needed.  Then draws the string,
 
263
    and a box around it derived from the stringWidth function"""
 
264
    canvas.saveState()
 
265
    fontName = faceName + '-' + encName
 
266
    try:
 
267
        font = pdfmetrics.getFont(fontName)
 
268
    except KeyError:
 
269
        font = cidfonts.CIDFont(faceName, encName)
 
270
        pdfmetrics.registerFont(font)
 
271
 
 
272
    canvas.setFillGray(0.8)
 
273
    canvas.rect(x,y,pdfmetrics.stringWidth(msg, fontName, 16),16,stroke=0,fill=1)
 
274
    canvas.setFillGray(0)
 
275
    canvas.setFont(fontName, 16,16)
 
276
    canvas.drawString(x,y,msg)
 
277
    canvas.restoreState()
 
278
 
 
279
 
 
280
class CodeWidget(Widget):
 
281
    """Block showing all the characters"""
 
282
    def __init__(self):
 
283
        self.x = 0
 
284
        self.y = 0
 
285
        self.width = 160
 
286
        self.height = 160
 
287
 
 
288
    def draw(self):
 
289
        dx = self.width / 16.0
 
290
        dy = self.height / 16.0
 
291
        g = Group()
 
292
        g.add(Rect(self.x, self.y, self.width, self.height,
 
293
                   fillColor=None, strokeColor=colors.black))
 
294
        for x in range(16):
 
295
            for y in range(16):
 
296
                charValue = y * 16 + x
 
297
                if charValue > 32:
 
298
                    s = String(self.x + x * dx,
 
299
                               self.y + (self.height - y*dy), chr(charValue))
 
300
                    g.add(s)
 
301
        return g
 
302
 
 
303
 
 
304
 
 
305
 
 
306
 
 
307
 
 
308
def test():
 
309
    c = Canvas('codecharts.pdf')
 
310
    c.setFont('Helvetica-Bold', 24)
 
311
    c.drawString(72, 750, 'Testing code page charts')
 
312
    cc1 = SingleByteEncodingChart()
 
313
    cc1.drawOn(c, 72, 500)
 
314
 
 
315
    cc2 = SingleByteEncodingChart(charsPerRow=32)
 
316
    cc2.drawOn(c, 72, 300)
 
317
 
 
318
    cc3 = SingleByteEncodingChart(charsPerRow=25, hex=0)
 
319
    cc3.drawOn(c, 72, 100)
 
320
 
 
321
##    c.showPage()
 
322
##
 
323
##    c.setFont('Helvetica-Bold', 24)
 
324
##    c.drawString(72, 750, 'Multi-byte Kuten code chart examples')
 
325
##    KutenRowCodeChart(1, 'HeiseiMin-W3','EUC-H').drawOn(c, 72, 600)
 
326
##    KutenRowCodeChart(16, 'HeiseiMin-W3','EUC-H').drawOn(c, 72, 450)
 
327
##    KutenRowCodeChart(84, 'HeiseiMin-W3','EUC-H').drawOn(c, 72, 300)
 
328
##
 
329
##    c.showPage()
 
330
##    c.setFont('Helvetica-Bold', 24)
 
331
##    c.drawString(72, 750, 'Big5 Code Chart Examples')
 
332
##    #Big5CodeChart(0xA1, 'MSungStd-Light-Acro','ETenms-B5-H').drawOn(c, 72, 500)
 
333
 
 
334
    c.save()
 
335
    print 'saved codecharts.pdf'
 
336
 
 
337
if __name__=='__main__':
 
338
    test()
 
339
 
 
340