summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: ebe92ca)
raw | patch | inline | side by side (parent: ebe92ca)
author | d <d@d-desktop> | |
Tue, 9 Nov 2010 04:08:25 +0000 (00:08 -0400) | ||
committer | d <d@d-desktop> | |
Tue, 9 Nov 2010 04:08:25 +0000 (00:08 -0400) |
share/extensions/Makefile.am | patch | blob | history | |
share/extensions/render_barcode_qrcode.inx | [new file with mode: 0644] | patch | blob |
share/extensions/render_barcode_qrcode.py | [new file with mode: 0644] | patch | blob |
index d77ac1fec79e651f416bcefd7b6e82fcc6c96104..f735f2ff249b7dfb4fcc59d0023cba25018f6564 100644 (file)
restack.py \
render_barcode.py \
render_barcode_datamatrix.py \
+ render_barcode_qrcode.py \
render_alphabetsoup.py \
render_alphabetsoup_config.py \
rtree.py \
radiusrand.inx \
render_barcode.inx \
render_barcode_datamatrix.inx \
+ render_barcode_qrcode.inx \
render_alphabetsoup.inx \
replace_font.inx \
restack.inx \
diff --git a/share/extensions/render_barcode_qrcode.inx b/share/extensions/render_barcode_qrcode.inx
--- /dev/null
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
+ <_name>Barcode - QR Code</_name>
+ <id>org.inkscape.qrcode</id>
+ <dependency type="executable" location="extensions">render_barcode_qrcode.py</dependency>
+ <dependency type="executable" location="extensions">inkex.py</dependency>
+ <_param name="generalhint" type="description" xml:space="preserve">See http://www.denso-wave.com/qrcode/index-e.html for details</_param>
+ <param name="text" type="string" _gui-text="Text:">www.inkscape.org</param>
+ <param name="typenumber" type="enum" _gui-text="Size, in unit squares:">
+ <_item value="0">Auto</_item>
+ <item value="1">21x21</item>
+ <item value="2">25x25</item>
+ <item value="3">29x29</item>
+ <item value="4">33x33</item>
+ <item value="5">37x37</item>
+ <item value="6">41x41</item>
+ <item value="7">45x45</item>
+ <item value="8">49x49</item>
+ <item value="9">53x53</item>
+ <item value="10">57x37</item>
+ <item value="11">61x61</item>
+ <item value="12">65x65</item>
+ <item value="13">69x69</item>
+ <item value="14">73x73</item>
+ <item value="15">77x77</item>
+ <item value="16">81x81</item>
+ <item value="17">85x85</item>
+ <item value="18">89x89</item>
+ <item value="19">93x93</item>
+ <item value="20">97x97</item>
+ <item value="21">101x101</item>
+ <item value="22">105x105</item>
+ <item value="23">109x109</item>
+ <item value="24">113x113</item>
+ <item value="25">117x117</item>
+ <item value="26">121x121</item>
+ <item value="27">125x125</item>
+ <item value="28">129x129</item>
+ <item value="29">133x133</item>
+ <item value="30">137x137</item>
+ <item value="31">141x141</item>
+ <item value="32">145x145</item>
+ <item value="33">149x149</item>
+ <item value="34">153x153</item>
+ <item value="35">157x157</item>
+ <item value="36">161x161</item>
+ <item value="37">165x165</item>
+ <item value="38">169x169</item>
+ <item value="39">173x173</item>
+ <item value="40">177x177</item>
+ </param>
+ <_param name="sizehint" type="description" xml:space="preserve">With "Auto", the size of the barcode depends on the length of the text and the error correction level</_param>
+ <param name="correctionlevel" type="enum" _gui-text="Error correction level:">
+ <_item value="1">L (Approx. 7%)</_item>
+ <_item value="0">M (Approx. 15%)</_item>
+ <_item value="3">Q (Approx. 25%)</_item>
+ <_item value="2">H (Approx. 30%)</_item>
+ </param>
+ <param name="modulesize" type="float" min="0" max="1000" _gui-text="Square size (px):">4</param>
+ <effect>
+ <object-type>all</object-type>
+ <effects-menu>
+ <submenu _name="Render"/>
+ </effects-menu>
+ </effect>
+ <script>
+ <command reldir="extensions" interpreter="python">render_barcode_qrcode.py</command>
+ </script>
+</inkscape-extension>
diff --git a/share/extensions/render_barcode_qrcode.py b/share/extensions/render_barcode_qrcode.py
--- /dev/null
@@ -0,0 +1,1057 @@
+import math, sys\r
+import inkex\r
+\r
+#QRCode for Python\r
+#\r
+#Ported from the Javascript library by Sam Curren\r
+#\r
+#QRCode for Javascript\r
+#http://d-project.googlecode.com/svn/trunk/misc/qrcode/js/qrcode.js\r
+#\r
+#Copyright (c) 2009 Kazuhiko Arase\r
+#\r
+#URL: http://www.d-project.com/\r
+#\r
+#Licensed under the MIT license:\r
+# http://www.opensource.org/licenses/mit-license.php\r
+#\r
+# The word "QR Code" is registered trademark of\r
+# DENSO WAVE INCORPORATED\r
+# http://www.denso-wave.com/qrcode/faqpatent-e.html\r
+\r
+\r
+class QR8bitByte:\r
+\r
+ def __init__(self, data):\r
+ self.mode = QRMode.MODE_8BIT_BYTE\r
+ self.data = data\r
+\r
+ def getLength(self):\r
+ return len(self.data)\r
+\r
+ def write(self, buffer):\r
+ for i in range(len(self.data)):\r
+ #// not JIS ...\r
+ buffer.put(ord(self.data[i]), 8)\r
+ def __repr__(self):\r
+ return self.data\r
+\r
+class QRCode:\r
+ def __init__(self, typeNumber, errorCorrectLevel):\r
+ self.typeNumber = typeNumber\r
+ self.errorCorrectLevel = errorCorrectLevel\r
+ self.modules = None\r
+ self.moduleCount = 0\r
+ self.dataCache = None\r
+ self.dataList = []\r
+ def addData(self, data):\r
+ newData = QR8bitByte(data)\r
+ self.dataList.append(newData)\r
+ self.dataCache = None\r
+ def isDark(self, row, col):\r
+ if (row < 0 or self.moduleCount <= row or col < 0 or self.moduleCount <= col):\r
+ raise Exception("%s,%s - %s" % (row, col, self.moduleCount))\r
+ return self.modules[row][col]\r
+ def getModuleCount(self):\r
+ return self.moduleCount\r
+ def make(self):\r
+ self.makeImpl(False, self.getBestMaskPattern() )\r
+ def makeImpl(self, test, maskPattern):\r
+\r
+ if self.typeNumber == 0:\r
+ self.typeNumber = QRCode.autoNumber(self.errorCorrectLevel, self.dataList)\r
+ self.moduleCount = self.typeNumber * 4 + 17\r
+ self.modules = [None for x in range(self.moduleCount)]\r
+\r
+ for row in range(self.moduleCount):\r
+\r
+ self.modules[row] = [None for x in range(self.moduleCount)]\r
+\r
+ for col in range(self.moduleCount):\r
+ self.modules[row][col] = None #//(col + row) % 3;\r
+\r
+ self.setupPositionProbePattern(0, 0)\r
+ self.setupPositionProbePattern(self.moduleCount - 7, 0)\r
+ self.setupPositionProbePattern(0, self.moduleCount - 7)\r
+ self.setupPositionAdjustPattern()\r
+ self.setupTimingPattern()\r
+ self.setupTypeInfo(test, maskPattern)\r
+\r
+ if (self.typeNumber >= 7):\r
+ self.setupTypeNumber(test)\r
+\r
+ if (self.dataCache == None):\r
+ self.dataCache = QRCode.createData(self.typeNumber, self.errorCorrectLevel, self.dataList)\r
+ self.mapData(self.dataCache, maskPattern)\r
+\r
+ def setupPositionProbePattern(self, row, col):\r
+\r
+ for r in range(-1, 8):\r
+\r
+ if (row + r <= -1 or self.moduleCount <= row + r): continue\r
+\r
+ for c in range(-1, 8):\r
+\r
+ if (col + c <= -1 or self.moduleCount <= col + c): continue\r
+\r
+ if ( (0 <= r and r <= 6 and (c == 0 or c == 6) )\r
+ or (0 <= c and c <= 6 and (r == 0 or r == 6) )\r
+ or (2 <= r and r <= 4 and 2 <= c and c <= 4) ):\r
+ self.modules[row + r][col + c] = True;\r
+ else:\r
+ self.modules[row + r][col + c] = False;\r
+\r
+ def getBestMaskPattern(self):\r
+\r
+ minLostPoint = 0\r
+ pattern = 0\r
+\r
+ for i in range(8):\r
+\r
+ self.makeImpl(True, i);\r
+\r
+ lostPoint = QRUtil.getLostPoint(self);\r
+\r
+ if (i == 0 or minLostPoint > lostPoint):\r
+ minLostPoint = lostPoint\r
+ pattern = i\r
+\r
+ return pattern\r
+\r
+ def makeSVG(self, grp, boxsize):\r
+ pixelsize = self.getModuleCount() * boxsize\r
+\r
+ for r in range(self.getModuleCount()):\r
+ for c in range(self.getModuleCount()):\r
+ if (self.isDark(r, c) ):\r
+ x = c * boxsize\r
+ y = r * boxsize\r
+ rect = inkex.etree.SubElement(grp, inkex.addNS('rect', 'svg'))\r
+ rect.set('x', str(x))\r
+ rect.set('y', str(y))\r
+ rect.set('width', str(boxsize))\r
+ rect.set('height', str(boxsize))\r
+ rect.set('style', 'fill:black;stroke:none')\r
+\r
+ def setupTimingPattern(self):\r
+\r
+ for r in range(8, self.moduleCount - 8):\r
+ if (self.modules[r][6] != None):\r
+ continue\r
+ self.modules[r][6] = (r % 2 == 0)\r
+\r
+ for c in range(8, self.moduleCount - 8):\r
+ if (self.modules[6][c] != None):\r
+ continue\r
+ self.modules[6][c] = (c % 2 == 0)\r
+\r
+ def setupPositionAdjustPattern(self):\r
+\r
+ pos = QRUtil.getPatternPosition(self.typeNumber)\r
+\r
+ for i in range(len(pos)):\r
+\r
+ for j in range(len(pos)):\r
+\r
+ row = pos[i]\r
+ col = pos[j]\r
+\r
+ if (self.modules[row][col] != None):\r
+ continue\r
+\r
+ for r in range(-2, 3):\r
+\r
+ for c in range(-2, 3):\r
+\r
+ if (r == -2 or r == 2 or c == -2 or c == 2 or (r == 0 and c == 0) ):\r
+ self.modules[row + r][col + c] = True\r
+ else:\r
+ self.modules[row + r][col + c] = False\r
+\r
+ def setupTypeNumber(self, test):\r
+\r
+ bits = QRUtil.getBCHTypeNumber(self.typeNumber)\r
+\r
+ for i in range(18):\r
+ mod = (not test and ( (bits >> i) & 1) == 1)\r
+ self.modules[i // 3][i % 3 + self.moduleCount - 8 - 3] = mod;\r
+\r
+ for i in range(18):\r
+ mod = (not test and ( (bits >> i) & 1) == 1)\r
+ self.modules[i % 3 + self.moduleCount - 8 - 3][i // 3] = mod;\r
+\r
+ def setupTypeInfo(self, test, maskPattern):\r
+\r
+ data = (self.errorCorrectLevel << 3) | maskPattern\r
+ bits = QRUtil.getBCHTypeInfo(data)\r
+\r
+ #// vertical\r
+ for i in range(15):\r
+\r
+ mod = (not test and ( (bits >> i) & 1) == 1)\r
+\r
+ if (i < 6):\r
+ self.modules[i][8] = mod\r
+ elif (i < 8):\r
+ self.modules[i + 1][8] = mod\r
+ else:\r
+ self.modules[self.moduleCount - 15 + i][8] = mod\r
+\r
+ #// horizontal\r
+ for i in range(15):\r
+\r
+ mod = (not test and ( (bits >> i) & 1) == 1);\r
+\r
+ if (i < 8):\r
+ self.modules[8][self.moduleCount - i - 1] = mod\r
+ elif (i < 9):\r
+ self.modules[8][15 - i - 1 + 1] = mod\r
+ else:\r
+ self.modules[8][15 - i - 1] = mod\r
+\r
+ #// fixed module\r
+ self.modules[self.moduleCount - 8][8] = (not test)\r
+\r
+ def mapData(self, data, maskPattern):\r
+\r
+ inc = -1\r
+ row = self.moduleCount - 1\r
+ bitIndex = 7\r
+ byteIndex = 0\r
+\r
+ for col in range(self.moduleCount - 1, 0, -2):\r
+\r
+ if (col == 6): col-=1\r
+\r
+ while (True):\r
+\r
+ for c in range(2):\r
+\r
+ if (self.modules[row][col - c] == None):\r
+\r
+ dark = False\r
+\r
+ if (byteIndex < len(data)):\r
+ dark = ( ( (data[byteIndex] >> bitIndex) & 1) == 1)\r
+\r
+ mask = QRUtil.getMask(maskPattern, row, col - c)\r
+\r
+ if (mask):\r
+ dark = not dark\r
+\r
+ self.modules[row][col - c] = dark\r
+ bitIndex-=1\r
+\r
+ if (bitIndex == -1):\r
+ byteIndex+=1\r
+ bitIndex = 7\r
+\r
+ row += inc\r
+\r
+ if (row < 0 or self.moduleCount <= row):\r
+ row -= inc\r
+ inc = -inc\r
+ break\r
+ PAD0 = 0xEC\r
+ PAD1 = 0x11\r
+\r
+ @staticmethod\r
+ def autoNumber(errorCorrectLevel, dataList):\r
+\r
+ for tn in range (1, 40):\r
+ \r
+ rsBlocks = QRRSBlock.getRSBlocks(tn, errorCorrectLevel)\r
+\r
+ buffer = QRBitBuffer();\r
+\r
+ for i in range(len(dataList)):\r
+ data = dataList[i]\r
+ buffer.put(data.mode, 4)\r
+ buffer.put(data.getLength(), QRUtil.getLengthInBits(data.mode, tn) )\r
+ data.write(buffer)\r
+\r
+ #// calc num max data.\r
+ totalDataCount = 0;\r
+ for i in range(len(rsBlocks)):\r
+ totalDataCount += rsBlocks[i].dataCount\r
+\r
+ if (buffer.getLengthInBits() <= totalDataCount * 8):\r
+ return tn\r
+\r
+ inkex.errormsg("Even the largest size won't take this much data ("\r
+ + str(buffer.getLengthInBits())\r
+ + ">"\r
+ + str(totalDataCount * 8)\r
+ + ")")\r
+ sys.exit()\r
+ \r
+\r
+\r
+ @staticmethod\r
+ def createData(typeNumber, errorCorrectLevel, dataList):\r
+\r
+ rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectLevel)\r
+\r
+ buffer = QRBitBuffer();\r
+\r
+ for i in range(len(dataList)):\r
+ data = dataList[i]\r
+ buffer.put(data.mode, 4)\r
+ buffer.put(data.getLength(), QRUtil.getLengthInBits(data.mode, typeNumber) )\r
+ data.write(buffer)\r
+\r
+ #// calc num max data.\r
+ totalDataCount = 0;\r
+ for i in range(len(rsBlocks)):\r
+ totalDataCount += rsBlocks[i].dataCount\r
+\r
+ if (buffer.getLengthInBits() > totalDataCount * 8):\r
+ inkex.errormsg("Text is too long for this size ("\r
+ + str(buffer.getLengthInBits())\r
+ + ">"\r
+ + str(totalDataCount * 8)\r
+ + ")")\r
+ sys.exit()\r
+\r
+ #// end code\r
+ if (buffer.getLengthInBits() + 4 <= totalDataCount * 8):\r
+ buffer.put(0, 4)\r
+\r
+ #// padding\r
+ while (buffer.getLengthInBits() % 8 != 0):\r
+ buffer.putBit(False)\r
+\r
+ #// padding\r
+ while (True):\r
+\r
+ if (buffer.getLengthInBits() >= totalDataCount * 8):\r
+ break\r
+ buffer.put(QRCode.PAD0, 8)\r
+\r
+ if (buffer.getLengthInBits() >= totalDataCount * 8):\r
+ break\r
+ buffer.put(QRCode.PAD1, 8)\r
+\r
+ return QRCode.createBytes(buffer, rsBlocks)\r
+\r
+ @staticmethod\r
+ def createBytes(buffer, rsBlocks):\r
+\r
+ offset = 0\r
+\r
+ maxDcCount = 0\r
+ maxEcCount = 0\r
+\r
+ dcdata = [0 for x in range(len(rsBlocks))]\r
+ ecdata = [0 for x in range(len(rsBlocks))]\r
+\r
+ for r in range(len(rsBlocks)):\r
+\r
+ dcCount = rsBlocks[r].dataCount\r
+ ecCount = rsBlocks[r].totalCount - dcCount\r
+\r
+ maxDcCount = max(maxDcCount, dcCount)\r
+ maxEcCount = max(maxEcCount, ecCount)\r
+\r
+ dcdata[r] = [0 for x in range(dcCount)]\r
+\r
+ for i in range(len(dcdata[r])):\r
+ dcdata[r][i] = 0xff & buffer.buffer[i + offset]\r
+ offset += dcCount\r
+\r
+ rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount)\r
+ rawPoly = QRPolynomial(dcdata[r], rsPoly.getLength() - 1)\r
+\r
+ modPoly = rawPoly.mod(rsPoly)\r
+ ecdata[r] = [0 for x in range(rsPoly.getLength()-1)]\r
+ for i in range(len(ecdata[r])):\r
+ modIndex = i + modPoly.getLength() - len(ecdata[r])\r
+ if (modIndex >= 0):\r
+ ecdata[r][i] = modPoly.get(modIndex)\r
+ else:\r
+ ecdata[r][i] = 0\r
+\r
+ totalCodeCount = 0\r
+ for i in range(len(rsBlocks)):\r
+ totalCodeCount += rsBlocks[i].totalCount\r
+\r
+ data = [None for x in range(totalCodeCount)]\r
+ index = 0\r
+\r
+ for i in range(maxDcCount):\r
+ for r in range(len(rsBlocks)):\r
+ if (i < len(dcdata[r])):\r
+ data[index] = dcdata[r][i]\r
+ index+=1\r
+\r
+ for i in range(maxEcCount):\r
+ for r in range(len(rsBlocks)):\r
+ if (i < len(ecdata[r])):\r
+ data[index] = ecdata[r][i]\r
+ index+=1\r
+\r
+ return data\r
+\r
+\r
+class QRMode:\r
+ MODE_NUMBER = 1 << 0\r
+ MODE_ALPHA_NUM = 1 << 1\r
+ MODE_8BIT_BYTE = 1 << 2\r
+ MODE_KANJI = 1 << 3\r
+\r
+class QRErrorCorrectLevel:\r
+ L = 1\r
+ M = 0\r
+ Q = 3\r
+ H = 2\r
+\r
+class QRMaskPattern:\r
+ PATTERN000 = 0\r
+ PATTERN001 = 1\r
+ PATTERN010 = 2\r
+ PATTERN011 = 3\r
+ PATTERN100 = 4\r
+ PATTERN101 = 5\r
+ PATTERN110 = 6\r
+ PATTERN111 = 7\r
+\r
+class QRUtil(object):\r
+ PATTERN_POSITION_TABLE = [\r
+ [],\r
+ [6, 18],\r
+ [6, 22],\r
+ [6, 26],\r
+ [6, 30],\r
+ [6, 34],\r
+ [6, 22, 38],\r
+ [6, 24, 42],\r
+ [6, 26, 46],\r
+ [6, 28, 50],\r
+ [6, 30, 54],\r
+ [6, 32, 58],\r
+ [6, 34, 62],\r
+ [6, 26, 46, 66],\r
+ [6, 26, 48, 70],\r
+ [6, 26, 50, 74],\r
+ [6, 30, 54, 78],\r
+ [6, 30, 56, 82],\r
+ [6, 30, 58, 86],\r
+ [6, 34, 62, 90],\r
+ [6, 28, 50, 72, 94],\r
+ [6, 26, 50, 74, 98],\r
+ [6, 30, 54, 78, 102],\r
+ [6, 28, 54, 80, 106],\r
+ [6, 32, 58, 84, 110],\r
+ [6, 30, 58, 86, 114],\r
+ [6, 34, 62, 90, 118],\r
+ [6, 26, 50, 74, 98, 122],\r
+ [6, 30, 54, 78, 102, 126],\r
+ [6, 26, 52, 78, 104, 130],\r
+ [6, 30, 56, 82, 108, 134],\r
+ [6, 34, 60, 86, 112, 138],\r
+ [6, 30, 58, 86, 114, 142],\r
+ [6, 34, 62, 90, 118, 146],\r
+ [6, 30, 54, 78, 102, 126, 150],\r
+ [6, 24, 50, 76, 102, 128, 154],\r
+ [6, 28, 54, 80, 106, 132, 158],\r
+ [6, 32, 58, 84, 110, 136, 162],\r
+ [6, 26, 54, 82, 110, 138, 166],\r
+ [6, 30, 58, 86, 114, 142, 170]\r
+ ]\r
+\r
+ G15 = (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0)\r
+ G18 = (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0)\r
+ G15_MASK = (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1)\r
+\r
+ @staticmethod\r
+ def getBCHTypeInfo(data):\r
+ d = data << 10;\r
+ while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) >= 0):\r
+ d ^= (QRUtil.G15 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) ) )\r
+\r
+ return ( (data << 10) | d) ^ QRUtil.G15_MASK\r
+ @staticmethod\r
+ def getBCHTypeNumber(data):\r
+ d = data << 12;\r
+ while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) >= 0):\r
+ d ^= (QRUtil.G18 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) ) )\r
+ return (data << 12) | d\r
+ @staticmethod\r
+ def getBCHDigit(data):\r
+ digit = 0;\r
+ while (data != 0):\r
+ digit += 1\r
+ data >>= 1\r
+ return digit\r
+ @staticmethod\r
+ def getPatternPosition(typeNumber):\r
+ return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1]\r
+ @staticmethod\r
+ def getMask(maskPattern, i, j):\r
+ if maskPattern == QRMaskPattern.PATTERN000 : return (i + j) % 2 == 0\r
+ if maskPattern == QRMaskPattern.PATTERN001 : return i % 2 == 0\r
+ if maskPattern == QRMaskPattern.PATTERN010 : return j % 3 == 0\r
+ if maskPattern == QRMaskPattern.PATTERN011 : return (i + j) % 3 == 0\r
+ if maskPattern == QRMaskPattern.PATTERN100 : return (math.floor(i / 2) + math.floor(j / 3) ) % 2 == 0\r
+ if maskPattern == QRMaskPattern.PATTERN101 : return (i * j) % 2 + (i * j) % 3 == 0\r
+ if maskPattern == QRMaskPattern.PATTERN110 : return ( (i * j) % 2 + (i * j) % 3) % 2 == 0\r
+ if maskPattern == QRMaskPattern.PATTERN111 : return ( (i * j) % 3 + (i + j) % 2) % 2 == 0\r
+ raise Exception("bad maskPattern:" + maskPattern);\r
+ @staticmethod\r
+ def getErrorCorrectPolynomial(errorCorrectLength):\r
+ a = QRPolynomial([1], 0);\r
+ for i in range(errorCorrectLength):\r
+ a = a.multiply(QRPolynomial([1, QRMath.gexp(i)], 0) )\r
+ return a\r
+ @staticmethod\r
+ def getLengthInBits(mode, type):\r
+\r
+ if 1 <= type and type < 10:\r
+\r
+ #// 1 - 9\r
+\r
+ if mode == QRMode.MODE_NUMBER : return 10\r
+ if mode == QRMode.MODE_ALPHA_NUM : return 9\r
+ if mode == QRMode.MODE_8BIT_BYTE : return 8\r
+ if mode == QRMode.MODE_KANJI : return 8\r
+ raise Exception("mode:" + mode)\r
+\r
+ elif (type < 27):\r
+\r
+ #// 10 - 26\r
+\r
+ if mode == QRMode.MODE_NUMBER : return 12\r
+ if mode == QRMode.MODE_ALPHA_NUM : return 11\r
+ if mode == QRMode.MODE_8BIT_BYTE : return 16\r
+ if mode == QRMode.MODE_KANJI : return 10\r
+ raise Exception("mode:" + mode)\r
+\r
+ elif (type < 41):\r
+\r
+ #// 27 - 40\r
+\r
+ if mode == QRMode.MODE_NUMBER : return 14\r
+ if mode == QRMode.MODE_ALPHA_NUM : return 13\r
+ if mode == QRMode.MODE_8BIT_BYTE : return 16\r
+ if mode == QRMode.MODE_KANJI : return 12\r
+ raise Exception("mode:" + mode)\r
+\r
+ else:\r
+ raise Exception("type:" + type)\r
+ @staticmethod\r
+ def getLostPoint(qrCode):\r
+\r
+ moduleCount = qrCode.getModuleCount();\r
+\r
+ lostPoint = 0;\r
+\r
+ #// LEVEL1\r
+\r
+ for row in range(moduleCount):\r
+\r
+ for col in range(moduleCount):\r
+\r
+ sameCount = 0;\r
+ dark = qrCode.isDark(row, col);\r
+\r
+ for r in range(-1, 2):\r
+\r
+ if (row + r < 0 or moduleCount <= row + r):\r
+ continue\r
+\r
+ for c in range(-1, 2):\r
+\r
+ if (col + c < 0 or moduleCount <= col + c):\r
+ continue\r
+ if (r == 0 and c == 0):\r
+ continue\r
+\r
+ if (dark == qrCode.isDark(row + r, col + c) ):\r
+ sameCount+=1\r
+ if (sameCount > 5):\r
+ lostPoint += (3 + sameCount - 5)\r
+\r
+ #// LEVEL2\r
+\r
+ for row in range(moduleCount - 1):\r
+ for col in range(moduleCount - 1):\r
+ count = 0;\r
+ if (qrCode.isDark(row, col ) ): count+=1\r
+ if (qrCode.isDark(row + 1, col ) ): count+=1\r
+ if (qrCode.isDark(row, col + 1) ): count+=1\r
+ if (qrCode.isDark(row + 1, col + 1) ): count+=1\r
+ if (count == 0 or count == 4):\r
+ lostPoint += 3\r
+\r
+ #// LEVEL3\r
+\r
+ for row in range(moduleCount):\r
+ for col in range(moduleCount - 6):\r
+ if (qrCode.isDark(row, col)\r
+ and not qrCode.isDark(row, col + 1)\r
+ and qrCode.isDark(row, col + 2)\r
+ and qrCode.isDark(row, col + 3)\r
+ and qrCode.isDark(row, col + 4)\r
+ and not qrCode.isDark(row, col + 5)\r
+ and qrCode.isDark(row, col + 6) ):\r
+ lostPoint += 40\r
+\r
+ for col in range(moduleCount):\r
+ for row in range(moduleCount - 6):\r
+ if (qrCode.isDark(row, col)\r
+ and not qrCode.isDark(row + 1, col)\r
+ and qrCode.isDark(row + 2, col)\r
+ and qrCode.isDark(row + 3, col)\r
+ and qrCode.isDark(row + 4, col)\r
+ and not qrCode.isDark(row + 5, col)\r
+ and qrCode.isDark(row + 6, col) ):\r
+ lostPoint += 40\r
+\r
+ #// LEVEL4\r
+\r
+ darkCount = 0;\r
+\r
+ for col in range(moduleCount):\r
+ for row in range(moduleCount):\r
+ if (qrCode.isDark(row, col) ):\r
+ darkCount+=1\r
+\r
+ ratio = abs(100 * darkCount / moduleCount / moduleCount - 50) / 5\r
+ lostPoint += ratio * 10\r
+\r
+ return lostPoint\r
+\r
+class QRMath:\r
+\r
+ @staticmethod\r
+ def glog(n):\r
+ if (n < 1):\r
+ raise Exception("glog(" + n + ")")\r
+ return LOG_TABLE[n];\r
+ @staticmethod\r
+ def gexp(n):\r
+ while n < 0:\r
+ n += 255\r
+ while n >= 256:\r
+ n -= 255\r
+ return EXP_TABLE[n];\r
+\r
+EXP_TABLE = [x for x in range(256)]\r
+\r
+LOG_TABLE = [x for x in range(256)]\r
+\r
+for i in range(8):\r
+ EXP_TABLE[i] = 1 << i;\r
+\r
+for i in range(8, 256):\r
+ EXP_TABLE[i] = EXP_TABLE[i - 4] ^ EXP_TABLE[i - 5] ^ EXP_TABLE[i - 6] ^ EXP_TABLE[i - 8]\r
+\r
+for i in range(255):\r
+ LOG_TABLE[EXP_TABLE[i] ] = i\r
+\r
+class QRPolynomial:\r
+\r
+ def __init__(self, num, shift):\r
+\r
+ if (len(num) == 0):\r
+ raise Exception(num.length + "/" + shift)\r
+\r
+ offset = 0\r
+\r
+ while offset < len(num) and num[offset] == 0:\r
+ offset += 1\r
+\r
+ self.num = [0 for x in range(len(num)-offset+shift)]\r
+ for i in range(len(num) - offset):\r
+ self.num[i] = num[i + offset]\r
+\r
+\r
+ def get(self, index):\r
+ return self.num[index]\r
+ def getLength(self):\r
+ return len(self.num)\r
+ def multiply(self, e):\r
+ num = [0 for x in range(self.getLength() + e.getLength() - 1)];\r
+\r
+ for i in range(self.getLength()):\r
+ for j in range(e.getLength()):\r
+ num[i + j] ^= QRMath.gexp(QRMath.glog(self.get(i) ) + QRMath.glog(e.get(j) ) )\r
+\r
+ return QRPolynomial(num, 0);\r
+ def mod(self, e):\r
+\r
+ if (self.getLength() - e.getLength() < 0):\r
+ return self;\r
+\r
+ ratio = QRMath.glog(self.get(0) ) - QRMath.glog(e.get(0) )\r
+\r
+ num = [0 for x in range(self.getLength())]\r
+\r
+ for i in range(self.getLength()):\r
+ num[i] = self.get(i);\r
+\r
+ for i in range(e.getLength()):\r
+ num[i] ^= QRMath.gexp(QRMath.glog(e.get(i) ) + ratio)\r
+\r
+ # recursive call\r
+ return QRPolynomial(num, 0).mod(e);\r
+\r
+class QRRSBlock:\r
+\r
+ RS_BLOCK_TABLE = [\r
+\r
+ #// L\r
+ #// M\r
+ #// Q\r
+ #// H\r
+\r
+ #// 1\r
+ [1, 26, 19],\r
+ [1, 26, 16],\r
+ [1, 26, 13],\r
+ [1, 26, 9],\r
+\r
+ #// 2\r
+ [1, 44, 34],\r
+ [1, 44, 28],\r
+ [1, 44, 22],\r
+ [1, 44, 16],\r
+\r
+ #// 3\r
+ [1, 70, 55],\r
+ [1, 70, 44],\r
+ [2, 35, 17],\r
+ [2, 35, 13],\r
+\r
+ #// 4\r
+ [1, 100, 80],\r
+ [2, 50, 32],\r
+ [2, 50, 24],\r
+ [4, 25, 9],\r
+\r
+ #// 5\r
+ [1, 134, 108],\r
+ [2, 67, 43],\r
+ [2, 33, 15, 2, 34, 16],\r
+ [2, 33, 11, 2, 34, 12],\r
+\r
+ #// 6\r
+ [2, 86, 68],\r
+ [4, 43, 27],\r
+ [4, 43, 19],\r
+ [4, 43, 15],\r
+\r
+ #// 7\r
+ [2, 98, 78],\r
+ [4, 49, 31],\r
+ [2, 32, 14, 4, 33, 15],\r
+ [4, 39, 13, 1, 40, 14],\r
+\r
+ #// 8\r
+ [2, 121, 97],\r
+ [2, 60, 38, 2, 61, 39],\r
+ [4, 40, 18, 2, 41, 19],\r
+ [4, 40, 14, 2, 41, 15],\r
+\r
+ #// 9\r
+ [2, 146, 116],\r
+ [3, 58, 36, 2, 59, 37],\r
+ [4, 36, 16, 4, 37, 17],\r
+ [4, 36, 12, 4, 37, 13],\r
+\r
+ #// 10\r
+ [2, 86, 68, 2, 87, 69],\r
+ [4, 69, 43, 1, 70, 44],\r
+ [6, 43, 19, 2, 44, 20],\r
+ [6, 43, 15, 2, 44, 16],\r
+\r
+ # 11\r
+ [4, 101, 81],\r
+ [1, 80, 50, 4, 81, 51],\r
+ [4, 50, 22, 4, 51, 23],\r
+ [3, 36, 12, 8, 37, 13],\r
+\r
+ # 12\r
+ [2, 116, 92, 2, 117, 93],\r
+ [6, 58, 36, 2, 59, 37],\r
+ [4, 46, 20, 6, 47, 21],\r
+ [7, 42, 14, 4, 43, 15],\r
+\r
+ # 13\r
+ [4, 133, 107],\r
+ [8, 59, 37, 1, 60, 38],\r
+ [8, 44, 20, 4, 45, 21],\r
+ [12, 33, 11, 4, 34, 12],\r
+\r
+ # 14\r
+ [3, 145, 115, 1, 146, 116],\r
+ [4, 64, 40, 5, 65, 41],\r
+ [11, 36, 16, 5, 37, 17],\r
+ [11, 36, 12, 5, 37, 13],\r
+\r
+ # 15\r
+ [5, 109, 87, 1, 110, 88],\r
+ [5, 65, 41, 5, 66, 42],\r
+ [5, 54, 24, 7, 55, 25],\r
+ [11, 36, 12],\r
+\r
+ # 16\r
+ [5, 122, 98, 1, 123, 99],\r
+ [7, 73, 45, 3, 74, 46],\r
+ [15, 43, 19, 2, 44, 20],\r
+ [3, 45, 15, 13, 46, 16],\r
+\r
+ # 17\r
+ [1, 135, 107, 5, 136, 108],\r
+ [10, 74, 46, 1, 75, 47],\r
+ [1, 50, 22, 15, 51, 23],\r
+ [2, 42, 14, 17, 43, 15],\r
+\r
+ # 18\r
+ [5, 150, 120, 1, 151, 121],\r
+ [9, 69, 43, 4, 70, 44],\r
+ [17, 50, 22, 1, 51, 23],\r
+ [2, 42, 14, 19, 43, 15],\r
+\r
+ # 19\r
+ [3, 141, 113, 4, 142, 114],\r
+ [3, 70, 44, 11, 71, 45],\r
+ [17, 47, 21, 4, 48, 22],\r
+ [9, 39, 13, 16, 40, 14],\r
+\r
+ # 20\r
+ [3, 135, 107, 5, 136, 108],\r
+ [3, 67, 41, 13, 68, 42],\r
+ [15, 54, 24, 5, 55, 25],\r
+ [15, 43, 15, 10, 44, 16],\r
+\r
+ # 21\r
+ [4, 144, 116, 4, 145, 117],\r
+ [17, 68, 42],\r
+ [17, 50, 22, 6, 51, 23],\r
+ [19, 46, 16, 6, 47, 17],\r
+\r
+ # 22\r
+ [2, 139, 111, 7, 140, 112],\r
+ [17, 74, 46],\r
+ [7, 54, 24, 16, 55, 25],\r
+ [34, 37, 13],\r
+\r
+ # 23\r
+ [4, 151, 121, 5, 152, 122],\r
+ [4, 75, 47, 14, 76, 48],\r
+ [11, 54, 24, 14, 55, 25],\r
+ [16, 45, 15, 14, 46, 16],\r
+\r
+ # 24\r
+ [6, 147, 117, 4, 148, 118],\r
+ [6, 73, 45, 14, 74, 46],\r
+ [11, 54, 24, 16, 55, 25],\r
+ [30, 46, 16, 2, 47, 17],\r
+\r
+ # 25\r
+ [8, 132, 106, 4, 133, 107],\r
+ [8, 75, 47, 13, 76, 48],\r
+ [7, 54, 24, 22, 55, 25],\r
+ [22, 45, 15, 13, 46, 16],\r
+\r
+ # 26\r
+ [10, 142, 114, 2, 143, 115],\r
+ [19, 74, 46, 4, 75, 47],\r
+ [28, 50, 22, 6, 51, 23],\r
+ [33, 46, 16, 4, 47, 17],\r
+\r
+ # 27\r
+ [8, 152, 122, 4, 153, 123],\r
+ [22, 73, 45, 3, 74, 46],\r
+ [8, 53, 23, 26, 54, 24],\r
+ [12, 45, 15, 28, 46, 16],\r
+\r
+ # 28\r
+ [3, 147, 117, 10, 148, 118],\r
+ [3, 73, 45, 23, 74, 46],\r
+ [4, 54, 24, 31, 55, 25],\r
+ [11, 45, 15, 31, 46, 16],\r
+\r
+ # 29\r
+ [7, 146, 116, 7, 147, 117],\r
+ [21, 73, 45, 7, 74, 46],\r
+ [1, 53, 23, 37, 54, 24],\r
+ [19, 45, 15, 26, 46, 16],\r
+\r
+ # 30\r
+ [5, 145, 115, 10, 146, 116],\r
+ [19, 75, 47, 10, 76, 48],\r
+ [15, 54, 24, 25, 55, 25],\r
+ [23, 45, 15, 25, 46, 16],\r
+\r
+ # 31\r
+ [13, 145, 115, 3, 146, 116],\r
+ [2, 74, 46, 29, 75, 47],\r
+ [42, 54, 24, 1, 55, 25],\r
+ [23, 45, 15, 28, 46, 16],\r
+\r
+ # 32\r
+ [17, 145, 115],\r
+ [10, 74, 46, 23, 75, 47],\r
+ [10, 54, 24, 35, 55, 25],\r
+ [19, 45, 15, 35, 46, 16],\r
+\r
+ # 33\r
+ [17, 145, 115, 1, 146, 116],\r
+ [14, 74, 46, 21, 75, 47],\r
+ [29, 54, 24, 19, 55, 25],\r
+ [11, 45, 15, 46, 46, 16],\r
+\r
+ # 34\r
+ [13, 145, 115, 6, 146, 116],\r
+ [14, 74, 46, 23, 75, 47],\r
+ [44, 54, 24, 7, 55, 25],\r
+ [59, 46, 16, 1, 47, 17],\r
+\r
+ # 35\r
+ [12, 151, 121, 7, 152, 122],\r
+ [12, 75, 47, 26, 76, 48],\r
+ [39, 54, 24, 14, 55, 25],\r
+ [22, 45, 15, 41, 46, 16],\r
+\r
+ # 36\r
+ [6, 151, 121, 14, 152, 122],\r
+ [6, 75, 47, 34, 76, 48],\r
+ [46, 54, 24, 10, 55, 25],\r
+ [2, 45, 15, 64, 46, 16],\r
+\r
+ # 37\r
+ [17, 152, 122, 4, 153, 123],\r
+ [29, 74, 46, 14, 75, 47],\r
+ [49, 54, 24, 10, 55, 25],\r
+ [24, 45, 15, 46, 46, 16],\r
+\r
+ # 38\r
+ [4, 152, 122, 18, 153, 123],\r
+ [13, 74, 46, 32, 75, 47],\r
+ [48, 54, 24, 14, 55, 25],\r
+ [42, 45, 15, 32, 46, 16],\r
+\r
+ # 39\r
+ [20, 147, 117, 4, 148, 118],\r
+ [40, 75, 47, 7, 76, 48],\r
+ [43, 54, 24, 22, 55, 25],\r
+ [10, 45, 15, 67, 46, 16],\r
+\r
+ # 40\r
+ [19, 148, 118, 6, 149, 119],\r
+ [18, 75, 47, 31, 76, 48],\r
+ [34, 54, 24, 34, 55, 25],\r
+ [20, 45, 15, 61, 46, 16]\r
+\r
+ ]\r
+\r
+ def __init__(self, totalCount, dataCount):\r
+ self.totalCount = totalCount\r
+ self.dataCount = dataCount\r
+\r
+ @staticmethod\r
+ def getRSBlocks(typeNumber, errorCorrectLevel):\r
+ rsBlock = QRRSBlock.getRsBlockTable(typeNumber, errorCorrectLevel);\r
+ if rsBlock == None:\r
+ raise Exception("bad rs block @ typeNumber:" + typeNumber + "/errorCorrectLevel:" + errorCorrectLevel)\r
+\r
+ length = len(rsBlock) / 3\r
+\r
+ list = []\r
+\r
+ for i in range(length):\r
+\r
+ count = rsBlock[i * 3 + 0]\r
+ totalCount = rsBlock[i * 3 + 1]\r
+ dataCount = rsBlock[i * 3 + 2]\r
+\r
+ for j in range(count):\r
+ list.append(QRRSBlock(totalCount, dataCount))\r
+\r
+ return list;\r
+\r
+ @staticmethod\r
+ def getRsBlockTable(typeNumber, errorCorrectLevel):\r
+ if errorCorrectLevel == QRErrorCorrectLevel.L:\r
+ return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0];\r
+ elif errorCorrectLevel == QRErrorCorrectLevel.M:\r
+ return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1];\r
+ elif errorCorrectLevel == QRErrorCorrectLevel.Q:\r
+ return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2];\r
+ elif errorCorrectLevel == QRErrorCorrectLevel.H:\r
+ return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3];\r
+ else:\r
+ return None;\r
+\r
+class QRBitBuffer:\r
+ def __init__(self):\r
+ self.buffer = []\r
+ self.length = 0\r
+ def __repr__(self):\r
+ return ".".join([str(n) for n in self.buffer])\r
+ def get(self, index):\r
+ bufIndex = math.floor(index / 8)\r
+ val = ( (self.buffer[bufIndex] >> (7 - index % 8) ) & 1) == 1\r
+ print "get ", val\r
+ return ( (self.buffer[bufIndex] >> (7 - index % 8) ) & 1) == 1\r
+ def put(self, num, length):\r
+ for i in range(length):\r
+ self.putBit( ( (num >> (length - i - 1) ) & 1) == 1)\r
+ def getLengthInBits(self):\r
+ return self.length\r
+ def putBit(self, bit):\r
+ bufIndex = self.length // 8\r
+ if len(self.buffer) <= bufIndex:\r
+ self.buffer.append(0)\r
+ if bit:\r
+ self.buffer[bufIndex] |= (0x80 >> (self.length % 8) )\r
+ self.length+=1\r
+\r
+class QRCodeInkscape(inkex.Effect):\r
+ def __init__(self):\r
+ inkex.Effect.__init__(self)\r
+ \r
+ #PARSE OPTIONS\r
+ self.OptionParser.add_option("--text",\r
+ action="store", type="string",\r
+ dest="TEXT", default='www.inkscape.org')\r
+ self.OptionParser.add_option("--typenumber",\r
+ action="store", type="string",\r
+ dest="TYPENUMBER", default="0")\r
+ self.OptionParser.add_option("--correctionlevel",\r
+ action="store", type="string",\r
+ dest="CORRECTIONLEVEL", default="0")\r
+ self.OptionParser.add_option("--modulesize",\r
+ action="store", type="float",\r
+ dest="MODULESIZE", default=10)\r
+ \r
+ def effect(self):\r
+ \r
+ so = self.options\r
+ \r
+ if so.TEXT == '': #abort if converting blank text\r
+ inkex.errormsg(_('Please enter an input text'))\r
+ else:\r
+ \r
+ #INKSCAPE GROUP TO CONTAIN EVERYTHING\r
+ \r
+ centre = self.view_center #Put in in the centre of the current view\r
+ grp_transform = 'translate' + str( centre )\r
+ grp_name = 'QRCode'\r
+ grp_attribs = {inkex.addNS('label','inkscape'):grp_name,\r
+ 'transform':grp_transform }\r
+ grp = inkex.etree.SubElement(self.current_layer, 'g', grp_attribs) #the group to put everything in\r
+ \r
+ #GENERATE THE QRCODE\r
+ qr = QRCode(int(so.TYPENUMBER), int(so.CORRECTIONLEVEL))\r
+ qr.addData(so.TEXT)\r
+ qr.make()\r
+ qr.makeSVG(grp, so.MODULESIZE)\r
+ \r
+if __name__ == '__main__':\r
+ e = QRCodeInkscape()\r
+ e.affect()\r
+\r
+# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 encoding=utf-8 textwidth=99\r