Erster Commit: nativer Linux-Port aus macOS-Bytecode

Läuft die Voice Acoustic VA-Remotecontrol (AllDSP AllControl) nativ unter Linux
auf echtem wxGTK 3.0 — ohne Wine und ohne dekompilierten App-Code. Ausgeführt wird
das unveränderte Python-2.7-Bytecode aus dem macOS-.app; C-Extensions (wxGTK/numpy/
scipy/PortAudio) kommen nativ aus Debian stretch.

Enthält: va/ (Original-.pyc + pure-Python-Libs + Assets + launch.py mit den drei
Linux-Fixes), Dockerfile/run.sh/entrypoint.sh, reference/ (dekompilierter Quellcode
zum Debuggen) und README/STATUS. img.cache (378 MB, regenerierbar) ist per
.gitignore ausgeschlossen.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
maik
2026-08-20 19:57:01 +02:00
co-authored by Claude Opus 4.8
commit a7c93fa266
654 changed files with 478133 additions and 0 deletions
@@ -0,0 +1,13 @@
English: Hello World
Greek: Γειά σου κόσμος
Polish: Witaj świecie
Portuguese: Olá mundo
Russian: Здравствуй, Мир
Vietnamese: Xin chào thế giới
Arabic: مرحبا العالم
Hebrew: שלום עולם
Hindi: नमस्ते दुनिया
Chinese: 你好世界
Japanese: こんにちは世界
Korean: 안녕하세요
Thai: สวัสดีชาวโลก
@@ -0,0 +1,47 @@
"Print all charters"
from fpdf import FPDF, FPDF_VERSION, TTFontFile
print FPDF_VERSION
class MyTTFontFile(TTFontFile):
def getCMAP4(self, unicode_cmap_offset, glyphToChar, charToGlyph):
TTFontFile.getCMAP4(self, unicode_cmap_offset, glyphToChar, charToGlyph)
self.saveChar = charToGlyph
def getCMAP12(self, unicode_cmap_offset, glyphToChar, charToGlyph):
TTFontFile.getCMAP12(self, unicode_cmap_offset, glyphToChar, charToGlyph)
self.saveChar = charToGlyph
pdf=FPDF()
pdf.compression = True
pdf.add_page()
fontpath = "DroidSansFallback.ttf"
pdf.add_font("font", '', fontpath, uni = True)
ttf = MyTTFontFile()
ttf.getMetrics(fontpath)
pdf.set_font("font", '', 10)
# create PDF with first 999 charters in font
cnt = 0
for char in ttf.saveChar:
cnt += 1
pdf.write(8, u"%03d) %06x - " % (cnt, char) + unichr(char))
pdf.ln()
if cnt >= 999:
break
fn = 'charmap.pdf'
pdf.output(fn,'F')
import os
try:
os.startfile(fn)
except:
os.system("xdg-open \"%s\"" % fn)
@@ -0,0 +1,6 @@
# -*- coding: utf-8 -*-
from .common import *
@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
# Test environment
import common
def main():
common.log("CHECK")
try:
from fpdf import FPDF_VERSION
except ImportError:
FPDF_VERSION = None
common.log("VER =", FPDF_VERSION)
try:
try:
import Image
except:
from PIL import Image
except ImportError:
Image = None
if Image:
common.log("PIL = yes")
else:
common.log("PIL = no")
if __name__ == "__main__":
main()
@@ -0,0 +1,284 @@
# -*- coding: utf-8 -*-
# common utilities for pyfpdf tests
# Note: 1) this file imported from both 2 and 3 version of python
# 2) import this file before import fpdf
# 3) assert this file in tests/cover folder
import sys, os, subprocess
PY3K = sys.version_info >= (3, 0)
basepath = os.path.abspath(os.path.join(__file__, "..", ".."))
RESHASH = "38db8db76e80a2e75f94d1df9eda307e"
# if PYFPDFTESTLOCAL is not set - use instaled pyfpdf version
PYFPDFTESTLOCAL = ("PYFPDFTESTLOCAL" in os.environ)
if PYFPDFTESTLOCAL:
sys.path = [os.path.join(basepath, "fpdf_local")] + sys.path
if PY3K:
#import common3 as _common
def tobytes(value):
return value.encode("latin1")
def frombytes(value):
return value.decode("latin1")
from hashlib import md5
unicode = str
else:
#import common2 as _common
def tobytes(value):
return value
def frombytes(value):
return value
try:
from hashlib import md5
except ImportError:
import md5
def exec_cmd(cmd):
"Execute command and return console output (stdout, stderr)"
obj = subprocess.Popen(cmd, \
stdout = subprocess.PIPE,
stderr = subprocess.PIPE)
std, err = obj.communicate()
return (frombytes(std), frombytes(err))
def start_by_ext(fn):
"Open file in associated progrom"
try:
try:
os.startfile(fn)
except WindowsError:
os.system("start " + fn)
except:
subprocess.call(["xdg-open", fn])
def writer(stream, items):
sep = ""
for item in items:
stream.write(sep)
sep = " "
if not isinstance(item, str):
item = str(item)
if not PY3K:
if not isinstance(item, unicode):
item = str(item)
stream.write(item)
stream.write("\n")
def log(*kw):
writer(sys.stdout, kw)
def err(*kw):
writer(sys.stderr, kw)
def test_putinfo(self):
"Replace info stamp with defaults for all automated test objects"
self._out('/Producer '+self._textstring('PyFPDF TEST http://pyfpdf.googlecode.com/'))
if hasattr(self,'title'):
self._out('/Title '+self._textstring(self.title))
if hasattr(self,'subject'):
self._out('/Subject '+self._textstring(self.subject))
if hasattr(self,'author'):
self._out('/Author '+self._textstring(self.author))
if hasattr (self,'keywords'):
self._out('/Keywords '+self._textstring(self.keywords))
if hasattr(self,'creator'):
self._out('/Creator '+self._textstring(self.creator))
self._out('/CreationDate '+self._textstring('D:19700101000000'))
def file_hash(fn):
"Calc MD5 hash for file"
md = md5()
f = open(fn, "rb")
try:
md.update(f.read())
finally:
f.close()
return md.hexdigest()
def read_cover_info(fn):
"Read cover test info"
f = open(fn, "rb")
da = {"res": []}
mark = "#PyFPDF-cover-test:"
encmark = "# -*- coding:"
enc = None
try:
hdr = False
for line in f.readlines():
if enc is None:
if line.decode("latin-1")[:len(encmark)] == unicode(encmark):
enc = line.decode("latin-1")[len(encmark):].strip()
if enc[-3:] == unicode("-*-"):
enc = enc[:-3].strip()
try:
line.decode(enc)
except:
enc = None
line = line.decode(enc or "UTF-8").strip()
if line[:len(mark)] == mark:
hdr = True
kv = line[len(mark):].split("=", 1)
if len(kv) == 2:
if kv[0] == "res":
da["res"].append(kv[1])
else:
da[kv[0]] = kv[1]
else:
if hdr and len(line) == 0:
break
finally:
f.close()
return da
def parse_test_args(args, deffn):
"Parse test args, return (fn, autotest)"
args = args[1:]
da = {}
da["fn"] = deffn
da["autotest"] = False
da["check"] = False
while len(args) > 0:
arg = args[0]
if arg == "--help":
log("Test usage: [--auto] [--check] [<outputname>]")
log(" --auto - no version and timestamp in file, do not open")
log(" --check - compare new file with stock")
log(" <outputname> - output filename, default \"%s\"" % deffn)
sys.exit(0)
if arg == "--auto":
da["autotest"] = True
elif arg == "--check":
da["check"] = True
else:
da["fn"] = arg
args = args[1:]
return da
def load_res_file(path):
items = {}
res = None
for line in open(path):
line = line.strip()
if line[:1] == "#":
continue
kv = line.split("=", 1)
if len(kv) != 2:
continue
if kv[0] == "res":
res = kv[1]
if res not in items:
items[res] = ["", []]
elif res is None:
continue
elif kv[0] == "hash":
items[res][0] = kv[1]
elif kv[0] == "tags":
items[res][1] += [kv[1].split(",")]
return items
def check_env(settings, args):
"Check test environment"
verbose = not args["autotest"]
# check python version
if PY3K:
if settings.get("python3", "yes") == "no":
# python 3 inacceptable
if verbose:
err("Python 3.x unsupported %s" % repr(sys.version_info))
else:
log("NOTFORPY3")
return False
else:
if settings.get("python2", "yes") == "no":
# python 2 inacceptable
if verbose:
err("Python 2.x unsupported %s" % repr(sys.version_info))
else:
log("NOTFORPY2")
return False
if settings.get("pil", "no") == "yes":
# import PIL
try:
try:
import Image
except:
from PIL import Image
except ImportError:
Image = None
if Image is None:
if verbose:
err("PIL or Pillow module is required")
else:
log("NOPIL")
return False
# check res
reslst = None
for res in settings.get("res", []):
if reslst is None:
# check
respath = os.path.join(basepath, "resources.txt")
if file_hash(respath) != RESHASH:
if verbose:
err("File resources.txt damaged (hash mismatch)")
else:
log("RESHASH")
return False
# load data
reslst = load_res_file(respath)
if res not in reslst:
err("Resource \"" + res + "\" not found")
if not verbose:
log("NORES")
return False
# check hash
respath = os.path.join(basepath, res)
hs = file_hash(respath)
if hs != reslst[res][0]:
err("Resource \"" + res + "\" damaged")
err(" read = %s" % hs)
err(" required = %s" % reslst[res][0])
if not verbose:
log("RESERR")
return False
return True
def check_result(settings, args):
check = True
if settings.get("fn"):
if args["check"]:
# compare with hash
hs = file_hash(args["fn"])
fhs = settings.get("hash", "")
if fhs != "" and hs != fhs:
check = False
err("Hash mismatch:")
err(" new = %s" % hs)
err(" required = %s" % fhs)
if args["autotest"]:
if check:
log("OK")
else:
log("HASHERROR")
else:
if settings.get("fn"):
start_by_ext(args["fn"])
else:
log("Test passed")
def testmain(fn, testfunc):
si = read_cover_info(fn)
da = parse_test_args(sys.argv, si.get("fn"))
if not check_env(si, da):
return
testfunc(da["fn"], da["autotest"] or da["check"])
check_result(si, da)
@@ -0,0 +1,151 @@
# -*- coding: utf-8 -*-
"Test caching"
#PyFPDF-cover-test:res=font/DejaVuSansCondensed.ttf
#PyFPDF-cover-test:res=font/DejaVuSans.ttf
import common
import fpdf
import os, shutil, time
def testfile(f1, f2):
# create pdf
pdf = fpdf.FPDF()
if f1:
pdf.add_font('DejaVuSansCondensed', '', f1, uni = True)
if f2:
pdf.add_font('DejaVuSans', '', f2, uni = True)
pdf.set_font('DejaVuSans', "", 10)
return pdf
def trashfile(fn):
f = open(fn, "w")
f.write("1234567890")
f.close()
try:
from hashlib import md5
except ImportError:
try:
from md5 import md5
except ImportError:
md5 = None
def hashfn(fn):
h = md5()
if common.PY3K:
h.update(fn.encode("UTF-8"))
else:
h.update(fn)
return h.hexdigest()
def dotest(outputname, nostamp):
cachepath = os.path.join(os.path.dirname(__file__), "cache")
if os.path.exists(cachepath):
# cleanup dest
for item in os.listdir(cachepath):
os.remove(os.path.join(cachepath, item))
else:
# create font dir
os.makedirs(cachepath)
hashpath = os.path.join(os.path.dirname(__file__), "hash")
if os.path.exists(hashpath):
# cleanup dest
for item in os.listdir(hashpath):
os.remove(os.path.join(hashpath, item))
else:
# create font dir
os.makedirs(hashpath)
# copy font files
shutil.copy(os.path.join(common.basepath, "font", "DejaVuSansCondensed.ttf"), cachepath)
shutil.copy(os.path.join(common.basepath, "font", "DejaVuSans.ttf"), cachepath)
f1 = os.path.join(cachepath, "DejaVuSansCondensed.ttf")
f2 = os.path.join(cachepath, "DejaVuSans.ttf")
# --- normal cache mode ---
fpdf.set_global("FPDF_CACHE_MODE", 0)
# first load
t0 = time.time()
pdf = testfile(f1, f2)
t1 = time.time()
assert os.path.exists(f1[:-3] + "pkl")
assert os.path.exists(f2[:-3] + "pkl")
# load cached
t2 = time.time()
pdf = testfile(f1, f2)
t3 = time.time()
if not nostamp:
common.log("Cache fonts: ", t1 - t0)
common.log("Reload fonts: ", t3 - t2)
pdf.add_page()
# trigger cw127
#pdf.write(5, "Γειά σου κόσμος")
pdf.write(5, "Привет!")
pdf.write(10, "Hello")
pdf.output(os.path.join(cachepath, "pdf0.pdf"), "F")
# check cw127
assert not os.path.exists(f1[:-3] + "cw127.pkl")
assert os.path.exists(f2[:-3] + "cw127.pkl")
# --- disable cache reading ---
fpdf.set_global("FPDF_CACHE_MODE", 1)
# put garbage data to cache files - fpdf should not read pkl
trashfile(f1[:-3] + "pkl")
trashfile(f2[:-3] + "pkl")
trashfile(f2[:-3] + "cw127.pkl")
# test same file
t0 = time.time()
pdf = testfile(f1, f2)
t1 = time.time()
# remove pkl files
os.remove(f1[:-3] + "pkl")
os.remove(f2[:-3] + "pkl")
os.remove(f2[:-3] + "cw127.pkl")
# test reload
t2 = time.time()
pdf = testfile(f1, f2)
t3 = time.time()
if not nostamp:
common.log("No cache 1st: ", t1 - t0)
common.log("No cache 2nd: ", t3 - t2)
pdf.add_page()
pdf.write(5, "Γειά σου κόσμος")
pdf.write(10, "Hello")
pdf.output(os.path.join(cachepath, "pdf1.pdf"), "F")
# test no files created
assert not os.path.exists(f1[:-3] + "pkl")
assert not os.path.exists(f2[:-3] + "pkl")
assert not os.path.exists(f1[:-3] + "cw127.pkl")
assert not os.path.exists(f2[:-3] + "cw127.pkl")
# --- hash cache ---
fpdf.set_global("FPDF_CACHE_MODE", 2)
fpdf.set_global("FPDF_CACHE_DIR", hashpath)
t0 = time.time()
pdf = testfile(f1, f2)
t1 = time.time()
assert not os.path.exists(f1[:-3] + "pkl")
assert not os.path.exists(f2[:-3] + "pkl")
# load cached
t2 = time.time()
pdf = testfile(f1, f2)
t3 = time.time()
# test reload
if not nostamp:
common.log("Hash load 1st:", t1 - t0)
common.log("Hash load 2nd:", t3 - t2)
# check hash
assert os.path.exists(os.path.join(hashpath, hashfn(f1) + ".pkl"))
assert os.path.exists(os.path.join(hashpath, hashfn(f2) + ".pkl"))
pdf.add_page()
pdf.write(5, "Хешировали, хешировали, да выдохешиовали.")
pdf.write(10, "Hello")
pdf.output(os.path.join(cachepath, "pdf2.pdf"), "F")
assert not os.path.exists(os.path.join(hashpath, hashfn(f1) + ".cw127.pkl"))
assert os.path.exists(os.path.join(hashpath, hashfn(f2) + ".cw127.pkl"))
if __name__ == "__main__":
common.testmain(__file__, dotest)
@@ -0,0 +1,165 @@
# -*- coding: utf-8 -*-
"PDF Template Helper for FPDF.py"
__author__ = "Mariano Reingart <reingart@gmail.com>"
__copyright__ = "Copyright (C) 2010 Mariano Reingart"
__license__ = "LGPL 3.0"
#PyFPDF-cover-test:format=PDF
#PyFPDF-cover-test:fn=invoice.pdf
#PyFPDF-cover-test:hash=5844bbebe3e33b0ac9cc15ac39327a81
#PyFPDF-cover-test:res=invoice.csv
import common
from fpdf import Template
import os
class randomfake:
RINT1_10 = [8, 5, 7, 9, 10, 8, 1, 9, 1, 7, 6, 2, 3, 7, 8, 4, 6, 5, 7, 2, \
5, 8, 6, 5, 5, 8, 7, 7, 6]
RINT65_90 = [67, 67, 87, 78, 84, 67, 86, 75, 86, 89, 81, 69, 72, 71, 84, \
80, 71 , 86 , 82 , 70 , 84 , 69 , 70]
RFLT = [0.820710198665, 0.342854771472, 0.0238515965298, 0.177658111957, \
0.422301628067, 0.701867781693, 0.168650983171, 0.329723498664, \
0.490481106182, 0.892634029991, 0.994758791625, 0.998243714035, \
0.596244312914 ,0.318601111178 ,0.321593673214 ,0.203486335469]
def __init__(self):
self.icnt1_10 = 0
self.icnt65_90 = 0
self.fcnt = 0
def randint(self, beg, end):
if beg == 1 and end == 10:
self.icnt1_10 += 1
if self.icnt1_10 > len(self.RINT1_10):
self.icnt1_10 = 1
return self.RINT1_10[self.icnt1_10 - 1]
if beg == 65 and end == 90:
self.icnt65_90 += 1
if self.icnt65_90 > len(self.RINT65_90):
self.icnt65_90 = 1
return self.RINT65_90[self.icnt65_90 - 1]
raise Exception("Not implemented")
def random(self):
self.fcnt += 1
if self.fcnt > len(self.RFLT):
self.fcnt = 1
return self.RFLT[self.fcnt - 1]
def dotest(outputname, nostamp):
# generate sample invoice (according Argentina's regulations)
from decimal import Decimal
f = Template(format="A4",
title="Sample Invoice", author="Sample Company",
subject="Sample Customer", keywords="Electronic TAX Invoice")
if nostamp:
f.pdf._putinfo = lambda: common.test_putinfo(f.pdf)
random = randomfake()
else:
import random
csvpath = os.path.join(common.basepath, "invoice.csv")
f.parse_csv(infile=csvpath, delimiter=";", decimal_sep=",")
detail = "Lorem ipsum dolor sit amet, consectetur. " * 30
items = []
for i in range(1, 30):
ds = "Sample product %s" % i
qty = random.randint(1,10)
price = round(random.random()*100,3)
code = "%s%s%02d" % (chr(random.randint(65,90)), chr(random.randint(65,90)),i)
items.append(dict(code=code, unit='u',
qty=qty, price=price,
amount=qty*price,
ds="%s: %s" % (i,ds)))
# divide and count lines
lines = 0
li_items = []
for it in items:
qty = it['qty']
code = it['code']
unit = it['unit']
for ds in f.split_multicell(it['ds'], 'item_description01'):
# add item description line (without price nor amount)
li_items.append(dict(code=code, ds=ds, qty=qty, unit=unit, price=None, amount=None))
# clean qty and code (show only at first)
unit = qty = code = None
# set last item line price and amount
li_items[-1].update(amount = it['amount'],
price = it['price'])
obs="\n<U>Detail:</U>\n\n" + detail
for ds in f.split_multicell(obs, 'item_description01'):
li_items.append(dict(code=code, ds=ds, qty=qty, unit=unit, price=None, amount=None))
# calculate pages:
lines = len(li_items)
max_lines_per_page = 24
pages = int(lines / (max_lines_per_page - 1))
if lines % (max_lines_per_page - 1): pages = pages + 1
# completo campos y hojas
for page in range(1, int(pages)+1):
f.add_page()
f['page'] = 'Page %s of %s' % (page, pages)
if pages>1 and page<pages:
s = 'Continues on page %s' % (page+1)
else:
s = ''
f['item_description%02d' % (max_lines_per_page+1)] = s
f["company_name"] = "Sample Company"
f["company_logo"] = os.path.join(common.basepath, "../tutorial/logo.png")
f["company_header1"] = "Some Address - somewhere -"
f["company_header2"] = "http://www.example.com"
f["company_footer1"] = "Tax Code ..."
f["company_footer2"] = "Tax/VAT ID ..."
f['number'] = '0001-00001234'
f['issue_date'] = '2010-09-10'
f['due_date'] = '2099-09-10'
f['customer_name'] = "Sample Client"
f['customer_address'] = "Siempreviva 1234"
# print line item...
li = 0
k = 0
total = Decimal("0.00")
for it in li_items:
k = k + 1
if k > page * (max_lines_per_page - 1):
break
if it['amount']:
total += Decimal("%.6f" % it['amount'])
if k > (page - 1) * (max_lines_per_page - 1):
li += 1
if it['qty'] is not None:
f['item_quantity%02d' % li] = it['qty']
if it['code'] is not None:
f['item_code%02d' % li] = it['code']
if it['unit'] is not None:
f['item_unit%02d' % li] = it['unit']
f['item_description%02d' % li] = it['ds']
if it['price'] is not None:
f['item_price%02d' % li] = "%0.3f" % it['price']
if it['amount'] is not None:
f['item_amount%02d' % li] = "%0.2f" % it['amount']
if pages == page:
f['net'] = "%0.2f" % (total/Decimal("1.21"))
f['vat'] = "%0.2f" % (total*(1-1/Decimal("1.21")))
f['total_label'] = 'Total:'
else:
f['total_label'] = 'SubTotal:'
f['total'] = "%0.2f" % total
f.render(outputname)
if __name__ == "__main__":
common.testmain(__file__, dotest)
@@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
"Test images flow mode (cell-like, trigger page breaks)"
#PyFPDF-cover-test:format=PDF
#PyFPDF-cover-test:fn=issue_14.pdf
#PyFPDF-cover-test:hash=7e4a5b0a77c4eaefa475bb7db655fcd9
#PyFPDF-cover-test:res=../tutorial/logo_pb.png
import common
from fpdf import FPDF
import os
def dotest(outputname, nostamp):
pdf = FPDF()
if nostamp:
pdf._putinfo = lambda: common.test_putinfo(pdf)
pdf.add_page()
for i in range(1,41):
# for flow mode, do not pass x or y:
pdf.image(os.path.join(common.basepath, '../tutorial/logo_pb.png'))
pdf.output(outputname, 'F')
if __name__ == "__main__":
common.testmain(__file__, dotest)
@@ -0,0 +1,114 @@
# -*- coding: utf-8 -*-
"Test issue 33 (Cannot import GIF files that don't have transparency)"
#PyFPDF-cover-test:format=PDF
#PyFPDF-cover-test:fn=issue_33.pdf
#PyFPDF-cover-test:hash=be95c7ef3a5b14b5a54a52f7eaf3a9e4
#PyFPDF-cover-test:2to3=no
#PyFPDF-cover-test:pil=yes
import common
from fpdf import FPDF
import os, sys, tempfile
try:
try:
import Image
except:
from PIL import Image
except ImportError:
Image = None
def genbar():
# bg
bg = Image.new("L", (112, 1), 1)
bg = bg.resize((112, 11))
# stripes
vbarnum = [0x4F43484B, 0xEE90D642, 0xF11A2735, 0xD71A]
vbar = Image.new("L", (112, 1), 1)
pix = vbar.load()
pos = 0
for b in vbarnum:
for i in range(32):
pix[pos, 0] = 0 if (b & 1) else 1
b = b >> 1
pos += 1
if pos >= 112: break
vbar = vbar.resize((112, 31), Image.NEAREST)
# digit
dignum = [0x398, 0x6dc, 0x61a, 0x31b, 0x1bf, 0x6d8, 0x7d8]
dbar = Image.new("L", (16, 7), 1)
pix = dbar.load()
pos = 0
ypos = 0
for b in dignum:
for i in range(16):
pix[pos, ypos] = 0 if (b & 1) else 1
b = b >> 1
pos += 1
ypos += 1
pos = 0
# result
bar = Image.new("L", (114, 44), 2)
bar.paste(vbar, (1, 1))
bar.paste(bg, (1, 32))
for i in range(4):
bar.paste(dbar, (35 + i * 12, 34))
return bar
def dotest(outputname, nostamp):
plane = genbar()
palette = (0,0,0, 255,255,255) + (128,128,128)*254
img = Image.fromstring("P", plane.size, plane.tostring())
img.putpalette(palette)
f = tempfile.NamedTemporaryFile(delete = False, suffix = ".gif")
gif1 = f.name
f.close()
f = tempfile.NamedTemporaryFile(delete = False, suffix = ".gif")
gif2 = f.name
f.close()
img.save(gif1, "GIF", optimize = 0)
img.save(gif2, "GIF", transparency = 1, optimize = 0)
pdf = FPDF()
if nostamp:
pdf._putinfo = lambda: common.test_putinfo(pdf)
pdf.add_page()
pdf.set_font('Arial', '', 16)
pdf.write(8, "Transparency")
pdf.ln()
pdf.write(8, " Transparency")
pdf.ln()
pdf.write(8, " Transparency")
pdf.ln()
pdf.image(gif1, x = 15, y = 15)
pdf.write(8, "Transparency")
pdf.ln()
pdf.write(8, " Transparency")
pdf.ln()
pdf.write(8, " Transparency")
pdf.ln()
pdf.image(gif2, x = 15, y = 39)
pdf.output(outputname, 'F')
os.unlink(gif1)
os.unlink(gif2)
def main():
si = common.read_cover_info(__file__)
da = common.parse_test_args(sys.argv, si["fn"])
if not common.check_env(si, da):
return
dotest(da["fn"], da["autotest"] or da["check"])
common.check_result(si, da)
if __name__ == "__main__":
main()
@@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-
"Tests new dashed line feature (issue 35)"
#PyFPDF-cover-test:format=PDF
#PyFPDF-cover-test:fn=issue_35.pdf
#PyFPDF-cover-test:hash=e8f92b3210aea65caa72f70d0f898c04
import common
from fpdf import FPDF
def dotest(outputname, nostamp):
pdf = FPDF()
if nostamp:
pdf._putinfo = lambda: common.test_putinfo(pdf)
pdf.add_page()
pdf.dashed_line(10, 10, 110, 10)
pdf.dashed_line(10, 20, 110, 20, 5, 5)
pdf.dashed_line(10, 30, 110, 30, 1, 10)
pdf.output(outputname, 'F')
if __name__ == "__main__":
common.testmain(__file__, dotest)
@@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
"Test issue 41 (escape CR char)"
#PyFPDF-cover-test:format=TXT
#PyFPDF-cover-test:fn=issue_41.txt
#PyFPDF-cover-test:hash=c576afec3362a7cc3b4b07a12feeefd3
import common # common set of utilities
import fpdf
import sys
def dotest(outputname, nostamp):
txt = "This is test string for issue41 with special symbols \n" +\
"ln - \n\n" +\
"cr - \r\n" +\
"\\ ( ) abcdef..xyz 01234\n" +\
"| [ ] ABCDEF..XYZ 56789\n"
pdf = fpdf.FPDF()
f = open(outputname, "wb")
f.write(pdf._escape(txt).encode("latin1"))
f.close()
def main():
si = common.read_cover_info(__file__)
da = common.parse_test_args(sys.argv, si["fn"])
if not common.check_env(si, da):
return
dotest(da["fn"], da["autotest"] or da["check"])
common.check_result(si, da)
if __name__ == "__main__":
main()
@@ -0,0 +1,46 @@
# -*- coding: utf-8 -*-
"Basic test to reproduce issue 60: RTL languages (arabian, hebrew, etc.)"
#PyFPDF-cover-test:format=PDF
#PyFPDF-cover-test:fn=issue_60.pdf
#PyFPDF-cover-test:hash=bc47380ca9511b96756d1066a3b494c1
#PyFPDF-cover-test:res=font/DejaVuSans.ttf
import common
from fpdf import FPDF
import sys, traceback, os
def dotest(outputname, nostamp):
pdf = FPDF()
if nostamp:
pdf._putinfo = lambda: common.test_putinfo(pdf)
pdf.compress = False
pdf.add_page()
pdf.add_font('DejaVu', '', \
os.path.join(common.basepath, 'font/DejaVuSans.ttf'), uni=True)
pdf.set_font('DejaVu', '', 14)
# this will be displayed wrong as actually it is stored LTR:
text= u"این یک متن پارسی است. This is a Persian text !!"
pdf.write(8, text)
pdf.ln(8)
# Reverse the RLT using the Bidirectional Algorithm to be displayed correctly:
# (http://unicode.org/reports/tr9/)
from bidi.algorithm import get_display
rtl_text = get_display(text)
pdf.write(8, rtl_text)
pdf.output(outputname, 'F')
if __name__ == "__main__":
try:
from bidi.algorithm import get_display
except ImportError:
traceback.print_exc(file = sys.stdout)
common.err("This test requre PyBiDi (https://pypi.python.org/pypi/python-bidi)")
common.log("SKIP")
sys.exit(0)
common.testmain(__file__, dotest)
@@ -0,0 +1,39 @@
# -*- coding: latin-1 -*-
"Basic test to reproduce issue 63: warning in unicode get_char_width"
#PyFPDF-cover-test:res=font/DejaVuSans.ttf
import common
from fpdf import FPDF
import os, struct
if common.PY3K:
def u(x):
return x
else:
import codecs
def u(x):
return codecs.unicode_escape_decode(x)[0]
def dotest(outputname, nostamp):
pdf = FPDF()
pdf.set_font('Arial','',14)
s = 'Texto largo que no cabe en esta celda pero que será ajustado'
w = pdf.get_string_width(s)
if not nostamp:
print (s, w)
assert round(w, 2) == 135.90
pdf.add_font('DejaVu', '', './font/DejaVuSans.ttf', uni=True)
pdf.set_font('DejaVu', '', 14)
s = u('Texto largo que no cabe en esta celda pero que será ajustado')
w = pdf.get_string_width(s)
if not nostamp:
print (s, w)
assert round(w, 2) == 153.64
if __name__ == "__main__":
common.testmain(__file__, dotest)
@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
"Basic test to check issue 70: raise an exception if add_page was not called"
import common
from fpdf import FPDF
import os, struct
def dotest(outputname, nostamp):
try:
# Portrait, millimeter units, A4 page size
pdf = FPDF("P", "mm", "A4")
# Set font: Times, normal, size 10
pdf.set_font('Times','', 12)
##pdf.add_page()
# Layout cell: 0 x 5 mm, text, no border, Left
pdf.cell(0,5,'Input 1 : ',border=0,align="L")
pdf.cell(0,5,'Input 2 : ', border=0,align="L")
pdf.cell(0,5,'Recomendation : ', border=0, align="L")
pdf.cell(0,5,'Data 1 :', border=0, align="L" )
pdf.cell(0,5,'Data 2 :', border=0, align="L" )
pdf.output(outputname,'F')
except RuntimeError as e:
assert e.args[0] == "FPDF error: No page open, you need to call add_page() first"
else:
raise RuntimeError("Exception not raised!")
if __name__ == "__main__":
common.testmain(__file__, dotest)
@@ -0,0 +1,34 @@
# -*- coding: utf-8 -*-
"Basic test to check issue 71: test Code39"
#PyFPDF-cover-test:format=PDF
#PyFPDF-cover-test:fn=issue_71.pdf
#PyFPDF-cover-test:hash=1575947cac5b0a8cdceedf9b525ee6db
# get res from http://upload.wikimedia.org/wikipedia/commons/thumb/0/0b/Code_3_of_9.svg/262px-Code_3_of_9.svg.png
# PyFPDF-cover-test:res=.png
import common
from fpdf import FPDF
import os
def dotest(outputname, nostamp):
# Portrait, millimeter units, A4 page size
pdf = FPDF("P", "mm", "A4")
if nostamp:
pdf._putinfo = lambda: common.test_putinfo(pdf)
# Set font: Times, normal, size 10
pdf.add_page()
if not nostamp:
# do not show picture in batch
url = "http://upload.wikimedia.org/wikipedia/commons/thumb/0/0b/Code_3_of_9.svg/262px-Code_3_of_9.svg.png"
pdf.image(url, 10, 10)
pdf.code39("*wikipedia*", 12.75, 7, 1.49)
pdf.output(outputname, 'F')
if __name__ == "__main__":
common.testmain(__file__, dotest)
@@ -0,0 +1,40 @@
# -*- coding: utf-8 -*-
"Test jpeg image embedding"
# Note: img_cmyk.jpg has no color profile, PDF rendering may vary
#PyFPDF-cover-test:format=PDF
#PyFPDF-cover-test:fn=jpeg.pdf
#PyFPDF-cover-test:hash=eb8db8f336226f6de671a3e515b9cc61
#PyFPDF-cover-test:res=img_gray.jpg
#PyFPDF-cover-test:res=img_rgb.jpg
#PyFPDF-cover-test:res=img_cmyk.jpg
import common # test utilities
from fpdf import FPDF
import sys
def dotest(outputname, nostamp):
pdf = FPDF()
if nostamp:
pdf._putinfo = lambda: common.test_putinfo(pdf)
pdf.add_page()
pdf.set_font('Arial', '', 14)
pdf.text(10, 57, 'DeviceGray')
pdf.image("img_gray.jpg", 55, 5)
pdf.text(10, 157, 'DeviceRGB')
pdf.image("img_rgb.jpg", 55, 105)
pdf.text(10, 257, 'DeviceCMYK')
pdf.image("img_cmyk.jpg", 55, 205)
pdf.output(outputname, 'F')
if __name__ == "__main__":
common.testmain(__file__, dotest)
@@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-
"Simple test to check alias_nb_pages replacement under unicode fonts"
#PyFPDF-cover-test:format=PDF
#PyFPDF-cover-test:fn=nb_pages.pdf
#PyFPDF-cover-test:hash=4f22df85e31007cb275fabdc9fa78f97
#PyFPDF-cover-test:res=font/DejaVuSansCondensed.ttf
import common
import fpdf
import os
def dotest(outputname, nostamp):
pdf = fpdf.FPDF()
if nostamp:
pdf._putinfo = lambda: common.test_putinfo(pdf)
fpdf.set_global("FPDF_CACHE_MODE", 1)
# set default alias: {nb} that will be replaced with total page count
pdf.alias_nb_pages()
# Add a Unicode font (uses UTF-8)
pdf.add_font('DejaVu', '', \
os.path.join(common.basepath, "font", 'DejaVuSansCondensed.ttf'), \
uni = True)
pdf.set_font('DejaVu', '', 14)
for i in range(5):
pdf.add_page()
pdf.set_font('Arial','B',16)
pdf.cell(40,10,'Hello World! Page %d from {nb}' % (i + 1))
pdf.set_font('DejaVu','',14)
pdf.cell(40,30,'Hello World! unicode {nb}')
pdf.output(outputname, 'F')
if __name__ == "__main__":
common.testmain(__file__, dotest)
@@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
"Basic example to test py3k conversion"
#PyFPDF-cover-test:format=PDF
#PyFPDF-cover-test:fn=py3k.pdf
#PyFPDF-cover-test:hash=ecf5ec7b9a3bb6015b4c9f0546f62e84
#PyFPDF-cover-test:python2=no
import common # test utilities
from fpdf import FPDF
import sys
def dotest(outputname, nostamp):
pdf = FPDF()
if nostamp:
pdf._putinfo = lambda: common.test_putinfo(pdf)
pdf.add_page()
pdf.set_font('Arial', '', 14)
pdf.ln(10)
if nostamp:
data = "TEST-TEST-TEST"
else:
data = sys.version
#áéíóúüñ
# This string converted with errors in py2.x
pdf.write(5, ('hello world %s áéíóúüñ' % data))
pdf.output(outputname, 'F')
if __name__ == "__main__":
common.testmain(__file__, dotest)
@@ -0,0 +1,39 @@
# -*- coding: utf-8 -*-
"Basic example to test PyFPDF"
#PyFPDF-cover-test:format=PDF
#PyFPDF-cover-test:fn=simple.pdf
#PyFPDF-cover-test:hash=1fd821a42cb5029a51727a6107b623ec
#PyFPDF-cover-test:pil=yes
#PyFPDF-cover-test:res=../tutorial/logo.png
#PyFPDF-cover-test:res=flower2.jpg
#PyFPDF-cover-test:res=lena.gif
import common # test utilities
from fpdf import FPDF
import sys
def dotest(outputname, nostamp):
pdf = FPDF()
if nostamp:
pdf._putinfo = lambda: common.test_putinfo(pdf)
pdf.add_page()
pdf.set_font('Arial', '', 14)
pdf.ln(10)
if nostamp:
data = "TEST-TEST-TEST"
else:
data = sys.version
pdf.write(5, 'hello world %s' % data)
pdf.image("../tutorial/logo.png", 50, 50)
pdf.image("flower2.jpg", 100, 50)
pdf.image("lena.gif", 50, 75)
pdf.output(outputname, 'F')
if __name__ == "__main__":
common.testmain(__file__, dotest)
@@ -0,0 +1,45 @@
# -*- coding: utf-8 -*-
"This is test template"
# Lines below must not be separated by blank line
# output formats PDF (can be auto-opened), TXT
#PyFPDF-cover-test:format=PDF
# default filename
#PyFPDF-cover-test:fn=template.pdf
# hash stamp for compare in --check mode (insert your hash)
#PyFPDF-cover-test:hash=b1812fffdcf175976e80317b3766a0f0
# use 2to3 tool (default - no)
#PyFPDF-cover-test:2to3=no
# can be used in python2 (default - yes)
#PyFPDF-cover-test:python2=yes
# can be used in python3 (default - yes)
#PyFPDF-cover-test:python3=yes
# is PIL required (default - no)
#PyFPDF-cover-test:pil=no
# only for platform (default all - *)
#PyFPDF-cover-test:platform=*
#...
#...PyFPDF-cover-test:res=some_resource.ttf
#...PyFPDF-cover-test:res=other_resource.txt
#...
import common # common set of utilities
from fpdf import FPDF
import sys
def dotest(outputname, nostamp):
# filename - output filename
# nostamp - do no use stamp in result file
pdf = FPDF()
if nostamp:
pdf._putinfo = lambda: common.test_putinfo(pdf)
pdf.add_page()
pdf.set_font('Arial', '', 16)
pdf.write(8, "Test template")
pdf.output(outputname, 'F')
if __name__ == "__main__":
common.testmain(__file__, dotest)
@@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-
"Basic test of TrueType Unicode font handling"
#PyFPDF-cover-test:res=font/DejaVuSansCondensed.ttf
#PyFPDF-cover-test:res=dejavusanscondensed.cw.dat
import common
from fpdf.ttfonts import TTFontFile
import os, struct
def dotest(outputname, nostamp):
ttf = TTFontFile()
ttffile = os.path.join(common.basepath, "font", "DejaVuSansCondensed.ttf");
ttf.getMetrics(ttffile)
# test basic metrics:
assert round(ttf.descent, 0) == -236
assert round(ttf.capHeight, 0) == 928
assert ttf.flags == 4
assert [round(i, 0) for i in ttf.bbox] == [-918, -415, 1513, 1167]
assert ttf.italicAngle == 0
assert ttf.stemV == 87
assert round(ttf.defaultWidth, 0) == 540
assert round(ttf.underlinePosition, 0) == -63
assert round(ttf.underlineThickness, 0) == 44
# test char widths 8(against binary file generated by tfpdf.php):
data = open(os.path.join(common.basepath, "dejavusanscondensed.cw.dat"),\
"rb").read()
char_widths = struct.unpack(">%dH" % int(len(data) / 2), data)
assert len(ttf.charWidths) == len(char_widths)
diff = []
for i, (x, y) in enumerate(zip(char_widths, ttf.charWidths)):
if x != y: # compare each char width
diff.append(i)
assert not diff
# for checking assertion works ttf.charWidths[1] = 600
assert tuple(ttf.charWidths) == tuple(char_widths)
if __name__ == "__main__":
common.testmain(__file__, dotest)
@@ -0,0 +1,38 @@
# -*- coding: utf-8 -*-
"Example of unicode support based on tfPDF http://www.fpdf.org/en/script/script92.php"
#PyFPDF-cover-test:format=PDF
#PyFPDF-cover-test:fn=ex.pdf
#PyFPDF-cover-test:hash=f77f71491e1662a732212861a2d87928
#PyFPDF-cover-test:res=font/DejaVuSansCondensed.ttf
#PyFPDF-cover-test:res=HelloWorld.txt
import common
from fpdf import FPDF
import os
def dotest(outputname, nostamp):
pdf = FPDF()
if nostamp:
pdf._putinfo = lambda: common.test_putinfo(pdf)
pdf.add_page()
# Add a Unicode font (uses UTF-8)
pdf.add_font('DejaVu', '', \
os.path.join(common.basepath, "font", 'DejaVuSansCondensed.ttf'), \
uni = True)
pdf.set_font('DejaVu','',14)
# Load a UTF-8 string from a file and print it
txt = open(os.path.join(common.basepath, "HelloWorld.txt"), "rb").\
read().decode("UTF-8")
pdf.write(8, txt)
pdf.output(outputname, 'F')
if __name__ == "__main__":
common.testmain(__file__, dotest)
@@ -0,0 +1,55 @@
# -*- coding: utf-8 -*-
"Example of unicode support winfonts based on tfPDF"
# http://www.fpdf.org/en/script/script92.php
#PyFPDF-cover-test:format=PDF
#PyFPDF-cover-test:fn=winfonts.pdf
#PyFPDF-cover-test:platform=win32
#PyFPDF-cover-test:res=HelloWorld.txt
# This test can't calc hash because TTF fonts can vary on systems
import common
import fpdf
import os, time
def dotest(outputname, nostamp):
fpdf.set_global('SYSTEM_TTFONTS', "c:\\WINDOWS\\Fonts")
pdf = fpdf.FPDF()
if nostamp:
pdf._putinfo = lambda: common.test_putinfo(pdf)
pdf.add_page()
# Add a Windows System font (uses UTF-8)
t0 = time.time()
pdf.add_font('sysfont','','arial.ttf',uni=True)
pdf.set_font('sysfont','',14)
t1 = time.time()
if not nostamp:
common.log("ttf loading time", t1-t0)
# Load a UTF-8 string from a file and print it
txt = open(os.path.join(common.basepath, "HelloWorld.txt"), "rb").\
read().decode("UTF-8")
pdf.multi_cell(25, 5, txt)
pdf.text(100, 5, '1234')
pdf.write(5,'To find out what\'s new in self tutorial, click ')
pdf.set_font('','U')
link=pdf.add_link()
pdf.write(5,'here',link)
# Select a standard font (uses windows-1252)
pdf.set_font('Arial','',14)
pdf.ln(10)
pdf.write(5, 'The file size of this PDF is only 12 KB.')
pdf.output(outputname, 'F')
if __name__ == "__main__":
common.testmain(__file__, dotest)
@@ -0,0 +1,61 @@
%PDF-1.3
3 0 obj
<</Type /Page
/Parent 1 0 R
/Resources 2 0 R
/Contents 4 0 R>>
endobj
4 0 obj
<</Filter /FlateDecode /Length 99>>
stream
xœUÍ1€0ÐBKË\7G½¾­±. Š…[ÁEUÙ£á™vRçvp‰l '¢»¼ùÀJµ÷ª$–Ñ×l‹køìȳ_[=åµÌníy¢7}&5
endstream
endobj
1 0 obj
<</Type /Pages
/Kids [3 0 R ]
/Count 1
/MediaBox [0 0 595.28 841.89]
>>
endobj
2 0 obj
<<
/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]
/Font <<
>>
/XObject <<
>>
>>
endobj
5 0 obj
<<
/Producer (PyFPDF 1.7.1 http://pyfpdf.googlecode.com/)
/CreationDate (D:20130308083055)
>>
endobj
6 0 obj
<<
/Type /Catalog
/Pages 1 0 R
/OpenAction [3 0 R /FitH null]
/PageLayout /OneColumn
>>
endobj
xref
0 7
0000000000 65535 f
0000000255 00000 n
0000000342 00000 n
0000000009 00000 n
0000000087 00000 n
0000000436 00000 n
0000000545 00000 n
trailer
<<
/Size 7
/Root 6 0 R
/Info 5 0 R
>>
startxref
648
%%EOF
@@ -0,0 +1,21 @@
"Tests new dashed line feature (issue 35)"
from fpdf import FPDF
import os
pdf=FPDF()
pdf.add_page()
pdf.dashed_line(10, 10, 110, 10)
pdf.dashed_line(10, 20, 110, 20, 5, 5)
pdf.dashed_line(10, 30, 110, 30, 1, 10)
fn = 'dashed_line_issue35.pdf'
pdf.output(fn,'F')
try:
os.startfile(fn)
except:
os.system("xdg-open \"%s\"" % fn)
@@ -0,0 +1,29 @@
# Example of unicode support based on tfPDF
# http://www.fpdf.org/en/script/script92.php
from fpdf import FPDF
import sys
pdf = FPDF()
pdf.add_page()
# Add a Unicode font (uses UTF-8)
pdf.add_font('DejaVu','','DejaVuSansCondensed.ttf',uni=True)
pdf.set_font('DejaVu','',14)
fn = 'ex.pdf'
# Load a UTF-8 string from a file and print it
txt = open('HelloWorld.txt').read()
pdf.write(8, txt)
# Select a standard font (uses windows-1252)
pdf.set_font('Arial','',14)
pdf.ln(10)
pdf.write(5, 'The file size of this PDF is only 12 KB.')
pdf.output(fn,'F')
import os
try:
os.startfile(fn)
except:
os.system("xdg-open \"%s\"" % fn)
Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

+99
View File
@@ -0,0 +1,99 @@
# -*- coding: latin-1 -*-
"HTML Renderer for FPDF.py"
__author__ = "Mariano Reingart <reingart@gmail.com>"
__copyright__ = "Copyright (C) 2010 Mariano Reingart"
__license__ = "LGPL 3.0"
# Inspired by tuto5.py and several examples from fpdf.org, html2fpdf, etc.
from fpdf import FPDF, HTMLMixin
if __name__=='__main__':
html="""
<H1 align="center">html2fpdf</H1>
<h2>Basic usage</h2>
<p>You can now easily print text mixing different
styles : <B>bold</B>, <I>italic</I>, <U>underlined</U>, or
<B><I><U>all at once</U></I></B>!<BR>You can also insert links
on text, such as <A HREF="http://www.fpdf.org">www.fpdf.org</A>,
or on an image: click on the logo.<br>
<center>
<A HREF="http://www.fpdf.org"><img src="../tutorial/logo.png" width="104" height="71"></A>
</center>
<h3>Sample List</h3>
<ul><li>option 1</li>
<ol><li>option 2</li></ol>
<li>option 3</li></ul>
<table border="0" align="center" width="50%">
<thead><tr><th width="30%">Header 1</th><th width="70%">header 2</th></tr></thead>
<tbody>
<tr><td>cell 1</td><td>cell 2</td></tr>
<tr><td>cell 2</td><td>cell 3</td></tr>
</tbody>
</table>
<table border="1">
<thead><tr bgcolor="#A0A0A0"><th width="30%">Header 1</th><th width="70%">header 2</th></tr></thead>
<tfoot><tr bgcolor="#E0E0E0"><td>footer 1</td><td>footer 2</td></tr></tfoot>
<tbody>
<tr><td>cell 1</td><td>cell 2</td></tr>
<tr>
<td width="30%">cell 1</td><td width="70%" bgcolor="#D0D0FF" align='right'>cell 2</td>
</tr>
</tbody>
<tbody><tr><td colspan="2">cell spanned</td></tr></tbody>
<tbody>
""" + """<tr bgcolor="#F0F0F0">
<td>cell 3</td><td>cell 4</td>
</tr><tr bgcolor="#FFFFFF">
<td>cell 5</td><td>cell 6</td>
</tr>""" * 200 + """
</tbody>
</table>
<font face='helvetica' size='40'>Font example: Arial 40pt</font>
"""
class MyFPDF(FPDF, HTMLMixin):
def header(self):
self.image('../tutorial/logo_pb.png',10,8,33)
self.set_font('Arial','B',15)
self.cell(80)
self.cell(30,10,'Title',1,0,'C')
self.ln(20)
def footer(self):
self.set_y(-15)
self.set_font('Arial','I',8)
txt = 'Page %s of %s' % (self.page_no(), self.alias_nb_pages())
self.cell(0,10,txt,0,0,'C')
pdf=MyFPDF()
#First page
pdf.add_page()
pdf.write_html(html)
# this will fail (tables without widht are not supported):
try:
pdf.write_html("""<table><tr><td></td></tr></table>""")
except RuntimeError:
pass
# this may be rendered incorrectly as currently there is no two pass auto-layout:
pdf.write_html("""<table><tr><th></th><td width="100%">100%</td></tr></table>""")
fn = 'html.pdf'
pdf.output(fn,'F')
import os
try:
os.startfile(fn)
except:
os.system("xdg-open \"%s\"" % fn)
@@ -0,0 +1,46 @@
# -*- coding: utf-8 -*-
"HTML Renderer for FPDF.py (unicode)"
__author__ = "Mariano Reingart <reingart@gmail.com>"
__copyright__ = "Copyright (C) 2010 Mariano Reingart"
__license__ = "LGPL 3.0"
# Inspired by tuto5.py and several examples from fpdf.org, html2fpdf, etc.
from fpdf import FPDF, HTMLMixin
if __name__ == '__main__':
class MyFPDF(FPDF, HTMLMixin): pass
pdf=MyFPDF()
# load the unicode font
pdf.add_font('DejaVu', '', 'DejaVuSansCondensed.ttf', uni=True)
pdf.add_page()
# test the basic fonts
pdf.write_html("""<p><font face="Arial"><B>hello</B> <I>world</I></font></p>""")
pdf.write_html("""<p><font face="Times"><B>hello</B> <I>world</I></font></p>""")
pdf.write_html("""<p><font face="Courier"><B>hello</B> <I>world</I></font></p>""")
pdf.write_html("""<p><font face="zapfdingbats"><B>hello</B> <I>world</I></font></p>""")
# test the unicode (utf8) font:
# greek
pdf.write_html(u"""<p><font face="DejaVu">Γειά σου κόσμος</font></p>""")
# russian
pdf.write_html(u"""<p><font face="DejaVu">Здравствуй, Мир</font></p>""")
fn = 'html_unicode.pdf'
pdf.output(fn,'F')
import os
try:
os.startfile(fn)
except:
os.system("xdg-open \"%s\"" % fn)
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

+210
View File
@@ -0,0 +1,210 @@
'barcode';'BC';20.30;246.80;140.30;254.30;'Interleaved 2of5 NT';0.75;0;0;0;0;0;'I';'200000000001000159053338016581200810081';3
'barcode_readable';'T';19.30;253.30;140.30;260.30;'Arial';10.00;0;0;0;0;0;'I';'200000000001000159053338016581200810081';3
'box';'B';15.30;15.30;185.30;260.30;'Arial';0.00;0;0;0;0;0;'I';None;0
'box_x';'B';95.30;15.30;105.30;25.30;'Arial';0.00;1;0;0;0;0;'I';None;2
'company_footer1';'T';115.30;45.30;175.30;50.30;'Arial';10.00;0;0;0;0;0;'I';'Company footer 1';2
'company_footer2';'T';115.30;50.30;175.30;55.30;'Arial';10.00;0;0;0;0;0;'I';'Company footer 2';2
'company_header1';'T';17.30;40.30;85.30;45.30;'Arial';10.00;0;0;0;0;0;'I';'Company header 1';2
'company_header2';'T';17.30;45.30;85.30;50.30;'Arial';10.00;0;0;0;0;0;'I';'Company header 2';2
'company_logo';'I';20.30;17.30;55.70;30.30;None;0.00;0;0;0;0;0;'I';'tutorial/logo.png';2
'company_name';'T';17.30;32.80;98.30;37.80;'Arial';12.00;1;0;0;0;0;'I';'Company name';2
'currency';'T';42.30;90.30;67.30;94.30;'Arial';10.00;0;0;0;0;65535;'I';'U.S.D.';0
'currency_l';'T';17.30;90.30;65.30;94.30;'Arial';10.00;0;0;0;0;0;'I';'Currency:';0
'customer_address';'T';35.30;64.30;160.30;70.30;'Arial';10.00;0;0;0;0;65535;'I';None;0
'customer_address_l';'t';17.30;64.30;35.30;70.30;'Arial';10.00;0;0;0;0;0;'I';'Address:';0
'customer_city';'T';133.30;69.30;175.30;75.30;'Arial';10.00;0;0;0;0;65535;'I';None;0
'customer_city_l';'T';115.30;69.30;133.30;75.30;'Arial';10.00;0;0;0;0;0;'I';'City:';0
'customer_country';'T';133.30;73.30;175.30;79.30;'Arial';10.00;0;0;0;0;65535;'I';None;0
'customer_name';'T';35.30;59.30;175.30;65.30;'Arial';10.00;0;0;0;0;65535;'I';None;0
'customer_name_l';'T';17.30;59.30;30.30;65.30;'Arial';10.00;0;0;0;0;0;'I';'Bill to:';0
'customer_phone';'T';35.30;69.30;115.30;75.30;'Arial';10.00;0;0;0;0;65535;'I';None;0
'customer_phone_l';'T';17.30;69.30;35.30;75.30;'Arial';10.00;0;0;0;0;0;'I';'Phone/Fax:';0
'customer_taxid';'T';135.30;74.30;175.30;79.30;'Arial';10.00;0;0;0;0;65535;'I';None;0
'customer_taxid_l';'T';115.30;74.30;135.30;79.30;'Arial';10.00;0;0;0;0;0;'I';'Tax ID:';0
'customer_vat';'T';35.30;74.30;105.30;79.30;'Arial';10.00;0;0;0;0;0;'I';None;0
'customer_vat_l';'T';17.30;74.30;32.30;79.30;'Arial';10.00;0;0;0;0;0;'I';'VAT:';0
'document_copy';'T';105.30;21.30;140.30;25.30;'Arial';8.00;0;0;0;0;0;'C';'Original';2
'document_label';'T';105.30;15.90;180.30;21.10;'Arial Black';13.00;0;0;0;0;0;'C';'INVOICE';2
'document_number';'T';115.30;27.80;125.30;33.30;'Arial';14.00;1;0;0;0;0;'I';'N\xba: ';2
'document_type';'T';95.30;16.10;105.30;24.30;'Arial';16.00;1;0;0;0;0;'C';'X';2
'due_date';'T';65.30;82.30;85.30;86.30;'Arial';10.00;0;0;0;0;65535;'I';'31/12/2009';0
'due_date_l';'T';17.30;82.30;65.30;86.30;'Arial';10.00;0;0;0;0;0;'I';'Due Date:';0
'issue_date';'T';135.30;33.30;175.30;40.30;'Arial';12.00;0;0;0;0;65535;'I';None;0
'issue_date_l';'T';115.30;33.30;175.30;40.30;'Arial';12.00;0;0;0;0;0;'I';'Date:';0
'item_amount';'T';160.30;97.30;185.30;102.30;'Arial';10.00;0;0;0;0;65535;'C';'Amount';0
'item_amount01';'T';160.30;103.30;183.30;108.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_amount02';'T';160.30;108.30;183.30;113.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_amount03';'T';160.30;113.30;183.30;118.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_amount04';'T';160.30;118.30;183.30;123.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_amount05';'T';160.30;123.30;183.30;128.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_amount06';'T';160.30;128.30;183.30;133.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_amount07';'T';160.30;133.30;183.30;138.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_amount08';'T';160.30;138.30;183.30;143.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_amount09';'T';160.30;143.30;183.30;148.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_amount10';'T';160.30;148.30;183.30;153.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_amount11';'T';160.30;153.30;183.30;158.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_amount12';'T';160.30;158.30;183.30;163.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_amount13';'T';160.30;163.30;183.30;168.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_amount14';'T';160.30;168.30;183.30;173.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_amount15';'T';160.30;173.30;183.30;178.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_amount16';'T';160.30;178.30;183.30;183.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_amount17';'T';160.30;183.30;183.30;188.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_amount18';'T';160.30;188.30;183.30;193.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_amount19';'T';160.30;193.30;183.30;198.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_amount20';'T';160.30;198.30;183.30;203.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_amount21';'T';160.30;203.30;183.30;208.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_amount22';'T';160.30;208.30;183.30;213.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_amount23';'T';160.30;213.30;183.30;218.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_amount24';'T';160.30;218.30;183.30;223.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_amount25';'T';160.30;223.30;183.30;228.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_code';'T';30.30;97.30;45.30;102.30;'Arial';10.00;0;0;0;0;65535;'C';'Cod.';0
'item_code01';'T';30.30;103.30;43.30;108.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_code02';'T';30.30;108.30;43.30;113.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_code03';'T';30.30;113.30;43.30;118.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_code04';'T';30.30;118.30;43.30;123.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_code05';'T';30.30;123.30;43.30;128.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_code06';'T';30.30;128.30;43.30;133.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_code07';'T';30.30;133.30;43.30;138.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_code08';'T';30.30;138.30;43.30;143.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_code09';'T';30.30;143.30;43.30;148.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_code10';'T';30.30;148.30;43.30;153.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_code11';'T';30.30;153.30;43.30;158.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_code12';'T';30.30;158.30;43.30;163.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_code13';'T';30.30;163.30;43.30;168.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_code14';'T';30.30;168.30;43.30;173.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_code15';'T';30.30;173.30;43.30;178.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_code16';'T';30.30;178.30;43.30;183.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_code17';'T';30.30;183.30;43.30;188.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_code18';'T';30.30;188.30;43.30;193.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_code19';'T';30.30;193.30;43.30;198.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_code20';'T';30.30;198.30;43.30;203.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_code21';'T';30.30;203.30;43.30;208.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_code22';'T';30.30;208.30;43.30;213.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_code23';'T';30.30;213.30;43.30;218.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_code24';'T';30.30;218.30;43.30;223.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_code25';'T';30.30;223.30;43.30;228.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_description';'T';45.30;97.30;140.30;102.30;'Arial';10.00;0;0;0;0;65535;'C';'Description';0
'item_description01';'T';47.30;103.30;138.30;108.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_description02';'T';47.30;108.30;138.30;113.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_description03';'T';47.30;113.30;138.30;118.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_description04';'T';47.30;118.30;138.30;123.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_description05';'T';47.30;123.30;138.30;128.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_description06';'T';47.30;128.30;138.30;133.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_description07';'T';47.30;133.30;138.30;138.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_description08';'T';47.30;138.30;138.30;143.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_description09';'T';47.30;143.30;138.30;148.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_description10';'T';47.30;148.30;138.30;153.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_description11';'T';47.30;153.30;138.30;158.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_description12';'T';47.30;158.30;138.30;163.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_description13';'T';47.30;163.30;138.30;168.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_description14';'T';47.30;168.30;138.30;173.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_description15';'T';47.30;173.30;138.30;178.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_description16';'T';47.30;178.30;138.30;183.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_description17';'T';47.30;183.30;138.30;188.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_description18';'T';47.30;188.30;138.30;193.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_description19';'T';47.30;193.30;138.30;198.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_description20';'T';47.30;198.30;138.30;203.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_description21';'T';47.30;203.30;138.30;208.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_description22';'T';47.30;208.30;138.30;213.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_description23';'T';47.30;213.30;138.30;218.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_description24';'T';47.30;218.30;138.30;223.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_description25';'T';47.30;223.30;138.30;228.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_price';'T';140.30;97.30;160.30;102.30;'Arial';10.00;0;0;0;0;65535;'C';'Price';0
'item_price01';'T';140.30;103.30;158.30;108.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_price02';'T';140.30;108.30;158.30;113.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_price03';'T';140.30;113.30;158.30;118.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_price04';'T';140.30;118.30;158.30;123.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_price05';'T';140.30;123.30;158.30;128.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_price06';'T';140.30;128.30;158.30;133.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_price07';'T';140.30;133.30;158.30;138.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_price08';'T';140.30;138.30;158.30;143.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_price09';'T';140.30;143.30;158.30;148.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_price10';'T';140.30;148.30;158.30;153.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_price11';'T';140.30;153.30;158.30;158.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_price12';'T';140.30;158.30;158.30;163.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_price13';'T';140.30;163.30;158.30;168.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_price14';'T';140.30;168.30;158.30;173.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_price15';'T';140.30;173.30;158.30;178.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_price16';'T';140.30;178.30;158.30;183.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_price17';'T';140.30;183.30;158.30;188.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_price18';'T';140.30;188.30;158.30;193.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_price19';'T';140.30;193.30;158.30;198.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_price20';'T';140.30;198.30;158.30;203.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_price21';'T';140.30;203.30;158.30;208.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_price22';'T';140.30;208.30;158.30;213.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_price23';'T';140.30;213.30;158.30;218.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_price24';'T';140.30;218.30;158.30;223.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_price25';'T';140.30;223.30;158.30;228.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_quantity';'T';15.30;97.30;30.30;102.30;'Arial';10.00;0;0;0;0;65535;'C';'Qty.';0
'item_quantity01';'T';15.30;103.30;25.30;108.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_quantity02';'T';15.30;108.30;25.30;113.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_quantity03';'T';15.30;113.30;25.30;118.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_quantity04';'T';15.30;118.30;25.30;123.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_quantity05';'T';15.30;123.30;25.30;128.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_quantity06';'T';15.30;128.30;25.30;133.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_quantity07';'T';15.30;133.30;25.30;138.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_quantity08';'T';15.30;138.30;25.30;143.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_quantity09';'T';15.30;143.30;25.30;148.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_quantity10';'T';15.30;148.30;25.30;153.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_quantity11';'T';15.30;153.30;25.30;158.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_quantity12';'T';15.30;158.30;25.30;163.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_quantity13';'T';15.30;163.30;25.30;168.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_quantity14';'T';15.30;168.30;25.30;173.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_quantity15';'T';15.30;173.30;25.30;178.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_quantity16';'T';15.30;178.30;25.30;183.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_quantity17';'T';15.30;183.30;25.30;188.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_quantity18';'T';15.30;188.30;25.30;193.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_quantity19';'T';15.30;193.30;25.30;198.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_quantity20';'T';15.30;198.30;25.30;203.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_quantity21';'T';15.30;203.30;25.30;208.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_quantity22';'T';15.30;208.30;25.30;213.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_quantity23';'T';15.30;213.30;25.30;218.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_quantity24';'T';15.30;218.30;25.30;223.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_quantity25';'T';15.30;223.30;25.30;228.30;'Arial';10.00;0;0;0;0;65535;'D';'';0
'item_unit01';'T';24.30;103.30;30.30;108.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_unit02';'T';24.30;108.30;30.30;113.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_unit03';'T';24.30;113.30;30.30;118.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_unit04';'T';24.30;118.30;30.30;123.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_unit05';'T';24.30;123.30;30.30;128.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_unit06';'T';24.30;128.30;30.30;133.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_unit07';'T';24.30;133.30;30.30;138.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_unit08';'T';24.30;138.30;30.30;143.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_unit09';'T';24.30;143.30;30.30;148.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_unit10';'T';24.30;148.30;30.30;153.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_unit11';'T';24.30;153.30;30.30;158.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_unit12';'T';24.30;158.30;30.30;163.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_unit13';'T';24.30;163.30;30.30;168.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_unit14';'T';24.30;168.30;30.30;173.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_unit15';'T';24.30;173.30;30.30;178.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_unit16';'T';24.30;178.30;30.30;183.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_unit17';'T';24.30;183.30;30.30;188.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_unit18';'T';24.30;188.30;30.30;193.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_unit19';'T';24.30;193.30;30.30;198.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_unit20';'T';24.30;198.30;30.30;203.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_unit21';'T';24.30;203.30;30.30;208.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_unit22';'T';24.30;208.30;30.30;213.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_unit23';'T';24.30;213.30;30.30;218.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_unit24';'T';24.30;218.30;30.30;223.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'item_unit25';'T';24.30;223.30;30.30;228.30;'Arial';10.00;0;0;0;0;65535;'I';'';0
'line1';'L';100.30;25.30;100.30;57.30;'Arial';0;0;0;0;0;0;'I';None;3
'line2';'L';15.30;57.30;185.30;57.30;None;0.00;0;0;0;0;0;'I';None;3
'line3';'L';15.30;80.30;185.30;80.30;None;0.00;0;0;0;0;0;'I';None;3
'line5';'L';15.30;95.30;185.30;95.30;None;0.00;0;0;0;0;0;'I';None;3
'line6';'L';15.30;230.30;185.30;230.30;None;0.00;0;0;0;0;0;'I';None;3
'line9';'L';15.30;102.30;185.30;102.30;None;0.00;0;0;0;0;0;'I';None;0
'line_cod';'L';45.30;95.30;45.30;230.30;None;0.00;0;0;0;0;0;'I';None;3
'line_desc';'L';140.30;95.30;140.30;230.30;None;0.00;0;0;0;0;0;'I';None;3
'line_price';'L';160.30;95.30;160.30;230.30;None;0.00;0;0;0;0;0;'I';None;3
'line_qty';'L';30.30;95.30;30.30;230.30;None;0.00;0;0;0;0;0;'I';None;3
'net';'T';145.30;234.30;178.30;243.30;'Arial';12.00;1;0;0;0;65535;'D';None;0
'net_l';'T';105.30;234.30;150.30;243.30;'Arial';12.00;0;0;0;0;0;'D';'NET:';0
'number';'T';125.30;25.80;185.30;35.30;'Arial';14.00;1;0;0;0;0;'I';'0000-00000000';2
'page';'T';140.30;21.30;180.30;25.30;'Arial';8.00;0;0;0;0;0;'C';'Page';2
'payment';'T';45.30;86.30;150.30;90.30;'Arial';10.00;0;0;0;0;65535;'I';'cash $';0
'payment_l';'T';17.30;86.30;45.30;90.30;'Arial';10.00;0;0;0;0;0;'I';'Payment terms:';0
'total';'T';105.30;251.30;178.30;260.30;'Arial';12.00;1;0;0;0;65535;'D';None;0
'total_box';'B';155.30;252.30;180.30;259.30;None;0.00;0;0;0;0;0;'I';None;0
'total_label';'T';125.30;251.30;150.30;260.30;'Arial';12.00;0;0;0;0;0;'D';'Total:';0
'vat';'T';145.30;241.30;178.30;250.30;'Arial';12.00;1;0;0;0;65535;'D';None;0
'vat';'T';115.30;40.30;175.30;45.30;'Arial';10.00;0;0;0;0;0;'I';'Tax or Vat number';2
'vat_l';'T';125.30;241.30;150.30;250.30;'Arial';12.00;0;0;0;0;0;'D';'VAT 21%:';0
1 'barcode' 'BC' 20.30 246.80 140.30 254.30 'Interleaved 2of5 NT' 0.75 0 0 0 0 0 'I' '200000000001000159053338016581200810081' 3
2 'barcode_readable' 'T' 19.30 253.30 140.30 260.30 'Arial' 10.00 0 0 0 0 0 'I' '200000000001000159053338016581200810081' 3
3 'box' 'B' 15.30 15.30 185.30 260.30 'Arial' 0.00 0 0 0 0 0 'I' None 0
4 'box_x' 'B' 95.30 15.30 105.30 25.30 'Arial' 0.00 1 0 0 0 0 'I' None 2
5 'company_footer1' 'T' 115.30 45.30 175.30 50.30 'Arial' 10.00 0 0 0 0 0 'I' 'Company footer 1' 2
6 'company_footer2' 'T' 115.30 50.30 175.30 55.30 'Arial' 10.00 0 0 0 0 0 'I' 'Company footer 2' 2
7 'company_header1' 'T' 17.30 40.30 85.30 45.30 'Arial' 10.00 0 0 0 0 0 'I' 'Company header 1' 2
8 'company_header2' 'T' 17.30 45.30 85.30 50.30 'Arial' 10.00 0 0 0 0 0 'I' 'Company header 2' 2
9 'company_logo' 'I' 20.30 17.30 55.70 30.30 None 0.00 0 0 0 0 0 'I' 'tutorial/logo.png' 2
10 'company_name' 'T' 17.30 32.80 98.30 37.80 'Arial' 12.00 1 0 0 0 0 'I' 'Company name' 2
11 'currency' 'T' 42.30 90.30 67.30 94.30 'Arial' 10.00 0 0 0 0 65535 'I' 'U.S.D.' 0
12 'currency_l' 'T' 17.30 90.30 65.30 94.30 'Arial' 10.00 0 0 0 0 0 'I' 'Currency:' 0
13 'customer_address' 'T' 35.30 64.30 160.30 70.30 'Arial' 10.00 0 0 0 0 65535 'I' None 0
14 'customer_address_l' 't' 17.30 64.30 35.30 70.30 'Arial' 10.00 0 0 0 0 0 'I' 'Address:' 0
15 'customer_city' 'T' 133.30 69.30 175.30 75.30 'Arial' 10.00 0 0 0 0 65535 'I' None 0
16 'customer_city_l' 'T' 115.30 69.30 133.30 75.30 'Arial' 10.00 0 0 0 0 0 'I' 'City:' 0
17 'customer_country' 'T' 133.30 73.30 175.30 79.30 'Arial' 10.00 0 0 0 0 65535 'I' None 0
18 'customer_name' 'T' 35.30 59.30 175.30 65.30 'Arial' 10.00 0 0 0 0 65535 'I' None 0
19 'customer_name_l' 'T' 17.30 59.30 30.30 65.30 'Arial' 10.00 0 0 0 0 0 'I' 'Bill to:' 0
20 'customer_phone' 'T' 35.30 69.30 115.30 75.30 'Arial' 10.00 0 0 0 0 65535 'I' None 0
21 'customer_phone_l' 'T' 17.30 69.30 35.30 75.30 'Arial' 10.00 0 0 0 0 0 'I' 'Phone/Fax:' 0
22 'customer_taxid' 'T' 135.30 74.30 175.30 79.30 'Arial' 10.00 0 0 0 0 65535 'I' None 0
23 'customer_taxid_l' 'T' 115.30 74.30 135.30 79.30 'Arial' 10.00 0 0 0 0 0 'I' 'Tax ID:' 0
24 'customer_vat' 'T' 35.30 74.30 105.30 79.30 'Arial' 10.00 0 0 0 0 0 'I' None 0
25 'customer_vat_l' 'T' 17.30 74.30 32.30 79.30 'Arial' 10.00 0 0 0 0 0 'I' 'VAT:' 0
26 'document_copy' 'T' 105.30 21.30 140.30 25.30 'Arial' 8.00 0 0 0 0 0 'C' 'Original' 2
27 'document_label' 'T' 105.30 15.90 180.30 21.10 'Arial Black' 13.00 0 0 0 0 0 'C' 'INVOICE' 2
28 'document_number' 'T' 115.30 27.80 125.30 33.30 'Arial' 14.00 1 0 0 0 0 'I' 'N\xba: ' 2
29 'document_type' 'T' 95.30 16.10 105.30 24.30 'Arial' 16.00 1 0 0 0 0 'C' 'X' 2
30 'due_date' 'T' 65.30 82.30 85.30 86.30 'Arial' 10.00 0 0 0 0 65535 'I' '31/12/2009' 0
31 'due_date_l' 'T' 17.30 82.30 65.30 86.30 'Arial' 10.00 0 0 0 0 0 'I' 'Due Date:' 0
32 'issue_date' 'T' 135.30 33.30 175.30 40.30 'Arial' 12.00 0 0 0 0 65535 'I' None 0
33 'issue_date_l' 'T' 115.30 33.30 175.30 40.30 'Arial' 12.00 0 0 0 0 0 'I' 'Date:' 0
34 'item_amount' 'T' 160.30 97.30 185.30 102.30 'Arial' 10.00 0 0 0 0 65535 'C' 'Amount' 0
35 'item_amount01' 'T' 160.30 103.30 183.30 108.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
36 'item_amount02' 'T' 160.30 108.30 183.30 113.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
37 'item_amount03' 'T' 160.30 113.30 183.30 118.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
38 'item_amount04' 'T' 160.30 118.30 183.30 123.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
39 'item_amount05' 'T' 160.30 123.30 183.30 128.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
40 'item_amount06' 'T' 160.30 128.30 183.30 133.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
41 'item_amount07' 'T' 160.30 133.30 183.30 138.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
42 'item_amount08' 'T' 160.30 138.30 183.30 143.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
43 'item_amount09' 'T' 160.30 143.30 183.30 148.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
44 'item_amount10' 'T' 160.30 148.30 183.30 153.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
45 'item_amount11' 'T' 160.30 153.30 183.30 158.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
46 'item_amount12' 'T' 160.30 158.30 183.30 163.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
47 'item_amount13' 'T' 160.30 163.30 183.30 168.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
48 'item_amount14' 'T' 160.30 168.30 183.30 173.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
49 'item_amount15' 'T' 160.30 173.30 183.30 178.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
50 'item_amount16' 'T' 160.30 178.30 183.30 183.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
51 'item_amount17' 'T' 160.30 183.30 183.30 188.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
52 'item_amount18' 'T' 160.30 188.30 183.30 193.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
53 'item_amount19' 'T' 160.30 193.30 183.30 198.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
54 'item_amount20' 'T' 160.30 198.30 183.30 203.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
55 'item_amount21' 'T' 160.30 203.30 183.30 208.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
56 'item_amount22' 'T' 160.30 208.30 183.30 213.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
57 'item_amount23' 'T' 160.30 213.30 183.30 218.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
58 'item_amount24' 'T' 160.30 218.30 183.30 223.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
59 'item_amount25' 'T' 160.30 223.30 183.30 228.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
60 'item_code' 'T' 30.30 97.30 45.30 102.30 'Arial' 10.00 0 0 0 0 65535 'C' 'Cod.' 0
61 'item_code01' 'T' 30.30 103.30 43.30 108.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
62 'item_code02' 'T' 30.30 108.30 43.30 113.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
63 'item_code03' 'T' 30.30 113.30 43.30 118.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
64 'item_code04' 'T' 30.30 118.30 43.30 123.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
65 'item_code05' 'T' 30.30 123.30 43.30 128.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
66 'item_code06' 'T' 30.30 128.30 43.30 133.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
67 'item_code07' 'T' 30.30 133.30 43.30 138.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
68 'item_code08' 'T' 30.30 138.30 43.30 143.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
69 'item_code09' 'T' 30.30 143.30 43.30 148.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
70 'item_code10' 'T' 30.30 148.30 43.30 153.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
71 'item_code11' 'T' 30.30 153.30 43.30 158.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
72 'item_code12' 'T' 30.30 158.30 43.30 163.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
73 'item_code13' 'T' 30.30 163.30 43.30 168.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
74 'item_code14' 'T' 30.30 168.30 43.30 173.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
75 'item_code15' 'T' 30.30 173.30 43.30 178.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
76 'item_code16' 'T' 30.30 178.30 43.30 183.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
77 'item_code17' 'T' 30.30 183.30 43.30 188.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
78 'item_code18' 'T' 30.30 188.30 43.30 193.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
79 'item_code19' 'T' 30.30 193.30 43.30 198.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
80 'item_code20' 'T' 30.30 198.30 43.30 203.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
81 'item_code21' 'T' 30.30 203.30 43.30 208.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
82 'item_code22' 'T' 30.30 208.30 43.30 213.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
83 'item_code23' 'T' 30.30 213.30 43.30 218.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
84 'item_code24' 'T' 30.30 218.30 43.30 223.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
85 'item_code25' 'T' 30.30 223.30 43.30 228.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
86 'item_description' 'T' 45.30 97.30 140.30 102.30 'Arial' 10.00 0 0 0 0 65535 'C' 'Description' 0
87 'item_description01' 'T' 47.30 103.30 138.30 108.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
88 'item_description02' 'T' 47.30 108.30 138.30 113.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
89 'item_description03' 'T' 47.30 113.30 138.30 118.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
90 'item_description04' 'T' 47.30 118.30 138.30 123.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
91 'item_description05' 'T' 47.30 123.30 138.30 128.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
92 'item_description06' 'T' 47.30 128.30 138.30 133.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
93 'item_description07' 'T' 47.30 133.30 138.30 138.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
94 'item_description08' 'T' 47.30 138.30 138.30 143.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
95 'item_description09' 'T' 47.30 143.30 138.30 148.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
96 'item_description10' 'T' 47.30 148.30 138.30 153.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
97 'item_description11' 'T' 47.30 153.30 138.30 158.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
98 'item_description12' 'T' 47.30 158.30 138.30 163.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
99 'item_description13' 'T' 47.30 163.30 138.30 168.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
100 'item_description14' 'T' 47.30 168.30 138.30 173.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
101 'item_description15' 'T' 47.30 173.30 138.30 178.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
102 'item_description16' 'T' 47.30 178.30 138.30 183.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
103 'item_description17' 'T' 47.30 183.30 138.30 188.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
104 'item_description18' 'T' 47.30 188.30 138.30 193.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
105 'item_description19' 'T' 47.30 193.30 138.30 198.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
106 'item_description20' 'T' 47.30 198.30 138.30 203.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
107 'item_description21' 'T' 47.30 203.30 138.30 208.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
108 'item_description22' 'T' 47.30 208.30 138.30 213.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
109 'item_description23' 'T' 47.30 213.30 138.30 218.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
110 'item_description24' 'T' 47.30 218.30 138.30 223.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
111 'item_description25' 'T' 47.30 223.30 138.30 228.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
112 'item_price' 'T' 140.30 97.30 160.30 102.30 'Arial' 10.00 0 0 0 0 65535 'C' 'Price' 0
113 'item_price01' 'T' 140.30 103.30 158.30 108.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
114 'item_price02' 'T' 140.30 108.30 158.30 113.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
115 'item_price03' 'T' 140.30 113.30 158.30 118.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
116 'item_price04' 'T' 140.30 118.30 158.30 123.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
117 'item_price05' 'T' 140.30 123.30 158.30 128.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
118 'item_price06' 'T' 140.30 128.30 158.30 133.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
119 'item_price07' 'T' 140.30 133.30 158.30 138.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
120 'item_price08' 'T' 140.30 138.30 158.30 143.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
121 'item_price09' 'T' 140.30 143.30 158.30 148.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
122 'item_price10' 'T' 140.30 148.30 158.30 153.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
123 'item_price11' 'T' 140.30 153.30 158.30 158.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
124 'item_price12' 'T' 140.30 158.30 158.30 163.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
125 'item_price13' 'T' 140.30 163.30 158.30 168.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
126 'item_price14' 'T' 140.30 168.30 158.30 173.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
127 'item_price15' 'T' 140.30 173.30 158.30 178.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
128 'item_price16' 'T' 140.30 178.30 158.30 183.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
129 'item_price17' 'T' 140.30 183.30 158.30 188.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
130 'item_price18' 'T' 140.30 188.30 158.30 193.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
131 'item_price19' 'T' 140.30 193.30 158.30 198.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
132 'item_price20' 'T' 140.30 198.30 158.30 203.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
133 'item_price21' 'T' 140.30 203.30 158.30 208.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
134 'item_price22' 'T' 140.30 208.30 158.30 213.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
135 'item_price23' 'T' 140.30 213.30 158.30 218.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
136 'item_price24' 'T' 140.30 218.30 158.30 223.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
137 'item_price25' 'T' 140.30 223.30 158.30 228.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
138 'item_quantity' 'T' 15.30 97.30 30.30 102.30 'Arial' 10.00 0 0 0 0 65535 'C' 'Qty.' 0
139 'item_quantity01' 'T' 15.30 103.30 25.30 108.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
140 'item_quantity02' 'T' 15.30 108.30 25.30 113.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
141 'item_quantity03' 'T' 15.30 113.30 25.30 118.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
142 'item_quantity04' 'T' 15.30 118.30 25.30 123.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
143 'item_quantity05' 'T' 15.30 123.30 25.30 128.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
144 'item_quantity06' 'T' 15.30 128.30 25.30 133.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
145 'item_quantity07' 'T' 15.30 133.30 25.30 138.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
146 'item_quantity08' 'T' 15.30 138.30 25.30 143.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
147 'item_quantity09' 'T' 15.30 143.30 25.30 148.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
148 'item_quantity10' 'T' 15.30 148.30 25.30 153.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
149 'item_quantity11' 'T' 15.30 153.30 25.30 158.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
150 'item_quantity12' 'T' 15.30 158.30 25.30 163.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
151 'item_quantity13' 'T' 15.30 163.30 25.30 168.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
152 'item_quantity14' 'T' 15.30 168.30 25.30 173.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
153 'item_quantity15' 'T' 15.30 173.30 25.30 178.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
154 'item_quantity16' 'T' 15.30 178.30 25.30 183.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
155 'item_quantity17' 'T' 15.30 183.30 25.30 188.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
156 'item_quantity18' 'T' 15.30 188.30 25.30 193.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
157 'item_quantity19' 'T' 15.30 193.30 25.30 198.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
158 'item_quantity20' 'T' 15.30 198.30 25.30 203.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
159 'item_quantity21' 'T' 15.30 203.30 25.30 208.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
160 'item_quantity22' 'T' 15.30 208.30 25.30 213.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
161 'item_quantity23' 'T' 15.30 213.30 25.30 218.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
162 'item_quantity24' 'T' 15.30 218.30 25.30 223.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
163 'item_quantity25' 'T' 15.30 223.30 25.30 228.30 'Arial' 10.00 0 0 0 0 65535 'D' '' 0
164 'item_unit01' 'T' 24.30 103.30 30.30 108.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
165 'item_unit02' 'T' 24.30 108.30 30.30 113.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
166 'item_unit03' 'T' 24.30 113.30 30.30 118.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
167 'item_unit04' 'T' 24.30 118.30 30.30 123.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
168 'item_unit05' 'T' 24.30 123.30 30.30 128.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
169 'item_unit06' 'T' 24.30 128.30 30.30 133.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
170 'item_unit07' 'T' 24.30 133.30 30.30 138.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
171 'item_unit08' 'T' 24.30 138.30 30.30 143.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
172 'item_unit09' 'T' 24.30 143.30 30.30 148.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
173 'item_unit10' 'T' 24.30 148.30 30.30 153.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
174 'item_unit11' 'T' 24.30 153.30 30.30 158.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
175 'item_unit12' 'T' 24.30 158.30 30.30 163.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
176 'item_unit13' 'T' 24.30 163.30 30.30 168.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
177 'item_unit14' 'T' 24.30 168.30 30.30 173.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
178 'item_unit15' 'T' 24.30 173.30 30.30 178.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
179 'item_unit16' 'T' 24.30 178.30 30.30 183.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
180 'item_unit17' 'T' 24.30 183.30 30.30 188.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
181 'item_unit18' 'T' 24.30 188.30 30.30 193.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
182 'item_unit19' 'T' 24.30 193.30 30.30 198.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
183 'item_unit20' 'T' 24.30 198.30 30.30 203.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
184 'item_unit21' 'T' 24.30 203.30 30.30 208.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
185 'item_unit22' 'T' 24.30 208.30 30.30 213.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
186 'item_unit23' 'T' 24.30 213.30 30.30 218.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
187 'item_unit24' 'T' 24.30 218.30 30.30 223.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
188 'item_unit25' 'T' 24.30 223.30 30.30 228.30 'Arial' 10.00 0 0 0 0 65535 'I' '' 0
189 'line1' 'L' 100.30 25.30 100.30 57.30 'Arial' 0 0 0 0 0 0 'I' None 3
190 'line2' 'L' 15.30 57.30 185.30 57.30 None 0.00 0 0 0 0 0 'I' None 3
191 'line3' 'L' 15.30 80.30 185.30 80.30 None 0.00 0 0 0 0 0 'I' None 3
192 'line5' 'L' 15.30 95.30 185.30 95.30 None 0.00 0 0 0 0 0 'I' None 3
193 'line6' 'L' 15.30 230.30 185.30 230.30 None 0.00 0 0 0 0 0 'I' None 3
194 'line9' 'L' 15.30 102.30 185.30 102.30 None 0.00 0 0 0 0 0 'I' None 0
195 'line_cod' 'L' 45.30 95.30 45.30 230.30 None 0.00 0 0 0 0 0 'I' None 3
196 'line_desc' 'L' 140.30 95.30 140.30 230.30 None 0.00 0 0 0 0 0 'I' None 3
197 'line_price' 'L' 160.30 95.30 160.30 230.30 None 0.00 0 0 0 0 0 'I' None 3
198 'line_qty' 'L' 30.30 95.30 30.30 230.30 None 0.00 0 0 0 0 0 'I' None 3
199 'net' 'T' 145.30 234.30 178.30 243.30 'Arial' 12.00 1 0 0 0 65535 'D' None 0
200 'net_l' 'T' 105.30 234.30 150.30 243.30 'Arial' 12.00 0 0 0 0 0 'D' 'NET:' 0
201 'number' 'T' 125.30 25.80 185.30 35.30 'Arial' 14.00 1 0 0 0 0 'I' '0000-00000000' 2
202 'page' 'T' 140.30 21.30 180.30 25.30 'Arial' 8.00 0 0 0 0 0 'C' 'Page' 2
203 'payment' 'T' 45.30 86.30 150.30 90.30 'Arial' 10.00 0 0 0 0 65535 'I' 'cash $' 0
204 'payment_l' 'T' 17.30 86.30 45.30 90.30 'Arial' 10.00 0 0 0 0 0 'I' 'Payment terms:' 0
205 'total' 'T' 105.30 251.30 178.30 260.30 'Arial' 12.00 1 0 0 0 65535 'D' None 0
206 'total_box' 'B' 155.30 252.30 180.30 259.30 None 0.00 0 0 0 0 0 'I' None 0
207 'total_label' 'T' 125.30 251.30 150.30 260.30 'Arial' 12.00 0 0 0 0 0 'D' 'Total:' 0
208 'vat' 'T' 145.30 241.30 178.30 250.30 'Arial' 12.00 1 0 0 0 65535 'D' None 0
209 'vat' 'T' 115.30 40.30 175.30 45.30 'Arial' 10.00 0 0 0 0 0 'I' 'Tax or Vat number' 2
210 'vat_l' 'T' 125.30 241.30 150.30 250.30 'Arial' 12.00 0 0 0 0 0 'D' 'VAT 21%:' 0
+120
View File
@@ -0,0 +1,120 @@
# -*- coding: iso-8859-1 -*-
"PDF Template Helper for FPDF.py"
__author__ = "Mariano Reingart <reingart@gmail.com>"
__copyright__ = "Copyright (C) 2010 Mariano Reingart"
__license__ = "LGPL 3.0"
import sys, os
from fpdf import Template
if __name__ == "__main__":
# generate sample invoice (according Argentina's regulations)
import random
from decimal import Decimal
f = Template(format="A4",
title="Sample Invoice", author="Sample Company",
subject="Sample Customer", keywords="Electronic TAX Invoice")
f.parse_csv(infile="invoice.csv", delimiter=";", decimal_sep=",")
detail = "Lorem ipsum dolor sit amet, consectetur. " * 30
items = []
for i in range(1, 30):
ds = "Sample product %s" % i
qty = random.randint(1,10)
price = round(random.random()*100,3)
code = "%s%s%02d" % (chr(random.randint(65,90)), chr(random.randint(65,90)),i)
items.append(dict(code=code, unit='u',
qty=qty, price=price,
amount=qty*price,
ds="%s: %s" % (i,ds)))
# divide and count lines
lines = 0
li_items = []
for it in items:
qty = it['qty']
code = it['code']
unit = it['unit']
for ds in f.split_multicell(it['ds'], 'item_description01'):
# add item description line (without price nor amount)
li_items.append(dict(code=code, ds=ds, qty=qty, unit=unit, price=None, amount=None))
# clean qty and code (show only at first)
unit = qty = code = None
# set last item line price and amount
li_items[-1].update(amount = it['amount'],
price = it['price'])
obs="\n<U>Detail:</U>\n\n" + detail
for ds in f.split_multicell(obs, 'item_description01'):
li_items.append(dict(code=code, ds=ds, qty=qty, unit=unit, price=None, amount=None))
# calculate pages:
lines = len(li_items)
max_lines_per_page = 24
pages = int(lines / (max_lines_per_page - 1))
if lines % (max_lines_per_page - 1): pages = pages + 1
# completo campos y hojas
for page in range(1, int(pages)+1):
f.add_page()
f['page'] = 'Page %s of %s' % (page, pages)
if pages>1 and page<pages:
s = 'Continues on page %s' % (page+1)
else:
s = ''
f['item_description%02d' % (max_lines_per_page+1)] = s
f["company_name"] = "Sample Company"
f["company_logo"] = "../tutorial/logo.png"
f["company_header1"] = "Some Address - somewhere -"
f["company_header2"] = "http://www.example.com"
f["company_footer1"] = "Tax Code ..."
f["company_footer2"] = "Tax/VAT ID ..."
f['number'] = '0001-00001234'
f['issue_date'] = '2010-09-10'
f['due_date'] = '2099-09-10'
f['customer_name'] = "Sample Client"
f['customer_address'] = "Siempreviva 1234"
# print line item...
li = 0
k = 0
total = Decimal("0.00")
for it in li_items:
k = k + 1
if k > page * (max_lines_per_page - 1):
break
if it['amount']:
total += Decimal("%.6f" % it['amount'])
if k > (page - 1) * (max_lines_per_page - 1):
li += 1
if it['qty'] is not None:
f['item_quantity%02d' % li] = it['qty']
if it['code'] is not None:
f['item_code%02d' % li] = it['code']
if it['unit'] is not None:
f['item_unit%02d' % li] = it['unit']
f['item_description%02d' % li] = it['ds']
if it['price'] is not None:
f['item_price%02d' % li] = "%0.3f" % it['price']
if it['amount'] is not None:
f['item_amount%02d' % li] = "%0.2f" % it['amount']
if pages == page:
f['net'] = "%0.2f" % (total/Decimal("1.21"))
f['vat'] = "%0.2f" % (total*(1-1/Decimal("1.21")))
f['total_label'] = 'Total:'
else:
f['total_label'] = 'SubTotal:'
f['total'] = "%0.2f" % total
f.render("./invoice.pdf")
if sys.platform.startswith("linux"):
os.system("evince ./invoice.pdf")
else:
os.startfile("./invoice.pdf")
@@ -0,0 +1,19 @@
"Test images flow mode (cell-like, trigger page breaks)"
from fpdf import FPDF, FPDF_VERSION
print(FPDF_VERSION)
pdf=FPDF()
pdf.add_page()
for i in range(1,41):
# for flow mode, do not pass x or y:
pdf.image('../tutorial/logo_pb.png')
fn = 'issue14.pdf'
pdf.output(fn,'F')
import os
try:
os.startfile(fn)
except:
os.system("xdg-open \"%s\"" % fn)
@@ -0,0 +1,97 @@
"Test issue 33 (Cannot import GIF files that don't have transparency)"
from fpdf import FPDF, FPDF_VERSION
import os, tempfile
try:
import Image
except:
from PIL import Image
def genbar():
# bg
bg = Image.new("L", (112, 1), 1)
bg = bg.resize((112, 11))
# stripes
vbarnum = [0x4F43484B, 0xEE90D642, 0xF11A2735, 0xD71A]
vbar = Image.new("L", (112, 1), 1)
pix = vbar.load()
pos = 0
for b in vbarnum:
for i in range(32):
pix[pos, 0] = 0 if (b & 1) else 1
b = b >> 1
pos += 1
if pos >= 112: break
vbar = vbar.resize((112, 31), Image.NEAREST)
# digit
dignum = [0x398, 0x6dc, 0x61a, 0x31b, 0x1bf, 0x6d8, 0x7d8]
dbar = Image.new("L", (16, 7), 1)
pix = dbar.load()
pos = 0
ypos = 0
for b in dignum:
for i in range(16):
pix[pos, ypos] = 0 if (b & 1) else 1
b = b >> 1
pos += 1
ypos += 1
pos = 0
# result
bar = Image.new("L", (114, 44), 2)
bar.paste(vbar, (1, 1))
bar.paste(bg, (1, 32))
for i in range(4):
bar.paste(dbar, (35 + i * 12, 34))
return bar
plane = genbar()
palette = (0,0,0, 255,255,255) + (128,128,128)*254
img = Image.fromstring("P", plane.size, plane.tostring())
img.putpalette(palette)
f = tempfile.NamedTemporaryFile(delete = False, suffix = ".gif")
gif1 = f.name
f.close()
f = tempfile.NamedTemporaryFile(delete = False, suffix = ".gif")
gif2 = f.name
f.close()
img.save(gif1, "GIF")
img.save(gif2, "GIF", transparency = 1)
pdf=FPDF()
pdf.compress = False
pdf.add_page()
pdf.set_font('Arial', '', 16)
pdf.write(8, "Transparency")
pdf.ln()
pdf.write(8, " Transparency")
pdf.ln()
pdf.write(8, " Transparency")
pdf.ln()
pdf.image(gif1, x = 15, y = 15)
pdf.write(8, "Transparency")
pdf.ln()
pdf.write(8, " Transparency")
pdf.ln()
pdf.write(8, " Transparency")
pdf.ln()
pdf.image(gif2, x = 15, y = 39)
fn = 'issue33.pdf'
pdf.output(fn,'F')
os.unlink(gif1)
os.unlink(gif2)
try:
os.startfile(fn)
except:
os.system("xdg-open \"%s\"" % fn)
@@ -0,0 +1,27 @@
#!/usr/bin/env python
# -*- coding: utf8 -*-
"Basic test to reproduce issue 60: RTL languages (arabian, hebrew, etc.)"
from fpdf import FPDF
pdf = FPDF()
pdf.compress = False
pdf.add_page()
pdf.add_font('DejaVu', '', './font/DejaVuSans.ttf', uni=True)
pdf.set_font('DejaVu', '', 14)
# this will be displayed wrong as actually it is stored LTR:
text= u"این یک متن پارسی است. This is a Persian text !!"
pdf.write(8, text)
pdf.ln(8)
# Reverse the RLT using the Bidirectional Algorithm to be displayed correctly:
# (http://unicode.org/reports/tr9/)
from bidi.algorithm import get_display
rtl_text = get_display(text)
pdf.write(8, rtl_text)
fn = 'issue60.pdf'
pdf.output(fn,'F')
import os
try:
os.startfile(fn)
except:
os.system("xdg-open \"%s\"" % fn)
@@ -0,0 +1,19 @@
#!/usr/bin/env python
# -*- coding: latin1 -*-
"Basic test to reproduce issue 63: warning in unicode get_char_width"
from fpdf import FPDF
pdf = FPDF()
pdf.set_font('Arial','',14)
s = 'Texto largo que no cabe en esta celda pero que será ajustado'
w = pdf.get_string_width(s)
print (s, w)
assert round(w, 2) == 135.90
pdf.add_font('DejaVu', '', './font/DejaVuSans.ttf', uni=True)
pdf.set_font('DejaVu', '', 14)
s = u'Texto largo que no cabe en esta celda pero que será ajustado'
w = pdf.get_string_width(s)
print (s, w)
assert round(w, 2) == 153.64
@@ -0,0 +1,18 @@
"Test issue 65: twitter.png error (urlopen, transparency, internal regex error)"
from fpdf import FPDF, FPDF_VERSION
pdf=FPDF()
pdf.compress = False
pdf.add_page()
png = "https://g.twimg.com/Twitter_logo_blue.png"
pdf.image(png, x = 15, y = 15)
fn = 'issue65.pdf'
pdf.output(fn,'F')
import os
try:
os.startfile(fn)
except:
os.system("xdg-open \"%s\"" % fn)
@@ -0,0 +1,24 @@
#!/usr/bin/env python
# -*- coding: utf8 -*-
"Basic test to check issue 70: raise an exception if add_page was not called"
try:
import fpdf
# Portrait, millimeter units, A4 page size
pdf=fpdf.FPDF("P", "mm", "A4")
# Set font: Times, normal, size 10
pdf.set_font('Times','', 12)
##pdf.add_page()
# Layout cell: 0 x 5 mm, text, no border, Left
pdf.cell(0,5,'Input 1 : ',border=0,align="L")
pdf.cell(0,5,'Input 2 : ', border=0,align="L")
pdf.cell(0,5,'Recomendation : ', border=0, align="L")
pdf.cell(0,5,'Data 1 :', border=0, align="L" )
pdf.cell(0,5,'Data 2 :', border=0, align="L" )
fn = 'issue70.pdf'
pdf.output(fn,'F')
except RuntimeError as e:
assert e.args[0] == "FPDF error: No page open, you need to call add_page() first"
else:
raise RuntimeError("Exception not raised!")
@@ -0,0 +1,22 @@
#!/usr/bin/env python
# -*- coding: utf8 -*-
"Basic test to check issue 70: raise an exception if add_page was not called"
import fpdf
# Portrait, millimeter units, A4 page size
pdf=fpdf.FPDF("P", "mm", "A4")
# Set font: Times, normal, size 10
pdf.add_page()
url = "http://upload.wikimedia.org/wikipedia/commons/thumb/0/0b/Code_3_of_9.svg/262px-Code_3_of_9.svg.png"
pdf.image(url, 10, 10)
pdf.code39("*wikipedia*", 12.75, 7, 1.49)
fn = 'issue71.pdf'
pdf.output(fn,'F')
import os
try:
os.startfile(fn)
except:
os.system("xdg-open \"%s\"" % fn)
Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

@@ -0,0 +1,30 @@
#!/usr/bin/env python
"Simple test to check alias_nb_pages replacement under unicode fonts"
from fpdf import FPDF
pdf=FPDF()
# set default alias: {nb} that will be replaced with total page count
pdf.alias_nb_pages()
# Add a Unicode font (uses UTF-8)
pdf.add_font('DejaVu','','DejaVuSansCondensed.ttf',uni=True)
pdf.set_font('DejaVu','',14)
for i in range(5):
pdf.add_page()
pdf.set_font('Arial','B',16)
pdf.cell(40,10,'Hello World! {nb}')
pdf.set_font('DejaVu','',14)
pdf.cell(40,10,'Hello World! unicode {nb}')
fn = 'nb_pages.pdf'
pdf.output(fn, 'F')
import os
try:
os.startfile(fn)
except:
os.system("xdg-open \"%s\"" % fn)
@@ -0,0 +1,8 @@
rem prepare local copy for tests
mkdir fpdf_local
mkdir fpdf_local/fpdf
cp ../fpdf/*.py fpdf_local/fpdf/
@@ -0,0 +1,13 @@
#!/bin/sh
# prepare local copy for tests
mkdir fpdf_local
mkdir fpdf_local/fpdf
cp ../fpdf/*.py fpdf_local/fpdf/
echo Now you can test:
echo python runtest.py
Binary file not shown.
+35
View File
@@ -0,0 +1,35 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"Basic example to test py3k conversion"
import sys
from fpdf import FPDF
pdf = FPDF()
# compression also supported in py3k version
pdf.compress = True
pdf.add_page()
# unicode is not yet supported in py3k version, use windows-1252 standards font
pdf.set_font('Arial','',14)
pdf.ln(10)
pdf.write(5, u'hello world %s áéíóúüñ' % sys.version)
pdf.image("../tutorial/logo.png", 50, 50)
pdf.image("flower2.jpg", 100, 50)
pdf.image("lena.gif", 50, 75)
# Add a DejaVu Unicode font (uses UTF-8)
# Supports more than 200 languages. For a coverage status see:
# http://dejavu.svn.sourceforge.net/viewvc/dejavu/trunk/dejavu-fonts/langcover.txt
pdf.add_font('DejaVu','','DejaVuSansCondensed.ttf',uni=True)
pdf.set_font('DejaVu','',14)
pdf.ln(10)
pdf.write(8, u"Hello world in Russian: Здравствуй, Мир")
fn='py3k.pdf'
pdf.output(fn,'F')
import os
try:
os.startfile(fn)
except:
os.system("xdg-open \"%s\"" % fn)
@@ -0,0 +1,415 @@
# List of all resources as for 2015-01-07
# can be filled with runtest.py --hash <file_or_dir> [--tag tag1[|--tag tag2]]
res=HelloWorld.txt
hash=433cd9c4c1c29624a431f76f26b03edb
tags=
res=invoice.csv
hash=d425307e783a9b7ed858e5aaea3d0724
tags=
res=../tutorial/logo.png
hash=706e233af4189821a7cd0ca0a0804ee9
tags=
res=../tutorial/logo_pb.png
hash=6278f81df5ed1f7919b4364ca9b8dc4e
tags=
res=flower2.jpg
hash=e26fe0ddd61827b35d53500449ddce82
tags=
res=lena.gif
hash=2dea6fb17967bb6b9374ca83c07e9076
tags=
res=dejavusanscondensed.cw.dat
hash=61fb165f8f3947da890659ea595f58cf
tags=
res=img_gray.jpg
hash=97cd7bbd675a5d6b74bfa1a52fcfe2b7
tags=
res=img_rgb.jpg
hash=b9273f5de5a57a40328707635757ff7b
tags=
res=img_cmyk.jpg
hash=a1a0ebe183a8f04d3f586634292a4e25
tags=
res=font/Bandal.ttf
hash=f3543d1732de78164adb2ff007f73e8e
tags=fontpack
res=font/Bangwool.ttf
hash=56b08ed2d8f90bdc0687cf95dc893010
tags=fontpack
res=font/DejaVuSans-Bold.ttf
hash=aa0fe4048d408361d65bbf913a3aee22
tags=fontpack
res=font/DejaVuSans-BoldOblique.ttf
hash=ba0d224e31e29d3c0ad5a8a37dae14c2
tags=fontpack
res=font/DejaVuSans-ExtraLight.ttf
hash=bf35c26509b7f4654a6490c7d11861d9
tags=fontpack
res=font/DejaVuSans-Oblique.ttf
hash=ee14498581142ad399d0b7bfb1d70e3f
tags=fontpack
res=font/DejaVuSans.ttf
hash=eccb7a74720fc377b60d6b2110530fd9
tags=fontpack
res=font/DejaVuSansCondensed-Bold.ttf
hash=80e5791b476a8e9c4e9e611e34b9d31a
tags=fontpack
res=font/DejaVuSansCondensed-BoldOblique.ttf
hash=a853c46d69c39abc45d15601c7c8b5c1
tags=fontpack
res=font/DejaVuSansCondensed-Oblique.ttf
hash=621420f35d9eb4c0a6c4ada36abbc65d
tags=fontpack
res=font/DejaVuSansCondensed.ttf
hash=c05bb037ab3ccfe47a03a913799d9903
tags=fontpack
res=font/DejaVuSansMono-Bold.ttf
hash=26dd9aa93361477f10b4f949a0a76a61
tags=fontpack
res=font/DejaVuSansMono-BoldOblique.ttf
hash=44f2c073f5676fcf0c1748e9e28f2b03
tags=fontpack
res=font/DejaVuSansMono-Oblique.ttf
hash=f5b435e042123f193035256df7f70d4a
tags=fontpack
res=font/DejaVuSansMono.ttf
hash=0fa23684c88737952788b01bba227ea9
tags=fontpack
res=font/DejaVuSerif-Bold.ttf
hash=81a57a2411ba2b9f6b605befc5eca02b
tags=fontpack
res=font/DejaVuSerif-BoldItalic.ttf
hash=453f57f8c3e3a74c68dd7cf707a4403d
tags=fontpack
res=font/DejaVuSerif-Italic.ttf
hash=bf123a71cbb4732369dde37ca0c7f012
tags=fontpack
res=font/DejaVuSerif.ttf
hash=5bc094b834f5a547b92f53b50817d637
tags=fontpack
res=font/DejaVuSerifCondensed-Bold.ttf
hash=f3aafb6ed5299d8c10df115acd5b672f
tags=fontpack
res=font/DejaVuSerifCondensed-BoldItalic.ttf
hash=d3ff2825dab54513d33bf4c846bf5a6c
tags=fontpack
res=font/DejaVuSerifCondensed-Italic.ttf
hash=a46631be1e996bdc0e7a63668ac9aff7
tags=fontpack
res=font/DejaVuSerifCondensed.ttf
hash=c01fb6d344d6c179a3c037875d6c69a6
tags=fontpack
res=font/Eunjin.ttf
hash=3b0ecd18263ed44516906a34e9290d88
tags=fontpack
res=font/EunjinNakseo.ttf
hash=0c17d9e35f1654eb86797098a5495976
tags=fontpack
res=font/fireflysung.ttf
hash=4ead69abf2a299164eaa88f8fc4f4fd1
tags=fontpack
res=font/gargi.ttf
hash=18c01132b877b63c1aea7ed5c1daac7d
tags=fontpack
res=font/Garuda-Bold.ttf
hash=d36b00d5dfa35081d30960f58bc5275f
tags=fontpack
res=font/Garuda-BoldOblique.ttf
hash=69821a92a88ba446d93c8bf6f95eb2d6
tags=fontpack
res=font/Garuda-Oblique.ttf
hash=209709a7ecfb8418e7b38bb8eac9c8b9
tags=fontpack
res=font/Garuda.ttf
hash=d2221d242995810fe352a7ebc365cfd4
tags=fontpack
res=font/Guseul.ttf
hash=984cae7b51e9a70b74c6fd9a3ff54365
tags=fontpack
res=font/Kedage-b.ttf
hash=97b0204091e6d09865315a88151541cb
tags=fontpack
res=font/Kedage-n.ttf
hash=16024bea0eb7a59995c59edf5df20d8f
tags=fontpack
res=font/Kinnari-Bold.ttf
hash=0ab60d8824eea556126b5cb778595389
tags=fontpack
res=font/Kinnari-BoldItalic.ttf
hash=ef5b704a1e2b4ba81852c9f0b2fad49b
tags=fontpack
res=font/Kinnari-BoldOblique.ttf
hash=47434defc233f961034e081777525b49
tags=fontpack
res=font/Kinnari-Italic.ttf
hash=a1ce8f390abbcd0b740333edf9212e74
tags=fontpack
res=font/Kinnari-Oblique.ttf
hash=354b7bc1970513ca1b7f059c9be5e460
tags=fontpack
res=font/Kinnari.ttf
hash=45f5f56fb11fd153b9cb81e8b8913359
tags=fontpack
res=font/lohit_bn.ttf
hash=a9af3b241f54fd50e0a73680abdd2ceb
tags=fontpack
res=font/lohit_gu.ttf
hash=04b3a754167373cac633286f311cbb53
tags=fontpack
res=font/lohit_hi.ttf
hash=f9bc8fe5c8591cc224f4978c6b3c5ed8
tags=fontpack
res=font/lohit_ta.ttf
hash=e71234ee0e8bc17e7ab81f7695f08360
tags=fontpack
res=font/Loma-Bold.ttf
hash=020935090d612c1b6fe7a3bce7ed05a5
tags=fontpack
res=font/Loma-BoldOblique.ttf
hash=d32dcb6cf9eb2aa0a03b2bd18a38def4
tags=fontpack
res=font/Loma-Oblique.ttf
hash=b9a7683925ac16eb6adb408908061d1f
tags=fontpack
res=font/Loma.ttf
hash=336150c63733be6a2046eede6cbded3c
tags=fontpack
res=font/Malige-b.ttf
hash=bd9eb24f44562c349aba8dde07e5b9c0
tags=fontpack
res=font/Malige-n.ttf
hash=a51d5ab7ac3a520efa33067f6219facd
tags=fontpack
res=font/Meera_04.ttf
hash=c95a54607a0d39c032d861dde353db49
tags=fontpack
res=font/MuktiNarrow.ttf
hash=272712738eda622699d70ae3e6ba6daf
tags=fontpack
res=font/MuktiNarrowBold.ttf
hash=1182c76b00aa305778c789501a4f5a1d
tags=fontpack
res=font/Norasi-Bold.ttf
hash=d743998efde875de9f2ab96f6536ab82
tags=fontpack
res=font/Norasi-BoldItalic.ttf
hash=c63919f2ffef0afe5402951cde1f2639
tags=fontpack
res=font/Norasi-BoldOblique.ttf
hash=29e9a794a2b4ee7e9e98a5557aa6bfa3
tags=fontpack
res=font/Norasi-Italic.ttf
hash=5ce4b8f93cdaad097f01c28924080f0c
tags=fontpack
res=font/Norasi-Oblique.ttf
hash=bffe82f031e40639292ce91f8a15a2b0
tags=fontpack
res=font/Norasi.ttf
hash=dffb080d62ad3bcdd81e53af1744c74c
tags=fontpack
res=font/Purisa-Bold.ttf
hash=99cbea1e8b204549e239c49d4e7be8bc
tags=fontpack
res=font/Purisa-BoldOblique.ttf
hash=a5e42db5e91a2c19f0f6010fed9470ce
tags=fontpack
res=font/Purisa-Oblique.ttf
hash=a75f533f6a3ca4ab6edbc585ebf288de
tags=fontpack
res=font/Purisa.ttf
hash=d50d84d5e5f00760fe11f9fe8ec5f9e5
tags=fontpack
res=font/Sawasdee-Bold.ttf
hash=558ac9d0df800c207b9d6a757c1329f3
tags=fontpack
res=font/Sawasdee-BoldOblique.ttf
hash=fedf55c34867787540fb6429b783bcab
tags=fontpack
res=font/Sawasdee-Oblique.ttf
hash=145648527b7e615046b8bea467ac3764
tags=fontpack
res=font/Sawasdee.ttf
hash=037e7df8300f86a8037e5a2cfa6de23f
tags=fontpack
res=font/TlwgMono-Bold.ttf
hash=1b3dc9632f3a8bfd9093c1b37d4929c5
tags=fontpack
res=font/TlwgMono-BoldOblique.ttf
hash=fe6d4662dae5b8930e2303137e3b2c52
tags=fontpack
res=font/TlwgMono-Oblique.ttf
hash=c57cc0776dd53a970bf58c413f3dde93
tags=fontpack
res=font/TlwgMono.ttf
hash=1670ae98233b4130e3f75e60d78da337
tags=fontpack
res=font/TlwgTypewriter-Bold.ttf
hash=584648f7d16c9cc35dae0410a8ac7dfd
tags=fontpack
res=font/TlwgTypewriter-BoldOblique.ttf
hash=f96a9dae932cfa45b7dec3c16634f45c
tags=fontpack
res=font/TlwgTypewriter-Oblique.ttf
hash=171cb4b1233493971073bb77ef737247
tags=fontpack
res=font/TlwgTypewriter.ttf
hash=48f025131d8a3b6658e6e3646c744c43
tags=fontpack
res=font/TlwgTypist-Bold.ttf
hash=d0d3e01d91dc9ad51dac4b018bd8cae2
tags=fontpack
res=font/TlwgTypist-BoldOblique.ttf
hash=6301f2f0a757e97a993fea48754b3317
tags=fontpack
res=font/TlwgTypist-Oblique.ttf
hash=09440f241ad8fe637c3c2208dfce9b10
tags=fontpack
res=font/TlwgTypist.ttf
hash=ca60c6ab7d5af453a7310afbc7497f7e
tags=fontpack
res=font/TlwgTypo-Bold.ttf
hash=3ce15a7d2b71f75a27a5844771471501
tags=fontpack
res=font/TlwgTypo-BoldOblique.ttf
hash=e6dd6b8d1e57049bd1156c20e167d06b
tags=fontpack
res=font/TlwgTypo-Oblique.ttf
hash=bcc87b433cac57697e498b60a4952545
tags=fontpack
res=font/TlwgTypo.ttf
hash=c2cd075cef04bf7f0f195714bf22056e
tags=fontpack
res=font/Umpush-Bold.ttf
hash=9eeaa9e4c98b0b42c1d35282df490c4e
tags=fontpack
res=font/Umpush-BoldOblique.ttf
hash=643802c6506528b365427ed2f33c2364
tags=fontpack
res=font/Umpush-Light.ttf
hash=e934ebcdcd3e3766f645b11804998a5f
tags=fontpack
res=font/Umpush-LightOblique.ttf
hash=0b2ecb7dae7089736ce051a38a9a8e03
tags=fontpack
res=font/Umpush-Oblique.ttf
hash=83c18c4df7f95d0352dc9c68e3191ff5
tags=fontpack
res=font/Umpush.ttf
hash=bfbf73eb0d29d2366f83b87e3cad66d8
tags=fontpack
res=font/Waree-Bold.ttf
hash=87db2bc0c0d9396a26c5ebf4b87b6b6c
tags=fontpack
res=font/Waree-BoldOblique.ttf
hash=c2ed7a5092c377855c7f7401c01c8d51
tags=fontpack
res=font/Waree-Oblique.ttf
hash=22b0d1d9cc60a11405c2545daaaa871c
tags=fontpack
res=font/Waree.ttf
hash=2d925b6d5dda54f189e5a0255c555fa3
tags=fontpack
+520
View File
@@ -0,0 +1,520 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os, sys
import cover
import shutil
import traceback
def search_python_posix():
lst = []
path = os.environ.get("PATH")
for item in path.split(":"):
try:
for interp in os.listdir(item):
if interp[:6] != "python":
continue
if interp[-7:] == "-config":
continue
fp = os.path.join(item, interp)
# test if already in list
same = False
for lidx, l_interp in enumerate(lst):
if os.path.samefile(l_interp, fp):
same = True
# use shorter name
if len(l_interp) < len(fp):
lst[lidx] = fp
break
if same:
continue
lst.append(fp)
except OSError:
pass
return lst
def search_python_win():
lst = []
try:
try:
import _winreg as winreg
except ImportError:
import winreg
def findreg(key, lst):
PATH = "SOFTWARE\\Python\\PythonCore"
try:
rl = winreg.OpenKey(key, PATH)
except WindowsError:
return lst
try:
for i in range(winreg.QueryInfoKey(rl)[0]):
ver = winreg.EnumKey(rl, i)
rv = winreg.QueryValue(key, PATH + "\\" + ver + "\\InstallPath")
fp = os.path.join(rv, "python.exe")
#print fp
if os.path.exists(fp) and not fp in lst:
lst.append(fp)
except WindowsError:
pass
return lst
lst = findreg(winreg.HKEY_LOCAL_MACHINE, lst)
lst = findreg(winreg.HKEY_CURRENT_USER, lst)
except:
traceback.print_exc(file = sys.stdout)
# fallback
cover.log("Search python at system drive")
try:
path = os.environ.get("SystemDrive", "C:")
for item in os.listdir(path):
if item[:6].lower() != "python":
continue
fp = os.path.join(path, item, "python.exe")
if os.path.exists(fp) and not fp in lst:
lst.append(fp)
except:
traceback.print_exc(file = sys.stdout)
return lst
def search_python():
if sys.platform.startswith("linux"):
lst = search_python_posix()
elif sys.platform.startswith("win"):
lst = search_python_win()
else:
lst = search_python_posix()
if len(lst) == 0:
# fallback
lst.append(sys.executable)
return lst
def find_python_version(pylst):
lst = []
ids = []
for interp in pylst:
try:
std, err = cover.exec_cmd([interp, "-V"])
version = err.strip()
if not version:
# python 3.4+
version = std.strip()
if version[:6] == "Python":
shver = version[6:].strip().replace(" ", "-")
nid = shver
nidn = 0
while nid in ids:
nidn += 1
nid = shver + "-%d" % nidn
ids.append(nid)
lst.append((interp, nid, version))
else:
cover.err("Not a python", version)
# no python found
continue
except:
traceback.print_exc(file = sys.stdout)
return lst
def search_tests():
base = os.path.join(cover.basepath, "cover")
lst = []
for item in os.listdir(base):
if item[:5] != "test_" or item[-3:] != ".py":
continue
lst.append(os.path.join(base, item))
lst.sort()
return lst
def do_test_one(testfile, interp, info, dest):
path = interp[0]
nid = interp[1]
destpath = dest[0]
destenv = dest[1]
# check PIL
if info.get("pil", "no") == "yes":
if destenv.get("pil", "no") != "yes":
return ("skip", "no PIL or PIllow found")
# check python version
tool2to3 = (info.get("2to3", "no") == "yes")
py2 = (info.get("python2", "yes") == "yes")
py3 = (info.get("python3", "yes") == "yes")
plat = info.get("platform", "*")
if plat == "":
plat = "*"
if plat != "*":
plats = plat.split(",")
accept = False
for plat in plats:
if sys.platform == plat:
accept = True
break
if not accept:
return ("skip", "not for \"" + sys.platform + "\"")
copy = False
if nid[:2] == "3.":
if not py3:
return ("skip", "not for python 3")
if not tool2to3:
copy = True
else:
return ("unimplemented", "todo")
if nid[:2] == "2.":
if not py2:
return ("skip", "not for python 2")
copy = True
# check if fpdf instaled
if destenv.get("ver", "None") == "None":
return ("nofpdf", "")
# copy files
testname = os.path.basename(testfile)
testfmt = info.get("format", "raw")
newfile = os.path.join(destpath, testname)
newres = os.path.join(destpath, info.get("fn", testname + "." + testfmt.lower()))
if copy:
shutil.copy(testfile, destpath)
# start execution
std, err = cover.exec_cmd([path, "-B", newfile, "--check", "--auto", newres])
f = open(os.path.join(destpath, "testlog.txt"), "a")
f.write("#" * 40 + "\n")
f.write(testname + "\n")
f.write("=" * 40 + "\n")
f.write(std)
f.write("-" * 40 + "\n")
f.write(err)
f.close()
answ = std.strip()
if answ.find("\n") >= 0 or len(answ) == 0:
return ("fail", "bad output")
else:
if answ == "HASHERROR":
# get new hash
nh = ""
for line in err.split("\n"):
line = line.strip()
if line[:5] == "new =":
nh = line[5:].strip()
return ("hasherror", nh)
return (answ.lower(), "")
def prepare_dest(interp):
destpath = os.path.join(cover.basepath, "out-" + interp[1])
if not os.path.exists(destpath):
os.makedirs(destpath)
# copy common set
src = os.path.join(cover.basepath, "cover")
shutil.copy(os.path.join(src, "common.py"), destpath)
shutil.copy(os.path.join(src, "checkenv.py"), destpath)
f = open(os.path.join(destpath, "testlog.txt"), "w")
f.write("Version: " + interp[1] + "\n")
f.write("Path: " + interp[0] + "\n")
f.write(str(interp[2:]) + "\n")
# run checkenv
std, err = cover.exec_cmd([interp[0], "-B", os.path.join(destpath, "checkenv.py")])
env = {}
if len(err.strip()) == 0:
# OK
f.write("Check environment - ok:\n")
f.write(std)
lineno = 0
for line in std.split("\n"):
lineno += 1
line = line.strip()
if lineno == 1:
if line != "CHECK":
break
line = line.strip()
kv = line.split("=", 1)
if len(kv) == 2:
env[kv[0].lower().strip()] = kv[1].strip()
else:
f.write("ERROR:\n")
f.write(err)
f.close()
return (destpath, env)
def do_test(testfile, interps, dests, stats, hint = ""):
cover.log("Test", hint, ":", os.path.basename(testfile))
info = cover.read_cover_info(testfile)
resall = ""
# prepare
# do tests
hasherr = []
for interp in interps:
if len(interps) < 6:
resall += (interp[1] + " - ")
res, desc = do_test_one(testfile, interp, info, dests[interp[1]])
if res == "hasherror":
hasherr.append(desc)
#cover.log("HASH =", desc)
# update statistic
stats["_"]["_"] += 1
stats["_"][res] = stats["_"].get(res, 0) + 1
stats[interp[1]]["_"] += 1
stats[interp[1]][res] = stats[interp[1]].get(res, 0) + 1
resall += (res + " " * 10)[:6].upper()
resall += " "
cover.log(resall)
# test if all hash
if len(interps) == len(hasherr):
cover.err("All hashes wrong")
def print_interps(interps):
cover.log(">> Interpretors:", len(interps))
dests = {}
stats = {"_": {"_": 0}}
for idx, interp in enumerate(interps):
cover.log("%d) %s - %s" % (idx + 1, interp[1], interp[0]))
cover.log()
def do_all_test(interps, tests):
print_interps(interps)
dests = {}
stats = {"_": {"_": 0}}
for idx, interp in enumerate(interps):
dests[interp[1]] = prepare_dest(interp)
stats[interp[1]] = {"_": 0}
cover.log(">> Tests:", len(tests))
for idx, test in enumerate(tests):
do_test(test, interps, dests, stats, "%d / %d" % (idx + 1, len(tests)))
cover.log()
cover.log(">> Statistics:")
def stat_str(stat):
keys = list(stat.keys())
keys.sort()
st = "total - %d" % stat["_"]
for key in keys:
if key == "_":
continue
st += (", %s - %d" % (key, stat[key]))
return st
for interp in interps:
cover.log(interp[1] + ":", stat_str(stats[interp[1]]))
cover.log("-"*10)
cover.log("All:", stat_str(stats["_"]))
# check if no FPDF at all
total = stats["_"]["_"]
fpdf = stats["_"].get("nofpdf", 0)
skip = stats["_"].get("skip", 0)
if skip == total:
cover.log("All tests skipped. Install some modules (PIL, PyBIDI, Gluon etc)")
elif fpdf + skip == total:
hint_prepare()
def list_tests():
tst = search_tests()
cover.log(">> Tests:", len(tst))
for idx, test in enumerate(tst):
test = os.path.basename(test)
if test[:5].lower() == "test_":
test = test[5:]
if test[-3:].lower() == ".py":
test = test[:-3]
cover.log("%d) %s" % (idx + 1, test))
cover.log()
def usage():
cover.log("Usage: runtest.py [...]")
cover.log(" --listtests - list all tests")
cover.log(" --listinterps - list all availiable interpretors")
cover.log(" --test issuexx - add test issuexx")
cover.log(" --test @file - add test from file")
cover.log(" --interp path - test against specified interpretors")
cover.log(" --interp @file - read interpretors list from file")
cover.log(" --downloadfonts - download font set")
cover.log(" --help - this page")
def hint_prepare():
if cover.PYFPDFTESTLOCAL:
if sys.platform.startswith("win"):
prefix = ""
suffix = ".bat"
else:
prefix = "./"
suffix = ".sh"
cover.log("*** Please, prepare local copy for tests")
cover.log("*** " + prefix + "prepare_local" + suffix)
else:
cover.log("*** Please, install PyFPDF with")
cover.log("*** python setup.py install")
cover.log("*** or set PYFPDFTESTLOCAL variable to use local copy")
if sys.platform.startswith("win"):
cover.log("*** set PYFPDFTESTLOCAL=1")
else:
cover.log("*** export PYFPDFTESTLOCAL=1")
def read_list(fn):
f = open(fn, "r")
try:
return f.readlines()
finally:
f.close()
def hasher(path, args):
tags = []
while len(args):
arg = args[0]
args = args[1:]
if arg == "--tag":
if len(args) == 0:
cover.log("Param without value")
return
value = args[0]
args = args[1:]
if value not in tags:
tags.append(value)
else:
cover.log("Unknown param")
return
lst = []
if os.path.isdir(path):
files = [(x.lower(), x) for x in os.listdir(path)]
files.sort()
for s, item in files:
fp = os.path.join(path, item)
# clear path
bp = fp
if sys.platform.startswith("win"):
bp = fp.replace("\\", "/")
lst += [[bp, cover.file_hash(fp)]]
else:
lst = [[path, cover.file_hash(path)]]
for item, hs in lst:
cover.log("res=" + item)
cover.log("hash=" + hs)
cover.log("tags=" + ",".join(tags))
cover.log()
def download_fonts():
URL = "http://pyfpdf.googlecode.com/files/fpdf_unicode_font_pack.zip"
fntdir = os.path.join(cover.basepath, "font")
zippath = os.path.join(cover.basepath, URL.split('/')[-1])
if not os.path.exists(fntdir):
os.makedirs(fntdir)
if not os.path.exists(zippath):
import urllib2
u = urllib2.urlopen(URL)
meta = u.info()
file_size = int(meta.getheaders("Content-Length")[0])
cover.log("Downloading:", file_size, "bytes")
f = open(zippath, "wb")
file_size_dl = 0
while True:
buff = u.read(64 * 1024)
if not buff:
break
file_size_dl += len(buff)
f.write(buff)
cover.log(" ", file_size_dl * 100. / file_size, "%")
f.close()
# unpack
cover.log("Extracting")
import zipfile
fh = open(zippath, "rb")
z = zipfile.ZipFile(fh)
for name in z.namelist():
if name[:5] != "font/":
continue
if name[5:].find("/") >= 0:
continue
cover.log(" ", name[5:])
outfile = open(os.path.join(fntdir, name[5:]), "wb")
outfile.write(z.read(name))
outfile.close()
cover.log("Done")
def main():
cover.log("Test PyFPDF")
testsn = []
interpsn = []
args = sys.argv[1:]
while len(args):
arg = args[0]
args = args[1:]
if arg == "--hash":
if len(args) == 0:
cover.log("Param without value")
return usage()
return hasher(args[0], args[1:])
if arg == "--help":
return usage()
elif arg == "--test":
if len(args) > 0:
value = args[0]
args = args[1:]
else:
cover.log("Param without value")
return usage()
if value[:1] == "@":
# from file
testsn += read_list(value[1:])
else:
testsn.append(value)
elif arg == "--interp":
if len(args) > 0:
value = args[0]
args = args[1:]
else:
cover.log("Param without value")
return usage()
if value[:1] == "@":
# from file
interpsn += read_list(value[1:])
else:
interpsn.append(value)
elif arg == "--listtests":
return list_tests()
elif arg == "--listinterps":
return print_interps(find_python_version(search_python()))
elif arg == "--downloadfonts":
return download_fonts()
else:
cover.log("Unknown param")
return usage()
if len(testsn) == 0:
tests = search_tests()
else:
# cheack all tests
tests = []
for test in testsn:
test = test.strip()
fn = os.path.join(cover.basepath, "cover", "test_" + test + ".py")
if os.path.exists(fn):
tests.append(fn)
else:
cover.err("Test \"%s\" not found" % test)
return
if len(interpsn) == 0:
interps = find_python_version(search_python())
else:
# cheack all tests
interps = []
for interp in interpsn:
fn = os.path.abspath(interp)
if os.path.exists(fn):
interps.append(fn)
else:
cover.err("Interpretor \"%s\" not found" % test)
return
interps = find_python_version(interps)
do_all_test(interps, tests)
if __name__ == "__main__":
main()
@@ -0,0 +1,34 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"Basic test of TrueType Unicode font handling"
import struct
from fpdf.ttfonts import TTFontFile
if __name__ == '__main__':
ttf = TTFontFile()
ttffile = 'font/DejaVuSansCondensed.ttf';
ttf.getMetrics(ttffile)
# test basic metrics:
assert round(ttf.descent, 0) == -236
assert round(ttf.capHeight, 0) == 928
assert ttf.flags == 4
assert [round(i, 0) for i in ttf.bbox] == [-918, -415, 1513, 1167]
assert ttf.italicAngle == 0
assert ttf.stemV == 87
assert round(ttf.defaultWidth, 0) == 540
assert round(ttf.underlinePosition, 0) == -63
assert round(ttf.underlineThickness, 0) == 44
# test char widths 8(against binary file generated by tfpdf.php):
data = open("dejavusanscondensed.cw.dat", "rb").read()
char_widths = struct.unpack(">%dH" % int(len(data) / 2), data)
assert len(ttf.charWidths) == len(char_widths)
diff = []
for i, (x, y) in enumerate(zip(char_widths, ttf.charWidths)):
if x != y: # compare each char width
diff.append(i)
assert not diff
## assert ttf.charWidths == char_widths
@@ -0,0 +1,42 @@
# try all ttf fonts
from fpdf import FPDF
import fpdf
import sys
import os
import time
pdf = FPDF()
pdf.add_page()
#font_dir = fpdf.FPDF_FONT_DIR
font_dir = '../fpdf/font'
txt = open('HelloWorld.txt').read()
# Add a Unicode font (uses UTF-8)
for font in os.listdir(font_dir):
if font.lower().endswith('.ttf'):
fontpath = os.path.join(font_dir, font)
print(fontpath)
t0 = time.time()
pdf.add_font(font,'', fontpath, uni=True)
t1 = time.time()
pdf.set_font(font,'',14)
t2 = time.time()
pdf.write(8, font)
pdf.ln()
pdf.write(8, txt)
pdf.ln()
t3 = time.time()
print("ttf loading time", t1-t0)
print("ttf total time", t3-t0)
print()
fn = 'unifonts.pdf'
pdf.output(fn,'F')
import os
try:
os.startfile(fn)
except:
os.system("xdg-open \"%s\"" % fn)
+40
View File
@@ -0,0 +1,40 @@
import zlib
import sys
import pdb
import os
print sys.argv[1]
hex = '--hex' in sys.argv
r = open(sys.argv[1], 'rb')
i = 0
length = None
while 1:
l = r.readline()
if l == "":
break
if "/Length " in l:
print l
s = l[l.index("/Length ")+8:]
if ' ' in s:
s = s[:s.index(" ")]
if '>' in s:
s = s[:s.index(">")]
length = int(s)
print l, length
if l.startswith('stream') and length:
i += 1
fn = "stream_%s_%s" % (i, sys.argv[1])
print mytime.displayTime()+" writting ", length, fn
s = r.read(length)
w = open(fn, 'wb')
try:
s = zlib.decompress(s)
except zlib.error:
pass
if hex:
s = s.encode('hex')
w.write(s)
w.close()
r.close()
os.system("windiff stream_1_ex_php.pdf stream_1_ex.pdf")
@@ -0,0 +1,40 @@
# Example of unicode support based on tfPDF
# http://www.fpdf.org/en/script/script92.php
import sys
import time
import fpdf
# Set system font path
fpdf.set_global('SYSTEM_TTFONTS', r"c:\WINDOWS\Fonts")
pdf = fpdf.FPDF()
pdf.add_page()
# Add a Windows System font (uses UTF-8)
t0 = time.time()
pdf.add_font('sysfont','','arial.ttf',uni=True)
pdf.set_font('sysfont','',14)
t1 = time.time()
print mytime.displayTime()+" ttf loading time", t1-t0
fn = 'winfonts.pdf'
# Load a UTF-8 string from a file and print it
txt = open('HelloWorld.txt').read()
pdf.multi_cell(15, 5, txt)
pdf.text(100, 5, '1234')
pdf.write(5,'To find out what\'s new in self tutorial, click ')
pdf.set_font('','U')
link=pdf.add_link()
pdf.write(5,'here',link)
# Select a standard font (uses windows-1252)
pdf.set_font('Arial','',14)
pdf.ln(10)
pdf.write(5, 'The file size of this PDF is only 12 KB.')
pdf.output(fn,'F')
import os
os.startfile(fn)