Home‎ > ‎

パッチ情報

ReportLab 2.3 用パッチ

humanReadable を付けると AttributeError: decode になる

C++が好き で書かれているように、次のパッチを graphics/barcode/common.py にあてる。

reportlab/graphics/barcode/common.py:
--- common.py.orig    2009-02-04 22:18:32.000000000 +0900
+++ common.py    2010-04-09 11:02:21.566737300 +0900
@@ -173,7 +173,7 @@
         if anchor=='middle': func = 'drawCentredString'
         elif anchor=='end': func = 'drawRightString'
         else: func = 'drawString'
-        getattr(canv,func)(text,x,y)
+        getattr(canv,func)(x,y,text)
         canv.restoreState()
 
 class MultiWidthBarcode(Barcode):


pisa 3.0.29-33 用パッチ

このパッチは、pisa の後継プロジェクトである xhtml2pdf (Chris Glass 氏版) に採用されました。xhtml2pdf 0.0.3 を利用する場合、JAN (EAN) バーコードの見た目の改善を除き、以下でサポートされる多様なバーコードを出力できます。

バーコード出力を使えるようにする

そのままでは Code39 の固定サイズしか出力できないので、次のとおりパッチをあてる。
※以下は diff -u --ignore-space した結果なので、パッチをあてる前に 全行末空白を削除する必要がある。
※$PISADIR/sx/pisa3/pisa_context.pyここ のパッチをあてた
状態を想定しているため、バーコードのヒューマンリーダブルエリア(目視領域)には OCRB フォントを使用している。

sx/pisa3/pisa_default.py:
--- pisa_default.py.orig    2010-06-23 16:17:08.714447100 +0900
+++ pisa_default.py    2010-06-23 16:17:19.806422100 +0900
@@ -176,7 +176,22 @@
 
     "pdfbarcode": (0, {
         "value":                (STRING, MUST),
-        "align":                (["left", "center", "right"], "left"),
+        "type":                 (["i2of5", "itf",
+                                  "code39", "extendedcode39",
+                                  "code93", "extendedcode93",
+                                  "msi",
+                                  "codabar", "nw7",
+                                  "code11",
+                                  "fim",
+                                  "postnet",
+                                  "usps4s",
+                                  "code128",
+                                  "ean13", "ean8",
+                                 ], "code128"),
+        "humanreadable":        (STRING, ""),
+        "barwidth":             SIZE,
+        "barheight":            SIZE,
+        "align":                (["baseline", "top", "middle", "bottom"], "baseline"),
         }),
 
     # ========================================================


sx/pisa3/pisa_tags.py:
--- pisa_tags.py.orig    2010-06-23 16:18:39.496794600 +0900
+++ pisa_tags.py    2010-06-23 17:58:40.829398300 +0900
@@ -12,7 +12,8 @@
 from pisa_reportlab import *
 from pisa_util import *
 
-from reportlab.graphics.barcode.code39 import Standard39
+from reportlab.graphics.barcode import createBarcodeDrawing
+
 from reportlab.lib.styles import ParagraphStyle
 from reportlab.platypus.flowables import *
 from reportlab.platypus.paraparser import tt2ps, ABag
@@ -575,17 +576,95 @@
         c.loadFont(self.attr.name, self.attr.src, self.attr.encoding)
 
 class pisaTagPDFBARCODE(pisaTag):
-    """
-    <pdf:barcode value="" align="">
-    """
+
+    _codeName = {
+            "I2OF5": "I2of5",
+            "ITF": "I2of5",
+            "CODE39": "Standard39",
+            "EXTENDEDCODE39": "Extended39",
+            "CODE93": "Standard93",
+            "EXTENDEDCODE93": "Extended93",
+            "MSI": "MSI",
+            "CODABAR": "Codabar",
+            "NW7": "Codabar",
+            "CODE11": "Code11",
+            "FIM": "FIM",
+            "POSTNET": "POSTNET",
+            "USPS4S": "USPS_4State",
+            "CODE128": "Code128",
+            "EAN13": "EAN13",
+            "EAN8": "EAN8",
+            }
+
+    class _barcodeWrapper(Flowable):
+        """Wrapper for barcode widget
+        """
+        def __init__(self, codeName="Code128", value="", **kw):
+            self.widget = createBarcodeDrawing(codeName, value=value, **kw)
+
+        def draw(self, canvas, xoffset=0, **kw):
+            # NOTE: `canvas' is mutable, so canvas.restoreState() is a MUST.
+            canvas.saveState()
+            canvas.translate(xoffset, 0)
+            self.widget.canv = canvas
+            self.widget.draw()
+            canvas.restoreState()
+
+        def wrap(self, aW, aH):
+            return self.widget.wrap(aW, aH)
+
     def start(self, c):
-        c.addPara()
         attr = self.attr
-        bc = Standard39()
-        bc.value = attr.value
-        bc.barHeight = 0.5 * inch
-        bc.lquiet = 0 # left padding
-        bc.rquiet = 0 # left padding
-        bc.hAlign = attr.align.upper()
-        c.addStory(bc)
-        c.addPara()
+        codeName = attr.type or "Code128"
+        codeName = pisaTagPDFBARCODE._codeName[codeName.upper().replace("-", "")]
+        humanReadable = bool(attr.humanreadable)
+        barWidth = attr.barwidth or 0.01*inch
+        barHeight = attr.barheight or 0.5*inch
+        fontName = c.getFontName("OCRB10,OCR-B,OCR B,OCRB")  # or "Helvetica"
+        fontSize = 2.75*mm
+
+        # Assure minimal size.
+        if codeName in ("EAN13", "EAN8"):
+            barWidth = max(barWidth, 0.264*mm)
+            fontSize = max(fontSize, 2.75*mm)
+        else: # Code39 etc.
+            barWidth = max(barWidth, 0.0075*inch)
+        #barHeight = max(barHeight, 25.93*mm)
+
+        barcode = pisaTagPDFBARCODE._barcodeWrapper(
+                codeName=codeName,
+                value=attr.value,
+                barWidth=barWidth,
+                barHeight=barHeight,
+                humanReadable=humanReadable,
+                fontName=fontName,
+                fontSize=fontSize,
+                )
+
+        width, height = barcode.wrap(c.frag.width, c.frag.height)
+
+        #barcode.spaceBefore = c.frag.spaceBefore
+        #barcode.spaceAfter = c.frag.spaceAfter
+
+        c.force = True
+
+        valign = attr.align or c.frag.vAlign or "baseline"
+        if valign in ["texttop"]:
+            valign = "top"
+        elif valign in ["absmiddle"]:
+            valign = "middle"
+        elif valign in ["absbottom", "baseline"]:
+            valign = "bottom"
+
+        afrag = c.frag.clone()
+        afrag.text = ""
+        afrag.fontName = fontName
+        afrag.cbDefn = ABag(
+            kind="barcode",
+            barcode=barcode,
+            width=width,
+            height=height,
+            valign=valign,
+            )
+        c.fragList.append(afrag)
+


sx/pisa3/reportlab_paragraph.py:
--- reportlab_paragraph.py.orig    2010-06-23 16:20:27.104574600 +0900
+++ reportlab_paragraph.py    2010-06-23 16:21:04.770422100 +0900
@@ -218,6 +218,19 @@
                 cur_x += w
                 cur_x_s += w
                 setXPos(tx,cur_x_s-tx._x0)
+            elif kind=='barcode':
+                barcode = cbDefn.barcode
+                w = cbDefn.width
+                h = cbDefn.height
+                txfs = tx._fontsize
+                if txfs is None:
+                    txfs = xs.style.fontSize
+                iy0, iy1 = imgVRange(h, cbDefn.valign, txfs)
+                cur_x_s = cur_x + nSpaces*ws
+                barcode.draw(canvas=tx._canvas, xoffset=cur_x_s)
+                cur_x += w
+                cur_x_s += w
+                setXPos(tx, cur_x_s-tx._x0)
             else:
                 name = cbDefn.name
                 if kind=='anchor':

ついでに、ReportLab 本体にほんの少しだけ手を加えて JAN バーコードを見慣れた形にします。JAN バーコードでは標準の場合3か所のバーが長くなっていますが、長すぎるので文字高の1/2だけ縮めます。
※以下は pisa の変更ではなく ReportLab の変更であるため、 xhtml2pdf (Chris Glass 氏版) では採用されていないようです。また、バーが長すぎることはバグではありません。

reportlab/graphics/barcode/eanbc.py:
--- eanbc.py.orig       2009-02-04 22:18:00.000000000 +0900
+++ eanbc.py    2010-06-23 17:48:48.354204200 +0900
@@ -250,7 +250,7 @@
         lrect = None
         for i,c in enumerate(b):
             if c=="1":
-                dh = self._short_bar(i) and fth or 0
+                dh = self._short_bar(i) and fth or fth/2
                 yh = y+dh
                 if lrect and lrect.y==yh:
                     lrect.width += barWidth


ċ
common.patch
(0k)
Hideki HAYASI,
2010/06/18 3:28
ċ
eanbc.py.diff
(0k)
Hideki HAYASI,
2010/06/23 2:25
ċ
pisa_default.py.diff
(1k)
Hideki HAYASI,
2010/06/23 0:23
ċ
pisa_tags.py.diff
(4k)
Hideki HAYASI,
2010/06/28 7:17
ċ
reportlab_paragraph.py.diff
(1k)
Hideki HAYASI,
2010/06/23 2:03
Comments