1 #!/usr/bin/env python
2 # -*- coding: UTF-8 -*-
3 '''
4 Copyright (C) 2009 John Beard john.j.beard@gmail.com
6 ######DESCRIPTION######
8 This extension renders a DataMatrix 2D barcode, as specified in
9 BS ISO/IEC 16022:2006. Only ECC200 codes are considered, as these are the only
10 ones recommended for an "open" system.
12 The size of the DataMatrix is variable between 10x10 to 144x144
14 The absolute size of the DataMatrix modules (the little squares) is also
15 variable.
17 If more data is given than can be contained in one DataMatrix,
18 more than one DataMatrices will be produced.
20 Text is encoded as ASCII (the standard provides for other options, but these are
21 not implemented). Consecutive digits are encoded in a compressed form, halving
22 the space required to store them.
24 The basis processing flow is;
25 * Convert input string to codewords (modified ASCII and compressed digits)
26 * Split codewords into blocks of the right size for Reed-Solomon coding
27 * Interleave the blocks if required
28 * Apply Reed-Solomon coding
29 * De-interleave the blocks if required
30 * Place the codewords into the matrix bit by bit
31 * Render the modules in the matrix as squares
33 ######LICENCE#######
34 This program is free software; you can redistribute it and/or modify
35 it under the terms of the GNU General Public License as published by
36 the Free Software Foundation; either version 2 of the License, or
37 (at your option) any later version.
39 This program is distributed in the hope that it will be useful,
40 but WITHOUT ANY WARRANTY; without even the implied warranty of
41 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
42 GNU General Public License for more details.
44 You should have received a copy of the GNU General Public License
45 along with this program; if not, write to the Free Software
46 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
48 ######VERSION HISTORY#####
49 Ver. Date Notes
51 0.50 2009-10-25 Full functionality, up to 144x144.
52 ASCII and compressed digit encoding only.
53 '''
55 import inkex, simplestyle
57 import gettext
58 _ = gettext.gettext
60 #ENCODING ROUTINES ===================================================
61 # Take an input string and convert it to a sequence (or sequences)
62 # of codewords as specified in ISO/IEC 16022:2006 (section 5.2.3)
63 #=====================================================================
65 #create a 2d list corresponding to the 1's and 0s of the DataMatrix
66 def encode(text, (nrow, ncol) ):
67 #retreive the parameters of this size of DataMatrix
68 data_nrow, data_ncol, reg_row, reg_col, nd, nc, inter = get_parameters( nrow, ncol )
70 if not ((nrow == 144) and (ncol == 144)): #we have a regular datamatrix
71 size144 = False
72 else: #special handling will be required by get_codewords()
73 size144 = True
75 #generate the codewords including padding and ECC
76 codewords = get_codewords( text, nd, nc, inter, size144 )
78 # break up into separate arrays if more than one DataMatrix is needed
79 module_arrays = []
80 for codeword_stream in codewords: #for each datamatrix
81 bit_array = place_bits(codeword_stream, (data_nrow*reg_row, data_ncol*reg_col)) #place the codewords' bits across the array as modules
82 module_arrays.append(add_finder_pattern( bit_array, data_nrow, data_ncol, reg_row, reg_col )) #add finder patterns around the modules
84 return module_arrays
86 #return parameters for the selected datamatrix size
87 # data_nrow number of rows in each data region
88 # data_ncol number of cols in each data region
89 # reg_row number of rows of data regions
90 # reg_col number of cols of data regions
91 # nd number of data codewords per reed-solomon block
92 # nc number of ECC codewords per reed-solomon block
93 # inter number of interleaved Reed-Solomon blocks
94 def get_parameters(nrow, ncol):
96 #SQUARE SYMBOLS
97 if ( nrow == 10 and ncol == 10 ):
98 return 8, 8, 1, 1, 3, 5, 1
99 elif ( nrow == 12 and ncol == 12 ):
100 return 10, 10, 1, 1, 5, 7, 1
101 elif ( nrow == 14 and ncol == 14 ):
102 return 12, 12, 1, 1, 8, 10, 1
103 elif ( nrow == 16 and ncol == 16 ):
104 return 14, 14, 1, 1, 12, 12, 1
105 elif ( nrow == 18 and ncol == 18 ):
106 return 16, 16, 1, 1, 18, 14, 1
107 elif ( nrow == 20 and ncol == 20 ):
108 return 18, 18, 1, 1, 22, 18, 1
109 elif ( nrow == 22 and ncol == 22 ):
110 return 18, 18, 1, 1, 30, 20, 1
111 elif ( nrow == 24 and ncol == 24 ):
112 return 22, 22, 1, 1, 36, 24, 1
113 elif ( nrow == 26 and ncol == 26 ):
114 return 24, 24, 1, 1, 44, 28, 1
115 elif ( nrow == 32 and ncol == 32 ):
116 return 14, 14, 2, 2, 62, 36, 1
117 elif ( nrow == 36 and ncol == 36 ):
118 return 16, 16, 2, 2, 86, 42, 1
119 elif ( nrow == 40 and ncol == 40):
120 return 18, 18, 2, 2, 114, 48, 1
121 elif ( nrow == 44 and ncol == 44):
122 return 20, 20, 2, 2, 144, 56, 1
123 elif ( nrow == 48 and ncol == 48 ):
124 return 22, 22, 2, 2, 174, 68, 1
126 elif ( nrow == 52 and ncol == 52 ):
127 return 24, 24, 2, 2, 102, 42, 2
128 elif ( nrow == 64 and ncol == 64 ):
129 return 16, 16, 4, 4, 140, 56, 2
131 elif ( nrow == 72 and ncol == 72 ):
132 return 16, 16, 4, 4, 92, 36, 4
133 elif ( nrow == 80 and ncol == 80 ):
134 return 18, 18, 4, 4, 114, 48, 4
135 elif ( nrow == 88 and ncol == 88 ):
136 return 20, 20, 4, 4, 144, 56, 4
137 elif ( nrow == 96 and ncol == 96 ):
138 return 22, 22, 4, 4, 174, 68, 4
140 elif ( nrow == 104 and ncol == 104 ):
141 return 24, 24, 4, 4, 136, 56, 6
142 elif ( nrow == 120 and ncol == 120):
143 return 18, 18, 6, 6, 175, 68, 6
145 elif ( nrow == 132 and ncol == 132):
146 return 20, 20, 6, 6, 163, 62, 8
148 elif (nrow == 144 and ncol == 144):
149 return 22, 22, 6, 6, 0, 0, 0 #there are two separate sections of the data matrix with
150 #different interleaving and reed-solomon parameters.
151 #this will be handled separately
153 #RECTANGULAR SYMBOLS
154 elif ( nrow == 8 and ncol == 18 ):
155 return 6, 16, 1, 1, 5, 7, 1
156 elif ( nrow == 8 and ncol == 32 ):
157 return 6, 14, 1, 2, 10, 11, 1
158 elif ( nrow == 12 and ncol == 26 ):
159 return 10, 24, 1, 1, 16, 14, 1
160 elif ( nrow == 12 and ncol == 36 ):
161 return 10, 16, 1, 2, 22, 18, 1
162 elif ( nrow == 16 and ncol == 36 ):
163 return 14, 16, 1, 2, 32, 24, 1
164 elif ( nrow == 16 and ncol == 48 ):
165 return 14, 22, 1, 2, 49, 28, 1
167 #RETURN ERROR
168 else:
169 inkex.errormsg(_('Unrecognised DataMatrix size'))
171 return None
173 # CODEWORD STREAM GENERATION =========================================
174 #take the text input and return the codewords,
175 #including the Reed-Solomon error-correcting codes.
176 #=====================================================================
178 def get_codewords( text, nd, nc, inter, size144 ):
179 #convert the data to the codewords
180 data = encode_to_ascii( text )
182 if not size144: #render a "normal" datamatrix
183 data_blocks = partition_data(data, nd*inter) #partition into data blocks of length nd*inter -> inter Reed-Solomon block
185 data_blocks = interleave( data_blocks, inter) # interleave consecutive inter blocks if required
187 data_blocks = reed_solomon(data_blocks, nd, nc) #generate and append the Reed-Solomon codewords
189 data_blocks = combine_interleaved(data_blocks, inter, nd, nc, False) #concatenate Reed-Solomon blocks bound for the same datamatrix
191 else: #we have a 144x144 datamatrix
192 data_blocks = partition_data(data, 1558) #partition the data into datamtrix-sized chunks (1558 =156*8 + 155*2 )
194 for i in range(len(data_blocks)): #for each datamtrix
197 inter = 8
198 nd = 156
199 nc = 62
200 block1 = data_blocks[i][0:156*8]
201 block1 = interleave( [block1], inter) # interleave into 8 blocks
202 block1 = reed_solomon(block1, nd, nc) #generate and append the Reed-Solomon codewords
204 inter = 2
205 nd = 155
206 nc = 62
207 block2 = data_blocks[i][156*8:]
208 block2 = interleave( [block2], inter) # interleave into 2 blocks
209 block2 = reed_solomon(block2, nd, nc) #generate and append the Reed-Solomon codewords
211 blocks = block1
212 blocks.extend(block2)
214 blocks = combine_interleaved(blocks, 10, nd, nc, True)
216 data_blocks[i] = blocks[0]
219 return data_blocks
222 #Takes a codeword stream and splits up into "inter" blocks.
223 #eg interleave( [1,2,3,4,5,6], 2 ) -> [1,3,5], [2,4,6]
224 def interleave( blocks, inter):
226 if inter == 1: # if we don't have to interleave, just return the blocks
227 return blocks
228 else:
229 result = []
230 for block in blocks: #for each codeword block in the stream
231 block_length = len(block)/inter #length of each interleaved block
232 inter_blocks = [[0] * block_length for i in xrange(inter)] #the interleaved blocks
234 for i in range(block_length): #for each element in the interleaved blocks
235 for j in range(inter): #for each interleaved block
236 inter_blocks[j][i] = block[ i*inter + j ]
238 result.extend(inter_blocks) #add the interleaved blocks to the output
240 return result
242 #Combine interleaved blocks into the groups for the same datamatrix
243 #
244 #e.g combine_interleaved( [[d1, d3, d5, e1, e3, e5], [d2, d4, d6, e2, e4, e6]], 2, 3, 3 )
245 # --> [[d1, d2, d3, d4, d5, d6, e1, e2, e3, e4, e5, e6]]
246 def combine_interleaved( blocks, inter, nd, nc, size144):
247 if inter == 1: #the blocks aren't interleaved
248 return blocks
249 else:
250 result = []
251 for i in range( len(blocks) / inter ): #for each group of "inter" blocks -> one full datamatrix
252 data_codewords = [] #interleaved data blocks
254 if size144:
255 nd_range = 1558 #1558 = 156*8 + 155*2
256 nc_range = 620 #620 = 62*8 + 62*2
257 else:
258 nd_range = nd*inter
259 nc_range = nc*inter
261 for j in range(nd_range): #for each codeword in the final list
262 data_codewords.append( blocks[i*inter + j%inter][j/inter] )
264 for j in range(nc_range): #for each block, add the ecc codewords
265 data_codewords.append( blocks[i*inter + j%inter][nd + j/inter] )
267 result.append(data_codewords)
268 return result
270 #checks if an ASCII character is a digit from 0 - 9
271 def is_digit( char ):
273 if ord(char) >= 48 and ord(char) <= 57:
274 return True
275 else:
276 return False
278 def encode_to_ascii( text):
280 ascii = []
281 i = 0
282 while i < len(text):
283 #check for double digits
284 if is_digit( text[i] ) and ( i < len(text)-1) and is_digit( text[i+1] ): #if the next char is also a digit
286 codeword = int( text[i] + text[i+1] ) + 130
287 ascii.append( codeword )
288 i = i + 2 #move on 2 characters
289 else: #encode as a normal ascii,
290 ascii.append( ord(text[i] ) + 1 ) #codeword is ASCII value + 1 (ISO 16022:2006 5.2.3)
291 i = i + 1 #next character
293 return ascii
296 #partition data into blocks of the appropriate size to suit the
297 #Reed-Solomon block being used.
298 #e.g. partition_data([1,2,3,4,5], 3) -> [[1,2,3],[4,5,PAD]]
299 def partition_data( data , rs_data):
301 PAD_VAL = 129 # PAD codeword (ISO 16022:2006 5.2.3)
302 data_blocks = []
303 i = 0
304 while i < len(data):
305 if len(data) >= i+rs_data: #we have a whole block in our data
306 data_blocks.append( data[i:i+rs_data] )
307 i = i + rs_data
308 else: #pad out with the pad codeword
309 data_block = data[i:len(data)] #add any remaining data
310 pad_pos = len(data)
311 padded = False
312 while len(data_block) < rs_data:#and then pad with randomised pad codewords
313 if not padded:
314 data_block.append( PAD_VAL ) #add a normal pad codeword
315 padded = True
316 else:
317 data_block.append( randomise_pad_253( PAD_VAL, pad_pos) )
318 pad_pos = pad_pos + 1
319 data_blocks.append( data_block)
320 break
322 return data_blocks
324 #Pad character randomisation, to prevent regular patterns appearing
325 #in the data matrix
326 def randomise_pad_253(pad_value, pad_position ):
327 pseudo_random_number = ( ( 149 * pad_position ) % 253 )+ 1
328 randomised = pad_value + pseudo_random_number
329 if ( randomised <= 254 ):
330 return randomised
331 else:
332 return randomised - 254
334 # REED-SOLOMON ENCODING ROUTINES =====================================
336 # "prod(x,y,log,alog,gf)" returns the product "x" times "y"
337 def prod(x, y, log, alog, gf):
339 if ( x==0 or y==0):
340 return 0
341 else:
342 result = alog[ ( log[x] + log[y] ) % (gf - 1) ]
343 return result
345 # generate the log & antilog lists:
346 def gen_log_alog(gf, pp):
347 log = [0]*gf
348 alog = [0]*gf
350 log[0] = 1-gf
351 alog[0] = 1
353 for i in range(1,gf):
354 alog[i] = alog[i-1] * 2
356 if (alog[i] >= gf):
357 alog[i] = alog[i] ^ pp
359 log[alog[i]] = i
361 return log, alog
363 # generate the generator polynomial coefficients:
364 def gen_poly_coeffs(nc, log, alog, gf):
365 c = [0] * (nc+1)
366 c[0] = 1
368 for i in range(1,nc+1):
369 c[i] = c[i-1]
371 j = i-1
372 while j >= 1:
373 c[j] = c[j-1] ^ prod(c[j],alog[i],log,alog,gf)
374 j = j - 1
376 c[0] = prod(c[0],alog[i],log,alog,gf)
378 return c
380 # "ReedSolomon(wd,nd,nc)" takes "nd" data codeword values in wd[]
381 # and adds on "nc" check codewords, all within GF(gf) where "gf" is a
382 # power of 2 and "pp" is the value of its prime modulus polynomial */
383 def reed_solomon(data, nd, nc):
384 #parameters of the polynomial arithmetic
385 gf = 256 #operating on 8-bit codewords -> Galois field = 2^8 = 256
386 pp = 301 #prime modulus polynomial for ECC-200 is 0b100101101 = 301 (ISO 16022:2006 5.7.1)
388 log, alog = gen_log_alog(gf,pp)
389 c = gen_poly_coeffs(nc, log, alog, gf)
391 for block in data: #for each block of data codewords
393 block.extend( [0]*(nc+1) ) #extend to make space for the error codewords
395 #generate "nc" checkwords in the list block
396 for i in range(0, nd):
397 k = block[nd] ^ block[i]
399 for j in range(0,nc):
400 block[nd+j] = block[nd+j+1] ^ prod(k,c[nc-j-1],log, alog,gf)
402 block.pop()
404 return data
406 #MODULE PLACEMENT ROUTINES===========================================
407 # These routines take a steam of codewords, and place them into the
408 # DataMatrix in accordance with Annex F of BS ISO/IEC 16022:2006
410 # bit() returns the bit'th bit of the byte
411 def bit(byte, bit):
412 #the MSB is bit 1, LSB is bit 8
413 return ( byte >> (8-bit) ) %2
415 # "module" places a given bit with appropriate wrapping within array
416 def module(array, nrow, ncol, row, col, bit) :
417 if (row < 0) :
418 row = row + nrow
419 col = col + 4 - ((nrow+4)%8)
421 if (col < 0):
422 col = col + ncol
423 row = row + 4 - ((ncol+4)%8)
425 array[row][col] = bit
427 def corner1(array, nrow, ncol, char):
428 module(array, nrow, ncol, nrow-1, 0, bit(char,1));
429 module(array, nrow, ncol, nrow-1, 1, bit(char,2));
430 module(array, nrow, ncol, nrow-1, 2, bit(char,3));
431 module(array, nrow, ncol, 0, ncol-2, bit(char,4));
432 module(array, nrow, ncol, 0, ncol-1, bit(char,5));
433 module(array, nrow, ncol, 1, ncol-1, bit(char,6));
434 module(array, nrow, ncol, 2, ncol-1, bit(char,7));
435 module(array, nrow, ncol, 3, ncol-1, bit(char,8));
437 def corner2(array, nrow, ncol, char):
438 module(array, nrow, ncol, nrow-3, 0, bit(char,1));
439 module(array, nrow, ncol, nrow-2, 0, bit(char,2));
440 module(array, nrow, ncol, nrow-1, 0, bit(char,3));
441 module(array, nrow, ncol, 0, ncol-4, bit(char,4));
442 module(array, nrow, ncol, 0, ncol-3, bit(char,5));
443 module(array, nrow, ncol, 0, ncol-2, bit(char,6));
444 module(array, nrow, ncol, 0, ncol-1, bit(char,7));
445 module(array, nrow, ncol, 1, ncol-1, bit(char,8));
447 def corner3(array, nrow, ncol, char):
448 module(array, nrow, ncol, nrow-3, 0, bit(char,1));
449 module(array, nrow, ncol, nrow-2, 0, bit(char,2));
450 module(array, nrow, ncol, nrow-1, 0, bit(char,3));
451 module(array, nrow, ncol, 0, ncol-2, bit(char,4));
452 module(array, nrow, ncol, 0, ncol-1, bit(char,5));
453 module(array, nrow, ncol, 1, ncol-1, bit(char,6));
454 module(array, nrow, ncol, 2, ncol-1, bit(char,7));
455 module(array, nrow, ncol, 3, ncol-1, bit(char,8));
457 def corner4(array, nrow, ncol, char):
458 module(array, nrow, ncol, nrow-1, 0, bit(char,1));
459 module(array, nrow, ncol, nrow-1, ncol-1, bit(char,2));
460 module(array, nrow, ncol, 0, ncol-3, bit(char,3));
461 module(array, nrow, ncol, 0, ncol-2, bit(char,4));
462 module(array, nrow, ncol, 0, ncol-1, bit(char,5));
463 module(array, nrow, ncol, 1, ncol-3, bit(char,6));
464 module(array, nrow, ncol, 1, ncol-2, bit(char,7));
465 module(array, nrow, ncol, 1, ncol-1, bit(char,8));
467 #"utah" places the 8 bits of a utah-shaped symbol character in ECC200
468 def utah(array, nrow, ncol, row, col, char):
469 module(array, nrow, ncol,row-2, col-2, bit(char,1))
470 module(array, nrow, ncol,row-2, col-1, bit(char,2))
471 module(array, nrow, ncol,row-1, col-2, bit(char,3))
472 module(array, nrow, ncol,row-1, col-1, bit(char,4))
473 module(array, nrow, ncol,row-1, col, bit(char,5))
474 module(array, nrow, ncol,row, col-2, bit(char,6))
475 module(array, nrow, ncol,row, col-1, bit(char,7))
476 module(array, nrow, ncol,row, col, bit(char,8))
478 #"place_bits" fills an nrow x ncol array with the bits from the
479 # codewords in data.
480 def place_bits(data, (nrow, ncol)):
481 # First, fill the array[] with invalid entries */
482 INVALID = 2
483 array = [[INVALID] * ncol for i in xrange(nrow)] #initialise and fill with -1's (invalid value)
484 # Starting in the correct location for character #1, bit 8,...
485 char = 0
486 row = 4
487 col = 0
488 while True:
490 #first check for one of the special corner cases, then...
491 if ((row == nrow) and (col == 0)):
492 corner1(array, nrow, ncol, data[char])
493 char = char + 1
494 if ((row == nrow-2) and (col == 0) and (ncol%4)) :
495 corner2(array, nrow, ncol, data[char])
496 char = char + 1
497 if ((row == nrow-2) and (col == 0) and (ncol%8 == 4)):
498 corner3(array, nrow, ncol, data[char])
499 char = char + 1
500 if ((row == nrow+4) and (col == 2) and ((ncol%8) == 0)):
501 corner4(array, nrow, ncol, data[char])
502 char = char + 1
504 #sweep upward diagonally, inserting successive characters,...
505 while True:
506 if ((row < nrow) and (col >= 0) and (array[row][col] == INVALID)) :
507 utah(array, nrow, ncol,row,col,data[char])
508 char = char+1
509 row = row - 2
510 col = col + 2
512 if not((row >= 0) and (col < ncol)):
513 break
515 row = row + 1
516 col = col + 3
518 # & then sweep downward diagonally, inserting successive characters,...
519 while True:
520 if ((row >= 0) and (col < ncol) and (array[row][col] == INVALID)) :
521 utah(array, nrow, ncol,row,col,data[char])
522 char = char + 1
523 row = row + 2
524 col = col - 2
526 if not((row < nrow) and (col >= 0)):
527 break
529 row = row + 3
530 col = col + 1
532 #... until the entire array is scanned
533 if not((row < nrow) or (col < ncol)):
534 break
536 # Lastly, if the lower righthand corner is untouched, fill in fixed pattern */
537 if (array[nrow-1][ncol-1] == INVALID):
538 array[nrow-1][ncol-2] = 0
539 array[nrow-1][ncol-1] = 1
540 array[nrow-2][ncol-1] = 0
541 array[nrow-2][ncol-2] = 1
543 return array #return the array of 1's and 0's
546 def add_finder_pattern( array, data_nrow, data_ncol, reg_row, reg_col ):
548 #get the total size of the datamatrix
549 nrow = (data_nrow+2) * reg_row
550 ncol = (data_ncol+2) * reg_col
552 datamatrix = [[0] * ncol for i in xrange(nrow)] #initialise and fill with 0's
554 for i in range( reg_col ): #for each column of data regions
555 for j in range(nrow):
556 datamatrix[j][i*(data_ncol+2)] = 1 #vertical black bar on left
557 datamatrix[j][i*(data_ncol+2)+data_ncol+1] = (j)%2 # alternating blocks
559 for i in range( reg_row): # for each row of data regions
560 for j in range(ncol):
561 datamatrix[i*(data_nrow+2)+data_nrow+1][j] = 1 #horizontal black bar at bottom
562 datamatrix[i*(data_nrow+2)][j] = (j+1)%2 # alternating blocks
564 for i in range( data_nrow*reg_row ):
565 for j in range( data_ncol* reg_col ):
566 dest_col = j + 1 + 2*(j/(data_ncol)) #offset by 1, plus two for every addition block
567 dest_row = i + 1 + 2*(i/(data_nrow))
569 datamatrix[dest_row][dest_col] = array[i][j] #transfer from the plain bit array
571 return datamatrix
573 #RENDERING ROUTINES ==================================================
574 # Take the array of 1's and 0's and render as a series of black
575 # squares. A binary 1 is a filled square
576 #=====================================================================
578 #SVG element generation routine
579 def draw_SVG_square((w,h), (x,y), parent):
581 style = { 'stroke' : 'none',
582 'stroke-width' : '1',
583 'fill' : '#000000'
584 }
586 attribs = {
587 'style' :simplestyle.formatStyle(style),
588 'height' : str(h),
589 'width' : str(w),
590 'x' : str(x),
591 'y' : str(y)
592 }
593 circ = inkex.etree.SubElement(parent, inkex.addNS('rect','svg'), attribs )
595 #turn a 2D array of 1's and 0's into a set of black squares
596 def render_data_matrix( module_arrays, size, spacing, parent):
598 for i in range(len(module_arrays)): #for each data matrix
600 height = len(module_arrays[i])
601 width = len(module_arrays[i][0] )
603 for y in range(height): #loop over all the modules in the datamatrix
604 for x in range(width):
606 if module_arrays[i][y][x] == 1: #A binary 1 is a filled square
607 draw_SVG_square((size,size), (x*size + i*spacing,y*size), parent)
608 elif module_arrays[i][y][x] != 0: #we have an invalid bit value
609 inkex.errormsg(_('Invalid bit value, this is a bug!'))
611 class DataMatrix(inkex.Effect):
612 def __init__(self):
613 inkex.Effect.__init__(self)
615 #PARSE OPTIONS
616 self.OptionParser.add_option("--text",
617 action="store", type="string",
618 dest="TEXT", default='Inkscape')
619 self.OptionParser.add_option("--rows",
620 action="store", type="int",
621 dest="ROWS", default=10)
622 self.OptionParser.add_option("--cols",
623 action="store", type="int",
624 dest="COLS", default=10)
625 self.OptionParser.add_option("--size",
626 action="store", type="int",
627 dest="SIZE", default=4)
629 def effect(self):
631 so = self.options
633 if so.TEXT == '': #abort if converting blank text
634 inkex.errormsg(_('Please enter an input string'))
635 else:
637 #INKSCAPE GROUP TO CONTAIN EVERYTHING
639 centre = self.view_center #Put in in the centre of the current view
640 grp_transform = 'translate' + str( centre )
641 grp_name = 'DataMatrix'
642 grp_attribs = {inkex.addNS('label','inkscape'):grp_name,
643 'transform':grp_transform }
644 grp = inkex.etree.SubElement(self.current_layer, 'g', grp_attribs)#the group to put everything in
646 #GENERATE THE DATAMATRIX
647 encoded = encode( so.TEXT, (so.ROWS, so.COLS) ) #get the pattern of squares
648 render_data_matrix( encoded, so.SIZE, so.COLS*so.SIZE*1.5, grp ) # generate the SVG elements
650 if __name__ == '__main__':
651 e = DataMatrix()
652 e.affect()
654 # vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 encoding=utf-8 textwidth=99