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:
@@ -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Ð�Sü�BKË\7G�½¾�±.�OþŠ…[Á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)
|
||||
|
||||
Binary file not shown.
@@ -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 |
@@ -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 |
@@ -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
|
||||
|
@@ -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.
@@ -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
|
||||
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
Reference in New Issue
Block a user