Kaynağa Gözat

* Added fcl-pdf

git-svn-id: trunk@33162 -
michael 9 yıl önce
ebeveyn
işleme
5eb691f2c9

+ 22 - 0
.gitattributes

@@ -2572,6 +2572,28 @@ packages/fcl-passrc/tests/tctypeparser.pas svneol=native#text/plain
 packages/fcl-passrc/tests/tcvarparser.pas svneol=native#text/plain
 packages/fcl-passrc/tests/testpassrc.lpi svneol=native#text/plain
 packages/fcl-passrc/tests/testpassrc.lpr svneol=native#text/plain
+packages/fcl-pdf/Makefile svneol=native#text/plain
+packages/fcl-pdf/Makefile.fpc svneol=native#text/plain
+packages/fcl-pdf/examples/poppy.jpg -text
+packages/fcl-pdf/examples/testfppdf.lpi svneol=native#text/plain
+packages/fcl-pdf/examples/testfppdf.lpr svneol=native#text/plain
+packages/fcl-pdf/fpmake.pp svneol=native#text/plain
+packages/fcl-pdf/readme.txt svneol=native#text/plain
+packages/fcl-pdf/src/fpparsettf.pp svneol=native#text/plain
+packages/fcl-pdf/src/fppdf.pp svneol=native#text/plain
+packages/fcl-pdf/src/fpttf.pp svneol=native#text/plain
+packages/fcl-pdf/src/fpttfencodings.pp svneol=native#text/plain
+packages/fcl-pdf/tests/fpparsettf_test.pas svneol=native#text/plain
+packages/fcl-pdf/tests/fppdf_test.pas svneol=native#text/plain
+packages/fcl-pdf/tests/fpttf_test.pas svneol=native#text/plain
+packages/fcl-pdf/tests/readme.txt svneol=native#text/plain
+packages/fcl-pdf/tests/testunits.inc svneol=native#text/plain
+packages/fcl-pdf/tests/unittests_console.lpi svneol=native#text/plain
+packages/fcl-pdf/tests/unittests_console.lpr svneol=native#text/plain
+packages/fcl-pdf/tests/unittests_gui.lpi svneol=native#text/plain
+packages/fcl-pdf/tests/unittests_gui.lpr svneol=native#text/plain
+packages/fcl-pdf/utils/mkpdffontdef.lpi svneol=native#text/plain
+packages/fcl-pdf/utils/mkpdffontdef.pp svneol=native#text/plain
 packages/fcl-process/Makefile svneol=native#text/plain
 packages/fcl-process/Makefile.fpc svneol=native#text/plain
 packages/fcl-process/Makefile.fpc.fpcmake svneol=native#text/plain

+ 2617 - 0
packages/fcl-pdf/Makefile

@@ -0,0 +1,2617 @@
+#
+# Don't edit, this file is generated by FPCMake Version 2.0.0 [2015-09-05 rev 31523]
+#
+default: all
+MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-haiku i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian i386-nativent i386-iphonesim i386-android i386-aros m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos m68k-embedded powerpc-linux powerpc-netbsd powerpc-amiga powerpc-macos powerpc-darwin powerpc-morphos powerpc-embedded powerpc-wii powerpc-aix sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-netbsd x86_64-solaris x86_64-openbsd x86_64-darwin x86_64-win64 x86_64-embedded x86_64-iphonesim x86_64-aros x86_64-dragonfly arm-linux arm-palmos arm-darwin arm-wince arm-gba arm-nds arm-embedded arm-symbian arm-android powerpc64-linux powerpc64-darwin powerpc64-embedded powerpc64-aix avr-embedded armeb-linux armeb-embedded mips-linux mipsel-linux mipsel-embedded mipsel-android jvm-java jvm-android i8086-msdos i8086-win16 aarch64-linux aarch64-darwin
+BSDs = freebsd netbsd openbsd darwin dragonfly
+UNIXs = linux $(BSDs) solaris qnx haiku aix
+LIMIT83fs = go32v2 os2 emx watcom msdos win16
+OSNeedsComspecToRunBatch = go32v2 watcom
+FORCE:
+.PHONY: FORCE
+override PATH:=$(patsubst %/,%,$(subst \,/,$(PATH)))
+ifneq ($(findstring darwin,$(OSTYPE)),)
+inUnix=1 #darwin
+SEARCHPATH:=$(filter-out .,$(subst :, ,$(PATH)))
+else
+ifeq ($(findstring ;,$(PATH)),)
+inUnix=1
+SEARCHPATH:=$(filter-out .,$(subst :, ,$(PATH)))
+else
+SEARCHPATH:=$(subst ;, ,$(PATH))
+endif
+endif
+SEARCHPATH+=$(patsubst %/,%,$(subst \,/,$(dir $(MAKE))))
+PWD:=$(strip $(wildcard $(addsuffix /pwd.exe,$(SEARCHPATH))))
+ifeq ($(PWD),)
+PWD:=$(strip $(wildcard $(addsuffix /pwd,$(SEARCHPATH))))
+ifeq ($(PWD),)
+$(error You need the GNU utils package to use this Makefile)
+else
+PWD:=$(firstword $(PWD))
+SRCEXEEXT=
+endif
+else
+PWD:=$(firstword $(PWD))
+SRCEXEEXT=.exe
+endif
+ifndef inUnix
+ifeq ($(OS),Windows_NT)
+inWinNT=1
+else
+ifdef OS2_SHELL
+inOS2=1
+endif
+endif
+else
+ifneq ($(findstring cygdrive,$(PATH)),)
+inCygWin=1
+endif
+endif
+ifdef inUnix
+SRCBATCHEXT=.sh
+else
+ifdef inOS2
+SRCBATCHEXT=.cmd
+else
+SRCBATCHEXT=.bat
+endif
+endif
+ifdef COMSPEC
+ifneq ($(findstring $(OS_SOURCE),$(OSNeedsComspecToRunBatch)),)
+ifndef RUNBATCH
+RUNBATCH=$(COMSPEC) /C
+endif
+endif
+endif
+ifdef inUnix
+PATHSEP=/
+else
+PATHSEP:=$(subst /,\,/)
+ifdef inCygWin
+PATHSEP=/
+endif
+endif
+ifdef PWD
+BASEDIR:=$(subst \,/,$(shell $(PWD)))
+ifdef inCygWin
+ifneq ($(findstring /cygdrive/,$(BASEDIR)),)
+BASENODIR:=$(patsubst /cygdrive%,%,$(BASEDIR))
+BASEDRIVE:=$(firstword $(subst /, ,$(BASENODIR)))
+BASEDIR:=$(subst /cygdrive/$(BASEDRIVE)/,$(BASEDRIVE):/,$(BASEDIR))
+endif
+endif
+else
+BASEDIR=.
+endif
+ifdef inOS2
+ifndef ECHO
+ECHO:=$(strip $(wildcard $(addsuffix /gecho$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO:=$(strip $(wildcard $(addsuffix /echo$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO=echo
+else
+ECHO:=$(firstword $(ECHO))
+endif
+else
+ECHO:=$(firstword $(ECHO))
+endif
+endif
+export ECHO
+endif
+override DEFAULT_FPCDIR=../..
+ifndef FPC
+ifdef PP
+FPC=$(PP)
+endif
+endif
+ifndef FPC
+FPCPROG:=$(strip $(wildcard $(addsuffix /fpc$(SRCEXEEXT),$(SEARCHPATH))))
+ifneq ($(FPCPROG),)
+FPCPROG:=$(firstword $(FPCPROG))
+ifneq ($(CPU_TARGET),)
+FPC:=$(shell $(FPCPROG) -P$(CPU_TARGET) -PB)
+else
+FPC:=$(shell $(FPCPROG) -PB)
+endif
+ifneq ($(findstring Error,$(FPC)),)
+override FPC=$(firstword $(strip $(wildcard $(addsuffix /ppc386$(SRCEXEEXT),$(SEARCHPATH)))))
+else
+ifeq ($(strip $(wildcard $(FPC))),)
+FPC:=$(firstword $(FPCPROG))
+endif
+endif
+else
+override FPC=$(firstword $(strip $(wildcard $(addsuffix /ppc386$(SRCEXEEXT),$(SEARCHPATH)))))
+endif
+endif
+override FPC:=$(subst $(SRCEXEEXT),,$(FPC))
+override FPC:=$(subst \,/,$(FPC))$(SRCEXEEXT)
+FOUNDFPC:=$(strip $(wildcard $(FPC)))
+ifeq ($(FOUNDFPC),)
+FOUNDFPC=$(strip $(wildcard $(addsuffix /$(FPC),$(SEARCHPATH))))
+ifeq ($(FOUNDFPC),)
+$(error Compiler $(FPC) not found)
+endif
+endif
+ifndef FPC_COMPILERINFO
+FPC_COMPILERINFO:=$(shell $(FPC) -iVSPTPSOTO)
+endif
+ifndef FPC_VERSION
+FPC_VERSION:=$(word 1,$(FPC_COMPILERINFO))
+endif
+export FPC FPC_VERSION FPC_COMPILERINFO
+unexport CHECKDEPEND ALLDEPENDENCIES
+ifndef CPU_TARGET
+ifdef CPU_TARGET_DEFAULT
+CPU_TARGET=$(CPU_TARGET_DEFAULT)
+endif
+endif
+ifndef OS_TARGET
+ifdef OS_TARGET_DEFAULT
+OS_TARGET=$(OS_TARGET_DEFAULT)
+endif
+endif
+ifndef CPU_SOURCE
+CPU_SOURCE:=$(word 2,$(FPC_COMPILERINFO))
+endif
+ifndef CPU_TARGET
+CPU_TARGET:=$(word 3,$(FPC_COMPILERINFO))
+endif
+ifndef OS_SOURCE
+OS_SOURCE:=$(word 4,$(FPC_COMPILERINFO))
+endif
+ifndef OS_TARGET
+OS_TARGET:=$(word 5,$(FPC_COMPILERINFO))
+endif
+FULL_TARGET=$(CPU_TARGET)-$(OS_TARGET)
+FULL_SOURCE=$(CPU_SOURCE)-$(OS_SOURCE)
+ifeq ($(CPU_TARGET),armeb)
+ARCH=arm
+override FPCOPT+=-Cb
+else
+ifeq ($(CPU_TARGET),armel)
+ARCH=arm
+override FPCOPT+=-CaEABI
+else
+ARCH=$(CPU_TARGET)
+endif
+endif
+ifeq ($(FULL_TARGET),arm-embedded)
+ifeq ($(SUBARCH),)
+$(error When compiling for arm-embedded, a sub-architecture (e.g. SUBARCH=armv4t or SUBARCH=armv7m) must be defined)
+endif
+override FPCOPT+=-Cp$(SUBARCH)
+endif
+ifeq ($(FULL_TARGET),avr-embedded)
+ifeq ($(SUBARCH),)
+$(error When compiling for avr-embedded, a sub-architecture (e.g. SUBARCH=avr25 or SUBARCH=avr35) must be defined)
+endif
+override FPCOPT+=-Cp$(SUBARCH)
+endif
+ifeq ($(FULL_TARGET),mipsel-embedded)
+ifeq ($(SUBARCH),)
+$(error When compiling for mipsel-embedded, a sub-architecture (e.g. SUBARCH=pic32mx) must be defined)
+endif
+override FPCOPT+=-Cp$(SUBARCH)
+endif
+ifneq ($(findstring $(OS_SOURCE),$(LIMIT83fs)),)
+TARGETSUFFIX=$(OS_TARGET)
+SOURCESUFFIX=$(OS_SOURCE)
+else
+ifneq ($(findstring $(OS_TARGET),$(LIMIT83fs)),)
+TARGETSUFFIX=$(OS_TARGET)
+else
+TARGETSUFFIX=$(FULL_TARGET)
+endif
+SOURCESUFFIX=$(FULL_SOURCE)
+endif
+ifneq ($(FULL_TARGET),$(FULL_SOURCE))
+CROSSCOMPILE=1
+endif
+ifeq ($(findstring makefile,$(MAKECMDGOALS)),)
+ifeq ($(findstring $(FULL_TARGET),$(MAKEFILETARGETS)),)
+$(error The Makefile doesn't support target $(FULL_TARGET), please run fpcmake first)
+endif
+endif
+ifneq ($(findstring $(OS_TARGET),$(BSDs)),)
+BSDhier=1
+endif
+ifeq ($(OS_TARGET),linux)
+linuxHier=1
+endif
+ifndef CROSSCOMPILE
+BUILDFULLNATIVE=1
+export BUILDFULLNATIVE
+endif
+ifdef BUILDFULLNATIVE
+BUILDNATIVE=1
+export BUILDNATIVE
+endif
+export OS_TARGET OS_SOURCE ARCH CPU_TARGET CPU_SOURCE FULL_TARGET FULL_SOURCE TARGETSUFFIX SOURCESUFFIX CROSSCOMPILE
+ifdef FPCDIR
+override FPCDIR:=$(subst \,/,$(FPCDIR))
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR=wrong
+endif
+else
+override FPCDIR=wrong
+endif
+ifdef DEFAULT_FPCDIR
+ifeq ($(FPCDIR),wrong)
+override FPCDIR:=$(subst \,/,$(DEFAULT_FPCDIR))
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR=wrong
+endif
+endif
+endif
+ifeq ($(FPCDIR),wrong)
+ifdef inUnix
+override FPCDIR=/usr/local/lib/fpc/$(FPC_VERSION)
+ifeq ($(wildcard $(FPCDIR)/units),)
+override FPCDIR=/usr/lib/fpc/$(FPC_VERSION)
+endif
+else
+override FPCDIR:=$(subst /$(FPC),,$(firstword $(strip $(wildcard $(addsuffix /$(FPC),$(SEARCHPATH))))))
+override FPCDIR:=$(FPCDIR)/..
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR:=$(FPCDIR)/..
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR:=$(BASEDIR)
+ifeq ($(wildcard $(addprefix $(FPCDIR)/,rtl units)),)
+override FPCDIR=c:/pp
+endif
+endif
+endif
+endif
+endif
+ifndef CROSSBINDIR
+CROSSBINDIR:=$(wildcard $(FPCDIR)/bin/$(TARGETSUFFIX))
+endif
+ifneq ($(findstring $(OS_TARGET),darwin iphonesim),)
+ifeq ($(OS_SOURCE),darwin)
+DARWIN2DARWIN=1
+endif
+endif
+ifndef BINUTILSPREFIX
+ifndef CROSSBINDIR
+ifdef CROSSCOMPILE
+ifneq ($(OS_TARGET),msdos)
+ifndef DARWIN2DARWIN
+ifneq ($(CPU_TARGET),jvm)
+BINUTILSPREFIX=$(CPU_TARGET)-$(OS_TARGET)-
+ifeq ($(OS_TARGET),android)
+ifeq ($(CPU_TARGET),arm)
+BINUTILSPREFIX=arm-linux-androideabi-
+else
+ifeq ($(CPU_TARGET),i386)
+BINUTILSPREFIX=i686-linux-android-
+else
+ifeq ($(CPU_TARGET),mipsel)
+BINUTILSPREFIX=mipsel-linux-android-
+endif
+endif
+endif
+endif
+endif
+endif
+else
+BINUTILSPREFIX=$(OS_TARGET)-
+endif
+endif
+endif
+endif
+UNITSDIR:=$(wildcard $(FPCDIR)/units/$(TARGETSUFFIX))
+ifeq ($(UNITSDIR),)
+UNITSDIR:=$(wildcard $(FPCDIR)/units/$(OS_TARGET))
+endif
+PACKAGESDIR:=$(wildcard $(FPCDIR) $(FPCDIR)/packages $(FPCDIR)/packages/base $(FPCDIR)/packages/extra)
+ifndef FPCFPMAKE
+ifdef CROSSCOMPILE
+ifeq ($(strip $(wildcard $(addsuffix /compiler/ppc$(SRCEXEEXT),$(FPCDIR)))),)
+FPCPROG:=$(strip $(wildcard $(addsuffix /fpc$(SRCEXEEXT),$(SEARCHPATH))))
+ifneq ($(FPCPROG),)
+FPCPROG:=$(firstword $(FPCPROG))
+FPCFPMAKE:=$(shell $(FPCPROG) -PB)
+ifeq ($(strip $(wildcard $(FPCFPMAKE))),)
+FPCFPMAKE:=$(firstword $(FPCPROG))
+endif
+else
+override FPCFPMAKE=$(firstword $(strip $(wildcard $(addsuffix /ppc386$(SRCEXEEXT),$(SEARCHPATH)))))
+endif
+else
+FPCFPMAKE=$(strip $(wildcard $(addsuffix /compiler/ppc$(SRCEXEEXT),$(FPCDIR))))
+FPMAKE_SKIP_CONFIG=-n
+export FPCFPMAKE
+export FPMAKE_SKIP_CONFIG
+endif
+else
+FPMAKE_SKIP_CONFIG=-n
+FPCFPMAKE=$(FPC)
+endif
+endif
+override PACKAGE_NAME=fcl-pdf
+override PACKAGE_VERSION=3.1.1
+FPMAKE_BIN_CLEAN=$(wildcard ./fpmake$(SRCEXEEXT))
+ifdef OS_TARGET
+FPC_TARGETOPT+=--os=$(OS_TARGET)
+endif
+ifdef CPU_TARGET
+FPC_TARGETOPT+=--cpu=$(CPU_TARGET)
+endif
+LOCALFPMAKE=./fpmake$(SRCEXEEXT)
+PACKAGEDIR_FPMKUNIT:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /fpmkunit/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_FPMKUNIT),)
+ifneq ($(wildcard $(PACKAGEDIR_FPMKUNIT)/units_bs/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_FPMKUNIT=$(PACKAGEDIR_FPMKUNIT)/units_bs/$(SOURCESUFFIX)
+else
+UNITDIR_FPMAKE_FPMKUNIT=$(PACKAGEDIR_FPMKUNIT)
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_FPMKUNIT)/$(FPCMADE):
+	$(MAKE) -C $(PACKAGEDIR_FPMKUNIT) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_FPMKUNIT)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_FPMKUNIT=
+UNITDIR_FPMKUNIT:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /fpmkunit/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_FPMKUNIT),)
+UNITDIR_FPMKUNIT:=$(firstword $(UNITDIR_FPMKUNIT))
+else
+UNITDIR_FPMKUNIT=
+endif
+endif
+ifdef UNITDIR_FPMAKE_FPMKUNIT
+override COMPILER_FPMAKE_UNITDIR+=$(UNITDIR_FPMAKE_FPMKUNIT)
+endif
+override INSTALL_FPCPACKAGE=y
+ifdef REQUIRE_UNITSDIR
+override UNITSDIR+=$(REQUIRE_UNITSDIR)
+endif
+ifdef REQUIRE_PACKAGESDIR
+override PACKAGESDIR+=$(REQUIRE_PACKAGESDIR)
+endif
+ifdef ZIPINSTALL
+ifneq ($(findstring $(OS_TARGET),$(UNIXs)),)
+UNIXHier=1
+endif
+else
+ifneq ($(findstring $(OS_SOURCE),$(UNIXs)),)
+UNIXHier=1
+endif
+endif
+ifndef INSTALL_PREFIX
+ifdef PREFIX
+INSTALL_PREFIX=$(PREFIX)
+endif
+endif
+ifndef INSTALL_PREFIX
+ifdef UNIXHier
+INSTALL_PREFIX=/usr/local
+else
+ifdef INSTALL_FPCPACKAGE
+INSTALL_BASEDIR:=/pp
+else
+INSTALL_BASEDIR:=/$(PACKAGE_NAME)
+endif
+endif
+endif
+export INSTALL_PREFIX
+ifdef INSTALL_FPCSUBDIR
+export INSTALL_FPCSUBDIR
+endif
+ifndef DIST_DESTDIR
+DIST_DESTDIR:=$(BASEDIR)
+endif
+export DIST_DESTDIR
+ifndef COMPILER_UNITTARGETDIR
+ifdef PACKAGEDIR_MAIN
+COMPILER_UNITTARGETDIR=$(PACKAGEDIR_MAIN)/units/$(TARGETSUFFIX)
+else
+COMPILER_UNITTARGETDIR=units/$(TARGETSUFFIX)
+endif
+endif
+ifndef COMPILER_TARGETDIR
+COMPILER_TARGETDIR=.
+endif
+ifndef INSTALL_BASEDIR
+ifdef UNIXHier
+ifdef INSTALL_FPCPACKAGE
+INSTALL_BASEDIR:=$(INSTALL_PREFIX)/lib/fpc/$(FPC_VERSION)
+else
+INSTALL_BASEDIR:=$(INSTALL_PREFIX)/lib/$(PACKAGE_NAME)
+endif
+else
+INSTALL_BASEDIR:=$(INSTALL_PREFIX)
+endif
+endif
+ifndef INSTALL_BINDIR
+ifdef UNIXHier
+INSTALL_BINDIR:=$(INSTALL_PREFIX)/bin
+else
+INSTALL_BINDIR:=$(INSTALL_BASEDIR)/bin
+ifdef INSTALL_FPCPACKAGE
+ifdef CROSSCOMPILE
+ifdef CROSSINSTALL
+INSTALL_BINDIR:=$(INSTALL_BINDIR)/$(SOURCESUFFIX)
+else
+INSTALL_BINDIR:=$(INSTALL_BINDIR)/$(TARGETSUFFIX)
+endif
+else
+INSTALL_BINDIR:=$(INSTALL_BINDIR)/$(TARGETSUFFIX)
+endif
+endif
+endif
+endif
+ifndef INSTALL_UNITDIR
+INSTALL_UNITDIR:=$(INSTALL_BASEDIR)/units/$(TARGETSUFFIX)
+ifdef INSTALL_FPCPACKAGE
+ifdef PACKAGE_NAME
+INSTALL_UNITDIR:=$(INSTALL_UNITDIR)/$(PACKAGE_NAME)
+endif
+endif
+endif
+ifndef INSTALL_LIBDIR
+ifdef UNIXHier
+INSTALL_LIBDIR:=$(INSTALL_PREFIX)/lib
+else
+INSTALL_LIBDIR:=$(INSTALL_UNITDIR)
+endif
+endif
+ifndef INSTALL_SOURCEDIR
+ifdef UNIXHier
+ifdef BSDhier
+SRCPREFIXDIR=share/src
+else
+ifdef linuxHier
+SRCPREFIXDIR=share/src
+else
+SRCPREFIXDIR=src
+endif
+endif
+ifdef INSTALL_FPCPACKAGE
+ifdef INSTALL_FPCSUBDIR
+INSTALL_SOURCEDIR:=$(INSTALL_PREFIX)/$(SRCPREFIXDIR)/fpc-$(FPC_VERSION)/$(INSTALL_FPCSUBDIR)/$(PACKAGE_NAME)
+else
+INSTALL_SOURCEDIR:=$(INSTALL_PREFIX)/$(SRCPREFIXDIR)/fpc-$(FPC_VERSION)/$(PACKAGE_NAME)
+endif
+else
+INSTALL_SOURCEDIR:=$(INSTALL_PREFIX)/$(SRCPREFIXDIR)/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+endif
+else
+ifdef INSTALL_FPCPACKAGE
+ifdef INSTALL_FPCSUBDIR
+INSTALL_SOURCEDIR:=$(INSTALL_BASEDIR)/source/$(INSTALL_FPCSUBDIR)/$(PACKAGE_NAME)
+else
+INSTALL_SOURCEDIR:=$(INSTALL_BASEDIR)/source/$(PACKAGE_NAME)
+endif
+else
+INSTALL_SOURCEDIR:=$(INSTALL_BASEDIR)/source
+endif
+endif
+endif
+ifndef INSTALL_DOCDIR
+ifdef UNIXHier
+ifdef BSDhier
+DOCPREFIXDIR=share/doc
+else
+ifdef linuxHier
+DOCPREFIXDIR=share/doc
+else
+DOCPREFIXDIR=doc
+endif
+endif
+ifdef INSTALL_FPCPACKAGE
+INSTALL_DOCDIR:=$(INSTALL_PREFIX)/$(DOCPREFIXDIR)/fpc-$(FPC_VERSION)/$(PACKAGE_NAME)
+else
+INSTALL_DOCDIR:=$(INSTALL_PREFIX)/$(DOCPREFIXDIR)/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+endif
+else
+ifdef INSTALL_FPCPACKAGE
+INSTALL_DOCDIR:=$(INSTALL_BASEDIR)/doc/$(PACKAGE_NAME)
+else
+INSTALL_DOCDIR:=$(INSTALL_BASEDIR)/doc
+endif
+endif
+endif
+ifndef INSTALL_EXAMPLEDIR
+ifdef UNIXHier
+ifdef INSTALL_FPCPACKAGE
+ifdef BSDhier
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/share/examples/fpc-$(FPC_VERSION)/$(PACKAGE_NAME)
+else
+ifdef linuxHier
+INSTALL_EXAMPLEDIR:=$(INSTALL_DOCDIR)/examples
+else
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/doc/fpc-$(FPC_VERSION)/examples/$(PACKAGE_NAME)
+endif
+endif
+else
+ifdef BSDhier
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/share/examples/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+else
+ifdef linuxHier
+INSTALL_EXAMPLEDIR:=$(INSTALL_DOCDIR)/examples/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+else
+INSTALL_EXAMPLEDIR:=$(INSTALL_PREFIX)/doc/$(PACKAGE_NAME)-$(PACKAGE_VERSION)
+endif
+endif
+endif
+else
+ifdef INSTALL_FPCPACKAGE
+INSTALL_EXAMPLEDIR:=$(INSTALL_BASEDIR)/examples/$(PACKAGE_NAME)
+else
+INSTALL_EXAMPLEDIR:=$(INSTALL_BASEDIR)/examples
+endif
+endif
+endif
+ifndef INSTALL_DATADIR
+INSTALL_DATADIR=$(INSTALL_BASEDIR)
+endif
+ifndef INSTALL_SHAREDDIR
+INSTALL_SHAREDDIR=$(INSTALL_PREFIX)/lib
+endif
+ifdef CROSSCOMPILE
+ifndef CROSSBINDIR
+CROSSBINDIR:=$(wildcard $(CROSSTARGETDIR)/bin/$(SOURCESUFFIX))
+ifeq ($(CROSSBINDIR),)
+CROSSBINDIR:=$(wildcard $(INSTALL_BASEDIR)/cross/$(TARGETSUFFIX)/bin/$(FULL_SOURCE))
+endif
+endif
+else
+CROSSBINDIR=
+endif
+BATCHEXT=.bat
+LOADEREXT=.as
+EXEEXT=.exe
+PPLEXT=.ppl
+PPUEXT=.ppu
+OEXT=.o
+ASMEXT=.s
+SMARTEXT=.sl
+STATICLIBEXT=.a
+SHAREDLIBEXT=.so
+SHAREDLIBPREFIX=libfp
+STATICLIBPREFIX=libp
+IMPORTLIBPREFIX=libimp
+RSTEXT=.rst
+EXEDBGEXT=.dbg
+ifeq ($(OS_TARGET),go32v1)
+STATICLIBPREFIX=
+SHORTSUFFIX=v1
+endif
+ifeq ($(OS_TARGET),go32v2)
+STATICLIBPREFIX=
+SHORTSUFFIX=dos
+IMPORTLIBPREFIX=
+endif
+ifeq ($(OS_TARGET),watcom)
+STATICLIBPREFIX=
+OEXT=.obj
+ASMEXT=.asm
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=wat
+IMPORTLIBPREFIX=
+endif
+ifneq ($(CPU_TARGET),jvm)
+ifeq ($(OS_TARGET),android)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=lnx
+endif
+endif
+ifeq ($(OS_TARGET),linux)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=lnx
+endif
+ifeq ($(OS_TARGET),dragonfly)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=df
+endif
+ifeq ($(OS_TARGET),freebsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=fbs
+endif
+ifeq ($(OS_TARGET),netbsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=nbs
+endif
+ifeq ($(OS_TARGET),openbsd)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=obs
+endif
+ifeq ($(OS_TARGET),win32)
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=w32
+endif
+ifeq ($(OS_TARGET),os2)
+BATCHEXT=.cmd
+AOUTEXT=.out
+STATICLIBPREFIX=
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=os2
+ECHO=echo
+IMPORTLIBPREFIX=
+endif
+ifeq ($(OS_TARGET),emx)
+BATCHEXT=.cmd
+AOUTEXT=.out
+STATICLIBPREFIX=
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=emx
+ECHO=echo
+IMPORTLIBPREFIX=
+endif
+ifeq ($(OS_TARGET),amiga)
+EXEEXT=
+SHAREDLIBEXT=.library
+SHORTSUFFIX=amg
+endif
+ifeq ($(OS_TARGET),aros)
+EXEEXT=
+SHAREDLIBEXT=.library
+SHORTSUFFIX=aros
+endif
+ifeq ($(OS_TARGET),morphos)
+EXEEXT=
+SHAREDLIBEXT=.library
+SHORTSUFFIX=mos
+endif
+ifeq ($(OS_TARGET),atari)
+EXEEXT=.ttp
+SHORTSUFFIX=ata
+endif
+ifeq ($(OS_TARGET),beos)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=be
+endif
+ifeq ($(OS_TARGET),haiku)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=hai
+endif
+ifeq ($(OS_TARGET),solaris)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=sun
+endif
+ifeq ($(OS_TARGET),qnx)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=qnx
+endif
+ifeq ($(OS_TARGET),netware)
+EXEEXT=.nlm
+STATICLIBPREFIX=
+SHORTSUFFIX=nw
+IMPORTLIBPREFIX=imp
+endif
+ifeq ($(OS_TARGET),netwlibc)
+EXEEXT=.nlm
+STATICLIBPREFIX=
+SHORTSUFFIX=nwl
+IMPORTLIBPREFIX=imp
+endif
+ifeq ($(OS_TARGET),macos)
+BATCHEXT=
+EXEEXT=
+DEBUGSYMEXT=.xcoff
+SHORTSUFFIX=mac
+IMPORTLIBPREFIX=imp
+endif
+ifneq ($(findstring $(OS_TARGET),darwin iphonesim),)
+BATCHEXT=.sh
+EXEEXT=
+HASSHAREDLIB=1
+SHORTSUFFIX=dwn
+EXEDBGEXT=.dSYM
+endif
+ifeq ($(OS_TARGET),gba)
+EXEEXT=.gba
+SHAREDLIBEXT=.so
+SHORTSUFFIX=gba
+endif
+ifeq ($(OS_TARGET),symbian)
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=symbian
+endif
+ifeq ($(OS_TARGET),NativeNT)
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=nativent
+endif
+ifeq ($(OS_TARGET),wii)
+EXEEXT=.dol
+SHAREDLIBEXT=.so
+SHORTSUFFIX=wii
+endif
+ifeq ($(OS_TARGET),aix)
+BATCHEXT=.sh
+EXEEXT=
+SHORTSUFFIX=aix
+endif
+ifeq ($(OS_TARGET),java)
+OEXT=.class
+ASMEXT=.j
+SHAREDLIBEXT=.jar
+SHORTSUFFIX=java
+endif
+ifeq ($(CPU_TARGET),jvm)
+ifeq ($(OS_TARGET),android)
+OEXT=.class
+ASMEXT=.j
+SHAREDLIBEXT=.jar
+SHORTSUFFIX=android
+endif
+endif
+ifeq ($(OS_TARGET),msdos)
+STATICLIBPREFIX=
+STATICLIBEXT=.a
+SHORTSUFFIX=d16
+endif
+ifeq ($(OS_TARGET),embedded)
+EXEEXT=.bin
+SHORTSUFFIX=emb
+endif
+ifeq ($(OS_TARGET),win16)
+STATICLIBPREFIX=
+STATICLIBEXT=.a
+SHAREDLIBEXT=.dll
+SHORTSUFFIX=w16
+endif
+ifneq ($(findstring $(OS_SOURCE),$(LIMIT83fs)),)
+FPCMADE=fpcmade.$(SHORTSUFFIX)
+ZIPSUFFIX=$(SHORTSUFFIX)
+ZIPCROSSPREFIX=
+ZIPSOURCESUFFIX=src
+ZIPEXAMPLESUFFIX=exm
+else
+FPCMADE=fpcmade.$(TARGETSUFFIX)
+ZIPSOURCESUFFIX=.source
+ZIPEXAMPLESUFFIX=.examples
+ifdef CROSSCOMPILE
+ZIPSUFFIX=.$(SOURCESUFFIX)
+ZIPCROSSPREFIX=$(TARGETSUFFIX)-
+else
+ZIPSUFFIX=.$(TARGETSUFFIX)
+ZIPCROSSPREFIX=
+endif
+endif
+ifndef ECHO
+ECHO:=$(strip $(wildcard $(addsuffix /gecho$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO:=$(strip $(wildcard $(addsuffix /echo$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ECHO),)
+ECHO= __missing_command_ECHO
+else
+ECHO:=$(firstword $(ECHO))
+endif
+else
+ECHO:=$(firstword $(ECHO))
+endif
+endif
+export ECHO
+ifndef DATE
+DATE:=$(strip $(wildcard $(addsuffix /gdate$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(DATE),)
+DATE:=$(strip $(wildcard $(addsuffix /date$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(DATE),)
+DATE= __missing_command_DATE
+else
+DATE:=$(firstword $(DATE))
+endif
+else
+DATE:=$(firstword $(DATE))
+endif
+endif
+export DATE
+ifndef GINSTALL
+GINSTALL:=$(strip $(wildcard $(addsuffix /ginstall$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(GINSTALL),)
+GINSTALL:=$(strip $(wildcard $(addsuffix /install$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(GINSTALL),)
+GINSTALL= __missing_command_GINSTALL
+else
+GINSTALL:=$(firstword $(GINSTALL))
+endif
+else
+GINSTALL:=$(firstword $(GINSTALL))
+endif
+endif
+export GINSTALL
+ifndef CPPROG
+CPPROG:=$(strip $(wildcard $(addsuffix /cp$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(CPPROG),)
+CPPROG= __missing_command_CPPROG
+else
+CPPROG:=$(firstword $(CPPROG))
+endif
+endif
+export CPPROG
+ifndef RMPROG
+RMPROG:=$(strip $(wildcard $(addsuffix /rm$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(RMPROG),)
+RMPROG= __missing_command_RMPROG
+else
+RMPROG:=$(firstword $(RMPROG))
+endif
+endif
+export RMPROG
+ifndef MVPROG
+MVPROG:=$(strip $(wildcard $(addsuffix /mv$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(MVPROG),)
+MVPROG= __missing_command_MVPROG
+else
+MVPROG:=$(firstword $(MVPROG))
+endif
+endif
+export MVPROG
+ifndef MKDIRPROG
+MKDIRPROG:=$(strip $(wildcard $(addsuffix /gmkdir$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(MKDIRPROG),)
+MKDIRPROG:=$(strip $(wildcard $(addsuffix /mkdir$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(MKDIRPROG),)
+MKDIRPROG= __missing_command_MKDIRPROG
+else
+MKDIRPROG:=$(firstword $(MKDIRPROG))
+endif
+else
+MKDIRPROG:=$(firstword $(MKDIRPROG))
+endif
+endif
+export MKDIRPROG
+ifndef ECHOREDIR
+ifndef inUnix
+ECHOREDIR=echo
+else
+ECHOREDIR=$(ECHO)
+endif
+endif
+ifndef COPY
+COPY:=$(CPPROG) -fp
+endif
+ifndef COPYTREE
+COPYTREE:=$(CPPROG) -Rfp
+endif
+ifndef MKDIRTREE
+MKDIRTREE:=$(MKDIRPROG) -p
+endif
+ifndef MOVE
+MOVE:=$(MVPROG) -f
+endif
+ifndef DEL
+DEL:=$(RMPROG) -f
+endif
+ifndef DELTREE
+DELTREE:=$(RMPROG) -rf
+endif
+ifndef INSTALL
+ifdef inUnix
+INSTALL:=$(GINSTALL) -c -m 644
+else
+INSTALL:=$(COPY)
+endif
+endif
+ifndef INSTALLEXE
+ifdef inUnix
+INSTALLEXE:=$(GINSTALL) -c -m 755
+else
+INSTALLEXE:=$(COPY)
+endif
+endif
+ifndef MKDIR
+MKDIR:=$(GINSTALL) -m 755 -d
+endif
+export ECHOREDIR COPY COPYTREE MOVE DEL DELTREE INSTALL INSTALLEXE MKDIR
+ifndef PPUMOVE
+PPUMOVE:=$(strip $(wildcard $(addsuffix /ppumove$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(PPUMOVE),)
+PPUMOVE= __missing_command_PPUMOVE
+else
+PPUMOVE:=$(firstword $(PPUMOVE))
+endif
+endif
+export PPUMOVE
+ifndef FPCMAKE
+FPCMAKE:=$(strip $(wildcard $(addsuffix /fpcmake$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(FPCMAKE),)
+FPCMAKE= __missing_command_FPCMAKE
+else
+FPCMAKE:=$(firstword $(FPCMAKE))
+endif
+endif
+export FPCMAKE
+ifndef ZIPPROG
+ZIPPROG:=$(strip $(wildcard $(addsuffix /zip$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(ZIPPROG),)
+ZIPPROG= __missing_command_ZIPPROG
+else
+ZIPPROG:=$(firstword $(ZIPPROG))
+endif
+endif
+export ZIPPROG
+ifndef TARPROG
+TARPROG:=$(strip $(wildcard $(addsuffix /gtar$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(TARPROG),)
+TARPROG:=$(strip $(wildcard $(addsuffix /tar$(SRCEXEEXT),$(SEARCHPATH))))
+ifeq ($(TARPROG),)
+TARPROG= __missing_command_TARPROG
+else
+TARPROG:=$(firstword $(TARPROG))
+endif
+else
+TARPROG:=$(firstword $(TARPROG))
+endif
+endif
+export TARPROG
+ASNAME=$(BINUTILSPREFIX)as
+LDNAME=$(BINUTILSPREFIX)ld
+ARNAME=$(BINUTILSPREFIX)ar
+RCNAME=$(BINUTILSPREFIX)rc
+NASMNAME=$(BINUTILSPREFIX)nasm
+ifndef ASPROG
+ifdef CROSSBINDIR
+ASPROG=$(CROSSBINDIR)/$(ASNAME)$(SRCEXEEXT)
+else
+ASPROG=$(ASNAME)
+endif
+endif
+ifndef LDPROG
+ifdef CROSSBINDIR
+LDPROG=$(CROSSBINDIR)/$(LDNAME)$(SRCEXEEXT)
+else
+LDPROG=$(LDNAME)
+endif
+endif
+ifndef RCPROG
+ifdef CROSSBINDIR
+RCPROG=$(CROSSBINDIR)/$(RCNAME)$(SRCEXEEXT)
+else
+RCPROG=$(RCNAME)
+endif
+endif
+ifndef ARPROG
+ifdef CROSSBINDIR
+ARPROG=$(CROSSBINDIR)/$(ARNAME)$(SRCEXEEXT)
+else
+ARPROG=$(ARNAME)
+endif
+endif
+ifndef NASMPROG
+ifdef CROSSBINDIR
+NASMPROG=$(CROSSBINDIR)/$(NASMNAME)$(SRCEXEEXT)
+else
+NASMPROG=$(NASMNAME)
+endif
+endif
+AS=$(ASPROG)
+LD=$(LDPROG)
+RC=$(RCPROG)
+AR=$(ARPROG)
+NASM=$(NASMPROG)
+ifdef inUnix
+PPAS=./ppas$(SRCBATCHEXT)
+else
+PPAS=ppas$(SRCBATCHEXT)
+endif
+ifdef inUnix
+LDCONFIG=ldconfig
+else
+LDCONFIG=
+endif
+ifdef DATE
+DATESTR:=$(shell $(DATE) +%Y%m%d)
+else
+DATESTR=
+endif
+ZIPOPT=-9
+ZIPEXT=.zip
+ifeq ($(USETAR),bz2)
+TAROPT=vj
+TAREXT=.tar.bz2
+else
+TAROPT=vz
+TAREXT=.tar.gz
+endif
+override REQUIRE_PACKAGES=rtl fcl-base
+ifeq ($(FULL_TARGET),i386-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-haiku)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-darwin)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-symbian)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-nativent)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-iphonesim)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-android)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i386-aros)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),m68k-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),powerpc-amiga)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),powerpc-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),powerpc-wii)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),powerpc-aix)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),sparc-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),x86_64-netbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),x86_64-solaris)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),x86_64-openbsd)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),x86_64-darwin)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),x86_64-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),x86_64-iphonesim)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),x86_64-aros)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),x86_64-dragonfly)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),arm-palmos)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),arm-darwin)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),arm-gba)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),arm-nds)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),arm-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),arm-symbian)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),arm-android)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),powerpc64-darwin)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),powerpc64-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),powerpc64-aix)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),avr-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),armeb-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),armeb-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),mips-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),mipsel-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),mipsel-embedded)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),mipsel-android)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),jvm-java)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),jvm-android)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i8086-msdos)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),i8086-win16)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),aarch64-linux)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifeq ($(FULL_TARGET),aarch64-darwin)
+REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_PASZLIB=1
+REQUIRE_PACKAGES_FCL-PROCESS=1
+REQUIRE_PACKAGES_HASH=1
+REQUIRE_PACKAGES_LIBTAR=1
+REQUIRE_PACKAGES_FPMKUNIT=1
+REQUIRE_PACKAGES_FCL-BASE=1
+endif
+ifdef REQUIRE_PACKAGES_RTL
+PACKAGEDIR_RTL:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /rtl/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_RTL),)
+ifneq ($(wildcard $(PACKAGEDIR_RTL)/units/$(TARGETSUFFIX)),)
+UNITDIR_RTL=$(PACKAGEDIR_RTL)/units/$(TARGETSUFFIX)
+else
+UNITDIR_RTL=$(PACKAGEDIR_RTL)
+endif
+ifneq ($(wildcard $(PACKAGEDIR_RTL)/units/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_RTL=$(PACKAGEDIR_RTL)/units/$(SOURCESUFFIX)
+else
+ifneq ($(wildcard $(PACKAGEDIR_RTL)/units_bs/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_RTL=$(PACKAGEDIR_RTL)/units_bs/$(SOURCESUFFIX)
+else
+UNITDIR_FPMAKE_RTL=$(PACKAGEDIR_RTL)
+endif
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_RTL)/$(OS_TARGET)/$(FPCMADE):
+	$(MAKE) -C $(PACKAGEDIR_RTL)/$(OS_TARGET) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_RTL)/$(OS_TARGET)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_RTL=
+UNITDIR_RTL:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /rtl/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_RTL),)
+UNITDIR_RTL:=$(firstword $(UNITDIR_RTL))
+else
+UNITDIR_RTL=
+endif
+endif
+ifdef UNITDIR_RTL
+override COMPILER_UNITDIR+=$(UNITDIR_RTL)
+endif
+ifdef UNITDIR_FPMAKE_RTL
+override COMPILER_FPMAKE_UNITDIR+=$(UNITDIR_FPMAKE_RTL)
+endif
+endif
+ifdef REQUIRE_PACKAGES_PASZLIB
+PACKAGEDIR_PASZLIB:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /paszlib/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_PASZLIB),)
+ifneq ($(wildcard $(PACKAGEDIR_PASZLIB)/units/$(TARGETSUFFIX)),)
+UNITDIR_PASZLIB=$(PACKAGEDIR_PASZLIB)/units/$(TARGETSUFFIX)
+else
+UNITDIR_PASZLIB=$(PACKAGEDIR_PASZLIB)
+endif
+ifneq ($(wildcard $(PACKAGEDIR_PASZLIB)/units/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_PASZLIB=$(PACKAGEDIR_PASZLIB)/units/$(SOURCESUFFIX)
+else
+ifneq ($(wildcard $(PACKAGEDIR_PASZLIB)/units_bs/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_PASZLIB=$(PACKAGEDIR_PASZLIB)/units_bs/$(SOURCESUFFIX)
+else
+UNITDIR_FPMAKE_PASZLIB=$(PACKAGEDIR_PASZLIB)
+endif
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_PASZLIB)/$(FPCMADE):
+	$(MAKE) -C $(PACKAGEDIR_PASZLIB) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_PASZLIB)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_PASZLIB=
+UNITDIR_PASZLIB:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /paszlib/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_PASZLIB),)
+UNITDIR_PASZLIB:=$(firstword $(UNITDIR_PASZLIB))
+else
+UNITDIR_PASZLIB=
+endif
+endif
+ifdef UNITDIR_PASZLIB
+override COMPILER_UNITDIR+=$(UNITDIR_PASZLIB)
+endif
+ifdef UNITDIR_FPMAKE_PASZLIB
+override COMPILER_FPMAKE_UNITDIR+=$(UNITDIR_FPMAKE_PASZLIB)
+endif
+endif
+ifdef REQUIRE_PACKAGES_FCL-PROCESS
+PACKAGEDIR_FCL-PROCESS:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /fcl-process/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_FCL-PROCESS),)
+ifneq ($(wildcard $(PACKAGEDIR_FCL-PROCESS)/units/$(TARGETSUFFIX)),)
+UNITDIR_FCL-PROCESS=$(PACKAGEDIR_FCL-PROCESS)/units/$(TARGETSUFFIX)
+else
+UNITDIR_FCL-PROCESS=$(PACKAGEDIR_FCL-PROCESS)
+endif
+ifneq ($(wildcard $(PACKAGEDIR_FCL-PROCESS)/units/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_FCL-PROCESS=$(PACKAGEDIR_FCL-PROCESS)/units/$(SOURCESUFFIX)
+else
+ifneq ($(wildcard $(PACKAGEDIR_FCL-PROCESS)/units_bs/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_FCL-PROCESS=$(PACKAGEDIR_FCL-PROCESS)/units_bs/$(SOURCESUFFIX)
+else
+UNITDIR_FPMAKE_FCL-PROCESS=$(PACKAGEDIR_FCL-PROCESS)
+endif
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_FCL-PROCESS)/$(FPCMADE):
+	$(MAKE) -C $(PACKAGEDIR_FCL-PROCESS) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_FCL-PROCESS)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_FCL-PROCESS=
+UNITDIR_FCL-PROCESS:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /fcl-process/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_FCL-PROCESS),)
+UNITDIR_FCL-PROCESS:=$(firstword $(UNITDIR_FCL-PROCESS))
+else
+UNITDIR_FCL-PROCESS=
+endif
+endif
+ifdef UNITDIR_FCL-PROCESS
+override COMPILER_UNITDIR+=$(UNITDIR_FCL-PROCESS)
+endif
+ifdef UNITDIR_FPMAKE_FCL-PROCESS
+override COMPILER_FPMAKE_UNITDIR+=$(UNITDIR_FPMAKE_FCL-PROCESS)
+endif
+endif
+ifdef REQUIRE_PACKAGES_HASH
+PACKAGEDIR_HASH:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /hash/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_HASH),)
+ifneq ($(wildcard $(PACKAGEDIR_HASH)/units/$(TARGETSUFFIX)),)
+UNITDIR_HASH=$(PACKAGEDIR_HASH)/units/$(TARGETSUFFIX)
+else
+UNITDIR_HASH=$(PACKAGEDIR_HASH)
+endif
+ifneq ($(wildcard $(PACKAGEDIR_HASH)/units/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_HASH=$(PACKAGEDIR_HASH)/units/$(SOURCESUFFIX)
+else
+ifneq ($(wildcard $(PACKAGEDIR_HASH)/units_bs/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_HASH=$(PACKAGEDIR_HASH)/units_bs/$(SOURCESUFFIX)
+else
+UNITDIR_FPMAKE_HASH=$(PACKAGEDIR_HASH)
+endif
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_HASH)/$(FPCMADE):
+	$(MAKE) -C $(PACKAGEDIR_HASH) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_HASH)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_HASH=
+UNITDIR_HASH:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /hash/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_HASH),)
+UNITDIR_HASH:=$(firstword $(UNITDIR_HASH))
+else
+UNITDIR_HASH=
+endif
+endif
+ifdef UNITDIR_HASH
+override COMPILER_UNITDIR+=$(UNITDIR_HASH)
+endif
+ifdef UNITDIR_FPMAKE_HASH
+override COMPILER_FPMAKE_UNITDIR+=$(UNITDIR_FPMAKE_HASH)
+endif
+endif
+ifdef REQUIRE_PACKAGES_LIBTAR
+PACKAGEDIR_LIBTAR:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /libtar/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_LIBTAR),)
+ifneq ($(wildcard $(PACKAGEDIR_LIBTAR)/units/$(TARGETSUFFIX)),)
+UNITDIR_LIBTAR=$(PACKAGEDIR_LIBTAR)/units/$(TARGETSUFFIX)
+else
+UNITDIR_LIBTAR=$(PACKAGEDIR_LIBTAR)
+endif
+ifneq ($(wildcard $(PACKAGEDIR_LIBTAR)/units/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_LIBTAR=$(PACKAGEDIR_LIBTAR)/units/$(SOURCESUFFIX)
+else
+ifneq ($(wildcard $(PACKAGEDIR_LIBTAR)/units_bs/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_LIBTAR=$(PACKAGEDIR_LIBTAR)/units_bs/$(SOURCESUFFIX)
+else
+UNITDIR_FPMAKE_LIBTAR=$(PACKAGEDIR_LIBTAR)
+endif
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_LIBTAR)/$(FPCMADE):
+	$(MAKE) -C $(PACKAGEDIR_LIBTAR) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_LIBTAR)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_LIBTAR=
+UNITDIR_LIBTAR:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /libtar/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_LIBTAR),)
+UNITDIR_LIBTAR:=$(firstword $(UNITDIR_LIBTAR))
+else
+UNITDIR_LIBTAR=
+endif
+endif
+ifdef UNITDIR_LIBTAR
+override COMPILER_UNITDIR+=$(UNITDIR_LIBTAR)
+endif
+ifdef UNITDIR_FPMAKE_LIBTAR
+override COMPILER_FPMAKE_UNITDIR+=$(UNITDIR_FPMAKE_LIBTAR)
+endif
+endif
+ifdef REQUIRE_PACKAGES_FPMKUNIT
+PACKAGEDIR_FPMKUNIT:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /fpmkunit/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_FPMKUNIT),)
+ifneq ($(wildcard $(PACKAGEDIR_FPMKUNIT)/units/$(TARGETSUFFIX)),)
+UNITDIR_FPMKUNIT=$(PACKAGEDIR_FPMKUNIT)/units/$(TARGETSUFFIX)
+else
+UNITDIR_FPMKUNIT=$(PACKAGEDIR_FPMKUNIT)
+endif
+ifneq ($(wildcard $(PACKAGEDIR_FPMKUNIT)/units/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_FPMKUNIT=$(PACKAGEDIR_FPMKUNIT)/units/$(SOURCESUFFIX)
+else
+ifneq ($(wildcard $(PACKAGEDIR_FPMKUNIT)/units_bs/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_FPMKUNIT=$(PACKAGEDIR_FPMKUNIT)/units_bs/$(SOURCESUFFIX)
+else
+UNITDIR_FPMAKE_FPMKUNIT=$(PACKAGEDIR_FPMKUNIT)
+endif
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_FPMKUNIT)/$(FPCMADE):
+	$(MAKE) -C $(PACKAGEDIR_FPMKUNIT) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_FPMKUNIT)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_FPMKUNIT=
+UNITDIR_FPMKUNIT:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /fpmkunit/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_FPMKUNIT),)
+UNITDIR_FPMKUNIT:=$(firstword $(UNITDIR_FPMKUNIT))
+else
+UNITDIR_FPMKUNIT=
+endif
+endif
+ifdef UNITDIR_FPMKUNIT
+override COMPILER_UNITDIR+=$(UNITDIR_FPMKUNIT)
+endif
+ifdef UNITDIR_FPMAKE_FPMKUNIT
+override COMPILER_FPMAKE_UNITDIR+=$(UNITDIR_FPMAKE_FPMKUNIT)
+endif
+endif
+ifdef REQUIRE_PACKAGES_FCL-BASE
+PACKAGEDIR_FCL-BASE:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /fcl-base/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_FCL-BASE),)
+ifneq ($(wildcard $(PACKAGEDIR_FCL-BASE)/units/$(TARGETSUFFIX)),)
+UNITDIR_FCL-BASE=$(PACKAGEDIR_FCL-BASE)/units/$(TARGETSUFFIX)
+else
+UNITDIR_FCL-BASE=$(PACKAGEDIR_FCL-BASE)
+endif
+ifneq ($(wildcard $(PACKAGEDIR_FCL-BASE)/units/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_FCL-BASE=$(PACKAGEDIR_FCL-BASE)/units/$(SOURCESUFFIX)
+else
+ifneq ($(wildcard $(PACKAGEDIR_FCL-BASE)/units_bs/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_FCL-BASE=$(PACKAGEDIR_FCL-BASE)/units_bs/$(SOURCESUFFIX)
+else
+UNITDIR_FPMAKE_FCL-BASE=$(PACKAGEDIR_FCL-BASE)
+endif
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_FCL-BASE)/$(FPCMADE):
+	$(MAKE) -C $(PACKAGEDIR_FCL-BASE) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_FCL-BASE)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_FCL-BASE=
+UNITDIR_FCL-BASE:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /fcl-base/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_FCL-BASE),)
+UNITDIR_FCL-BASE:=$(firstword $(UNITDIR_FCL-BASE))
+else
+UNITDIR_FCL-BASE=
+endif
+endif
+ifdef UNITDIR_FCL-BASE
+override COMPILER_UNITDIR+=$(UNITDIR_FCL-BASE)
+endif
+ifdef UNITDIR_FPMAKE_FCL-BASE
+override COMPILER_FPMAKE_UNITDIR+=$(UNITDIR_FPMAKE_FCL-BASE)
+endif
+endif
+ifndef NOCPUDEF
+override FPCOPTDEF=$(ARCH)
+endif
+ifneq ($(OS_TARGET),$(OS_SOURCE))
+override FPCOPT+=-T$(OS_TARGET)
+endif
+ifneq ($(CPU_TARGET),$(CPU_SOURCE))
+override FPCOPT+=-P$(ARCH)
+endif
+ifeq ($(OS_SOURCE),openbsd)
+override FPCOPT+=-FD$(NEW_BINUTILS_PATH)
+override FPCMAKEOPT+=-FD$(NEW_BINUTILS_PATH)
+override FPMAKE_BUILD_OPT+=-FD$(NEW_BINUTILS_PATH)
+endif
+ifndef CROSSBOOTSTRAP
+ifneq ($(BINUTILSPREFIX),)
+override FPCOPT+=-XP$(BINUTILSPREFIX)
+endif
+ifneq ($(BINUTILSPREFIX),)
+override FPCOPT+=-Xr$(RLINKPATH)
+endif
+endif
+ifndef CROSSCOMPILE
+ifneq ($(BINUTILSPREFIX),)
+override FPCMAKEOPT+=-XP$(BINUTILSPREFIX)
+override FPMAKE_BUILD_OPT+=-XP$(BINUTILSPREFIX)
+endif
+endif
+ifdef UNITDIR
+override FPCOPT+=$(addprefix -Fu,$(UNITDIR))
+endif
+ifdef LIBDIR
+override FPCOPT+=$(addprefix -Fl,$(LIBDIR))
+endif
+ifdef OBJDIR
+override FPCOPT+=$(addprefix -Fo,$(OBJDIR))
+endif
+ifdef INCDIR
+override FPCOPT+=$(addprefix -Fi,$(INCDIR))
+endif
+ifdef LINKSMART
+override FPCOPT+=-XX
+endif
+ifdef CREATESMART
+override FPCOPT+=-CX
+endif
+ifdef DEBUG
+override FPCOPT+=-gl
+override FPCOPTDEF+=DEBUG
+endif
+ifdef RELEASE
+ifneq ($(findstring 2.0.,$(FPC_VERSION)),)
+ifeq ($(CPU_TARGET),i386)
+FPCCPUOPT:=-OG2p3
+endif
+ifeq ($(CPU_TARGET),powerpc)
+FPCCPUOPT:=-O1r
+endif
+else
+FPCCPUOPT:=-O2
+endif
+override FPCOPT+=-Ur -Xs $(FPCCPUOPT) -n
+override FPCOPTDEF+=RELEASE
+endif
+ifdef STRIP
+override FPCOPT+=-Xs
+endif
+ifdef OPTIMIZE
+override FPCOPT+=-O2
+endif
+ifdef VERBOSE
+override FPCOPT+=-vwni
+endif
+ifdef COMPILER_OPTIONS
+override FPCOPT+=$(COMPILER_OPTIONS)
+endif
+ifdef COMPILER_UNITDIR
+override FPCOPT+=$(addprefix -Fu,$(COMPILER_UNITDIR))
+endif
+ifdef COMPILER_LIBRARYDIR
+override FPCOPT+=$(addprefix -Fl,$(COMPILER_LIBRARYDIR))
+endif
+ifdef COMPILER_OBJECTDIR
+override FPCOPT+=$(addprefix -Fo,$(COMPILER_OBJECTDIR))
+endif
+ifdef COMPILER_INCLUDEDIR
+override FPCOPT+=$(addprefix -Fi,$(COMPILER_INCLUDEDIR))
+endif
+ifdef CROSSBINDIR
+override FPCOPT+=-FD$(CROSSBINDIR)
+endif
+ifdef COMPILER_TARGETDIR
+override FPCOPT+=-FE$(COMPILER_TARGETDIR)
+ifeq ($(COMPILER_TARGETDIR),.)
+override TARGETDIRPREFIX=
+else
+override TARGETDIRPREFIX=$(COMPILER_TARGETDIR)/
+endif
+endif
+ifdef COMPILER_UNITTARGETDIR
+override FPCOPT+=-FU$(COMPILER_UNITTARGETDIR)
+ifeq ($(COMPILER_UNITTARGETDIR),.)
+override UNITTARGETDIRPREFIX=
+else
+override UNITTARGETDIRPREFIX=$(COMPILER_UNITTARGETDIR)/
+endif
+else
+ifdef COMPILER_TARGETDIR
+override COMPILER_UNITTARGETDIR=$(COMPILER_TARGETDIR)
+override UNITTARGETDIRPREFIX=$(TARGETDIRPREFIX)
+endif
+endif
+ifdef CREATESHARED
+override FPCOPT+=-Cg
+endif
+ifneq ($(findstring $(OS_TARGET),dragonfly freebsd openbsd netbsd linux solaris),)
+ifneq ($(findstring $(CPU_TARGET),x86_64 mips mipsel),)
+override FPCOPT+=-Cg
+endif
+endif
+ifdef LINKSHARED
+endif
+ifdef OPT
+override FPCOPT+=$(OPT)
+endif
+ifdef FPMAKEBUILDOPT
+override FPMAKE_BUILD_OPT+=$(FPMAKEBUILDOPT)
+endif
+ifdef FPCOPTDEF
+override FPCOPT+=$(addprefix -d,$(FPCOPTDEF))
+endif
+ifdef CFGFILE
+override FPCOPT+=@$(CFGFILE)
+endif
+ifdef USEENV
+override FPCEXTCMD:=$(FPCOPT)
+override FPCOPT:=!FPCEXTCMD
+export FPCEXTCMD
+endif
+override AFULL_TARGET=$(CPU_TARGET)-$(OS_TARGET)
+override AFULL_SOURCE=$(CPU_SOURCE)-$(OS_SOURCE)
+ifneq ($(AFULL_TARGET),$(AFULL_SOURCE))
+override ACROSSCOMPILE=1
+endif
+ifdef ACROSSCOMPILE
+override FPCOPT+=$(CROSSOPT)
+endif
+override COMPILER:=$(strip $(FPC) $(FPCOPT))
+ifneq (,$(findstring -sh ,$(COMPILER)))
+UseEXECPPAS=1
+endif
+ifneq (,$(findstring -s ,$(COMPILER)))
+ifeq ($(FULL_SOURCE),$(FULL_TARGET))
+UseEXECPPAS=1
+endif
+endif
+ifneq ($(UseEXECPPAS),1)
+EXECPPAS=
+else
+ifdef RUNBATCH
+EXECPPAS:=@$(RUNBATCH) $(PPAS)
+else
+EXECPPAS:=@$(PPAS)
+endif
+endif
+ifdef TARGET_RSTS
+override RSTFILES=$(addsuffix $(RSTEXT),$(TARGET_RSTS))
+override CLEANRSTFILES+=$(RSTFILES)
+endif
+.PHONY: fpc_install fpc_sourceinstall fpc_exampleinstall
+ifdef INSTALL_UNITS
+override INSTALLPPUFILES+=$(addsuffix $(PPUEXT),$(INSTALL_UNITS))
+endif
+ifdef INSTALL_BUILDUNIT
+override INSTALLPPUFILES:=$(filter-out $(INSTALL_BUILDUNIT)$(PPUEXT),$(INSTALLPPUFILES))
+endif
+ifdef INSTALLPPUFILES
+override INSTALLPPULINKFILES:=$(subst $(PPUEXT),$(OEXT),$(INSTALLPPUFILES)) $(addprefix $(STATICLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(INSTALLPPUFILES))) $(addprefix $(IMPORTLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(INSTALLPPUFILES)))
+ifneq ($(UNITTARGETDIRPREFIX),)
+override INSTALLPPUFILES:=$(addprefix $(UNITTARGETDIRPREFIX),$(notdir $(INSTALLPPUFILES)))
+override INSTALLPPULINKFILES:=$(wildcard $(addprefix $(UNITTARGETDIRPREFIX),$(notdir $(INSTALLPPULINKFILES))))
+endif
+override INSTALL_CREATEPACKAGEFPC=1
+endif
+ifdef INSTALLEXEFILES
+ifneq ($(TARGETDIRPREFIX),)
+override INSTALLEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(notdir $(INSTALLEXEFILES)))
+endif
+endif
+fpc_install: all $(INSTALLTARGET)
+ifdef INSTALLEXEFILES
+	$(MKDIR) $(INSTALL_BINDIR)
+	$(INSTALLEXE) $(INSTALLEXEFILES) $(INSTALL_BINDIR)
+endif
+ifdef INSTALL_CREATEPACKAGEFPC
+ifdef FPCMAKE
+ifdef PACKAGE_VERSION
+ifneq ($(wildcard Makefile.fpc),)
+	$(FPCMAKE) -p -T$(CPU_TARGET)-$(OS_TARGET) Makefile.fpc
+	$(MKDIR) $(INSTALL_UNITDIR)
+	$(INSTALL) Package.fpc $(INSTALL_UNITDIR)
+endif
+endif
+endif
+endif
+ifdef INSTALLPPUFILES
+	$(MKDIR) $(INSTALL_UNITDIR)
+	$(INSTALL) $(INSTALLPPUFILES) $(INSTALL_UNITDIR)
+ifneq ($(INSTALLPPULINKFILES),)
+	$(INSTALL) $(INSTALLPPULINKFILES) $(INSTALL_UNITDIR)
+endif
+ifneq ($(wildcard $(LIB_FULLNAME)),)
+	$(MKDIR) $(INSTALL_LIBDIR)
+	$(INSTALL) $(LIB_FULLNAME) $(INSTALL_LIBDIR)
+ifdef inUnix
+	ln -sf $(LIB_FULLNAME) $(INSTALL_LIBDIR)/$(LIB_NAME)
+endif
+endif
+endif
+ifdef INSTALL_FILES
+	$(MKDIR) $(INSTALL_DATADIR)
+	$(INSTALL) $(INSTALL_FILES) $(INSTALL_DATADIR)
+endif
+fpc_sourceinstall: distclean
+	$(MKDIR) $(INSTALL_SOURCEDIR)
+	$(COPYTREE) $(BASEDIR)/* $(INSTALL_SOURCEDIR)
+fpc_exampleinstall: $(EXAMPLEINSTALLTARGET) $(addsuffix _distclean,$(TARGET_EXAMPLEDIRS))
+ifdef HASEXAMPLES
+	$(MKDIR) $(INSTALL_EXAMPLEDIR)
+endif
+ifdef EXAMPLESOURCEFILES
+	$(COPY) $(EXAMPLESOURCEFILES) $(INSTALL_EXAMPLEDIR)
+endif
+ifdef TARGET_EXAMPLEDIRS
+	$(COPYTREE) $(addsuffix /*,$(TARGET_EXAMPLEDIRS)) $(INSTALL_EXAMPLEDIR)
+endif
+.PHONY: fpc_distinstall
+fpc_distinstall: install exampleinstall
+.PHONY: fpc_zipinstall fpc_zipsourceinstall fpc_zipexampleinstall
+ifndef PACKDIR
+ifndef inUnix
+PACKDIR=$(BASEDIR)/../fpc-pack
+else
+PACKDIR=/tmp/fpc-pack
+endif
+endif
+ifndef ZIPNAME
+ifdef DIST_ZIPNAME
+ZIPNAME=$(DIST_ZIPNAME)
+else
+ZIPNAME=$(PACKAGE_NAME)
+endif
+endif
+ifndef FULLZIPNAME
+FULLZIPNAME=$(ZIPCROSSPREFIX)$(ZIPPREFIX)$(ZIPNAME)$(ZIPSUFFIX)
+endif
+ifndef ZIPTARGET
+ifdef DIST_ZIPTARGET
+ZIPTARGET=DIST_ZIPTARGET
+else
+ZIPTARGET=install
+endif
+endif
+ifndef USEZIP
+ifdef inUnix
+USETAR=1
+endif
+endif
+ifndef inUnix
+USEZIPWRAPPER=1
+endif
+ifdef USEZIPWRAPPER
+ZIPPATHSEP=$(PATHSEP)
+ZIPWRAPPER=$(subst /,$(PATHSEP),$(DIST_DESTDIR)/fpczip$(SRCBATCHEXT))
+else
+ZIPPATHSEP=/
+endif
+ZIPCMD_CDPACK:=cd $(subst /,$(ZIPPATHSEP),$(PACKDIR))
+ZIPCMD_CDBASE:=cd $(subst /,$(ZIPPATHSEP),$(BASEDIR))
+ifdef USETAR
+ZIPDESTFILE:=$(DIST_DESTDIR)/$(FULLZIPNAME)$(TAREXT)
+ZIPCMD_ZIP:=$(TARPROG) c$(TAROPT)f $(ZIPDESTFILE) *
+else
+ZIPDESTFILE:=$(DIST_DESTDIR)/$(FULLZIPNAME)$(ZIPEXT)
+ZIPCMD_ZIP:=$(subst /,$(ZIPPATHSEP),$(ZIPPROG)) -Dr $(ZIPOPT) $(ZIPDESTFILE) *
+endif
+fpc_zipinstall:
+	$(MAKE) $(ZIPTARGET) INSTALL_PREFIX=$(PACKDIR) ZIPINSTALL=1
+	$(MKDIR) $(DIST_DESTDIR)
+	$(DEL) $(ZIPDESTFILE)
+ifdef USEZIPWRAPPER
+ifneq ($(ECHOREDIR),echo)
+	$(ECHOREDIR) -e "$(subst \,\\,$(ZIPCMD_CDPACK))" > $(ZIPWRAPPER)
+	$(ECHOREDIR) -e "$(subst \,\\,$(ZIPCMD_ZIP))" >> $(ZIPWRAPPER)
+	$(ECHOREDIR) -e "$(subst \,\\,$(ZIPCMD_CDBASE))" >> $(ZIPWRAPPER)
+else
+	echo $(ZIPCMD_CDPACK) > $(ZIPWRAPPER)
+	echo $(ZIPCMD_ZIP) >> $(ZIPWRAPPER)
+	echo $(ZIPCMD_CDBASE) >> $(ZIPWRAPPER)
+endif
+ifdef inUnix
+	/bin/sh $(ZIPWRAPPER)
+else
+ifdef RUNBATCH
+	$(RUNBATCH) $(ZIPWRAPPER)
+else
+	$(ZIPWRAPPER)
+endif
+endif
+	$(DEL) $(ZIPWRAPPER)
+else
+	$(ZIPCMD_CDPACK) ; $(ZIPCMD_ZIP) ; $(ZIPCMD_CDBASE)
+endif
+	$(DELTREE) $(PACKDIR)
+fpc_zipsourceinstall:
+	$(MAKE) fpc_zipinstall ZIPTARGET=sourceinstall ZIPSUFFIX=$(ZIPSOURCESUFFIX)
+fpc_zipexampleinstall:
+ifdef HASEXAMPLES
+	$(MAKE) fpc_zipinstall ZIPTARGET=exampleinstall ZIPSUFFIX=$(ZIPEXAMPLESUFFIX)
+endif
+fpc_zipdistinstall:
+	$(MAKE) fpc_zipinstall ZIPTARGET=distinstall
+.PHONY: fpc_clean fpc_cleanall fpc_distclean
+ifdef EXEFILES
+override CLEANEXEFILES:=$(addprefix $(TARGETDIRPREFIX),$(CLEANEXEFILES))
+override CLEANEXEDBGFILES:=$(addprefix $(TARGETDIRPREFIX),$(CLEANEXEDBGFILES))
+endif
+ifdef CLEAN_PROGRAMS
+override CLEANEXEFILES+=$(addprefix $(TARGETDIRPREFIX),$(addsuffix $(EXEEXT), $(CLEAN_PROGRAMS)))
+override CLEANEXEDBGFILES+=$(addprefix $(TARGETDIRPREFIX),$(addsuffix $(EXEDBGEXT), $(CLEAN_PROGRAMS)))
+endif
+ifdef CLEAN_UNITS
+override CLEANPPUFILES+=$(addsuffix $(PPUEXT),$(CLEAN_UNITS))
+endif
+ifdef CLEANPPUFILES
+override CLEANPPULINKFILES:=$(subst $(PPUEXT),$(OEXT),$(CLEANPPUFILES)) $(addprefix $(STATICLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(CLEANPPUFILES))) $(addprefix $(IMPORTLIBPREFIX),$(subst $(PPUEXT),$(STATICLIBEXT),$(CLEANPPUFILES)))
+ifdef DEBUGSYMEXT
+override CLEANPPULINKFILES+=$(subst $(PPUEXT),$(DEBUGSYMEXT),$(CLEANPPUFILES))
+endif
+override CLEANPPUFILES:=$(addprefix $(UNITTARGETDIRPREFIX),$(CLEANPPUFILES))
+override CLEANPPULINKFILES:=$(wildcard $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANPPULINKFILES)))
+endif
+fpc_clean: $(CLEANTARGET)
+ifdef CLEANEXEFILES
+	-$(DEL) $(CLEANEXEFILES)
+endif
+ifdef CLEANEXEDBGFILES
+	-$(DELTREE) $(CLEANEXEDBGFILES)
+endif
+ifdef CLEANPPUFILES
+	-$(DEL) $(CLEANPPUFILES)
+endif
+ifneq ($(CLEANPPULINKFILES),)
+	-$(DEL) $(CLEANPPULINKFILES)
+endif
+ifdef CLEANRSTFILES
+	-$(DEL) $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANRSTFILES))
+endif
+ifdef CLEAN_FILES
+	-$(DEL) $(CLEAN_FILES)
+endif
+ifdef LIB_NAME
+	-$(DEL) $(LIB_NAME) $(LIB_FULLNAME)
+endif
+	-$(DEL) $(FPCMADE) Package.fpc $(PPAS) script.res link.res $(FPCEXTFILE) $(REDIRFILE)
+	-$(DEL) *$(ASMEXT) *_ppas$(BATCHEXT)
+fpc_cleanall: $(CLEANTARGET)
+ifdef CLEANEXEFILES
+	-$(DEL) $(CLEANEXEFILES)
+endif
+ifdef COMPILER_UNITTARGETDIR
+ifdef CLEANPPUFILES
+	-$(DEL) $(CLEANPPUFILES)
+endif
+ifneq ($(CLEANPPULINKFILES),)
+	-$(DEL) $(CLEANPPULINKFILES)
+endif
+ifdef CLEANRSTFILES
+	-$(DEL) $(addprefix $(UNITTARGETDIRPREFIX),$(CLEANRSTFILES))
+endif
+endif
+ifdef CLEAN_FILES
+	-$(DEL) $(CLEAN_FILES)
+endif
+	-$(DELTREE) units
+	-$(DEL) *$(OEXT) *$(PPUEXT) *$(RSTEXT) *$(ASMEXT) *$(STATICLIBEXT) *$(SHAREDLIBEXT) *$(PPLEXT)
+ifneq ($(PPUEXT),.ppu)
+	-$(DEL) *.o *.ppu *.a
+endif
+	-$(DELTREE) *$(SMARTEXT)
+	-$(DEL) fpcmade.* Package.fpc $(PPAS) script.res link.res $(FPCEXTFILE) $(REDIRFILE)
+	-$(DEL) *_ppas$(BATCHEXT)
+ifdef AOUTEXT
+	-$(DEL) *$(AOUTEXT)
+endif
+ifdef DEBUGSYMEXT
+	-$(DEL) *$(DEBUGSYMEXT)
+endif
+ifdef LOCALFPMAKEBIN
+	-$(DEL) $(LOCALFPMAKEBIN)
+	-$(DEL) $(FPMAKEBINOBJ)
+endif
+fpc_distclean: cleanall
+.PHONY: fpc_baseinfo
+override INFORULES+=fpc_baseinfo
+fpc_baseinfo:
+	@$(ECHO)
+	@$(ECHO)  == Package info ==
+	@$(ECHO)  Package Name..... $(PACKAGE_NAME)
+	@$(ECHO)  Package Version.. $(PACKAGE_VERSION)
+	@$(ECHO)
+	@$(ECHO)  == Configuration info ==
+	@$(ECHO)
+	@$(ECHO)  FPC.......... $(FPC)
+	@$(ECHO)  FPC Version.. $(FPC_VERSION)
+	@$(ECHO)  Source CPU... $(CPU_SOURCE)
+	@$(ECHO)  Target CPU... $(CPU_TARGET)
+	@$(ECHO)  Source OS.... $(OS_SOURCE)
+	@$(ECHO)  Target OS.... $(OS_TARGET)
+	@$(ECHO)  Full Source.. $(FULL_SOURCE)
+	@$(ECHO)  Full Target.. $(FULL_TARGET)
+	@$(ECHO)  SourceSuffix. $(SOURCESUFFIX)
+	@$(ECHO)  TargetSuffix. $(TARGETSUFFIX)
+	@$(ECHO)  FPC fpmake... $(FPCFPMAKE)
+	@$(ECHO)
+	@$(ECHO)  == Directory info ==
+	@$(ECHO)
+	@$(ECHO)  Required pkgs... $(REQUIRE_PACKAGES)
+	@$(ECHO)
+	@$(ECHO)  Basedir......... $(BASEDIR)
+	@$(ECHO)  FPCDir.......... $(FPCDIR)
+	@$(ECHO)  CrossBinDir..... $(CROSSBINDIR)
+	@$(ECHO)  UnitsDir........ $(UNITSDIR)
+	@$(ECHO)  PackagesDir..... $(PACKAGESDIR)
+	@$(ECHO)
+	@$(ECHO)  GCC library..... $(GCCLIBDIR)
+	@$(ECHO)  Other library... $(OTHERLIBDIR)
+	@$(ECHO)
+	@$(ECHO)  == Tools info ==
+	@$(ECHO)
+	@$(ECHO)  As........ $(AS)
+	@$(ECHO)  Ld........ $(LD)
+	@$(ECHO)  Ar........ $(AR)
+	@$(ECHO)  Rc........ $(RC)
+	@$(ECHO)
+	@$(ECHO)  Mv........ $(MVPROG)
+	@$(ECHO)  Cp........ $(CPPROG)
+	@$(ECHO)  Rm........ $(RMPROG)
+	@$(ECHO)  GInstall.. $(GINSTALL)
+	@$(ECHO)  Echo...... $(ECHO)
+	@$(ECHO)  Shell..... $(SHELL)
+	@$(ECHO)  Date...... $(DATE)
+	@$(ECHO)  FPCMake... $(FPCMAKE)
+	@$(ECHO)  PPUMove... $(PPUMOVE)
+	@$(ECHO)  Zip....... $(ZIPPROG)
+	@$(ECHO)
+	@$(ECHO)  == Object info ==
+	@$(ECHO)
+	@$(ECHO)  Target Loaders........ $(TARGET_LOADERS)
+	@$(ECHO)  Target Units.......... $(TARGET_UNITS)
+	@$(ECHO)  Target Implicit Units. $(TARGET_IMPLICITUNITS)
+	@$(ECHO)  Target Programs....... $(TARGET_PROGRAMS)
+	@$(ECHO)  Target Dirs........... $(TARGET_DIRS)
+	@$(ECHO)  Target Examples....... $(TARGET_EXAMPLES)
+	@$(ECHO)  Target ExampleDirs.... $(TARGET_EXAMPLEDIRS)
+	@$(ECHO)
+	@$(ECHO)  Clean Units......... $(CLEAN_UNITS)
+	@$(ECHO)  Clean Files......... $(CLEAN_FILES)
+	@$(ECHO)
+	@$(ECHO)  Install Units....... $(INSTALL_UNITS)
+	@$(ECHO)  Install Files....... $(INSTALL_FILES)
+	@$(ECHO)
+	@$(ECHO)  == Install info ==
+	@$(ECHO)
+	@$(ECHO)  DateStr.............. $(DATESTR)
+	@$(ECHO)  ZipName.............. $(ZIPNAME)
+	@$(ECHO)  ZipPrefix............ $(ZIPPREFIX)
+	@$(ECHO)  ZipCrossPrefix....... $(ZIPCROSSPREFIX)
+	@$(ECHO)  ZipSuffix............ $(ZIPSUFFIX)
+	@$(ECHO)  FullZipName.......... $(FULLZIPNAME)
+	@$(ECHO)  Install FPC Package.. $(INSTALL_FPCPACKAGE)
+	@$(ECHO)
+	@$(ECHO)  Install base dir..... $(INSTALL_BASEDIR)
+	@$(ECHO)  Install binary dir... $(INSTALL_BINDIR)
+	@$(ECHO)  Install library dir.. $(INSTALL_LIBDIR)
+	@$(ECHO)  Install units dir.... $(INSTALL_UNITDIR)
+	@$(ECHO)  Install source dir... $(INSTALL_SOURCEDIR)
+	@$(ECHO)  Install doc dir...... $(INSTALL_DOCDIR)
+	@$(ECHO)  Install example dir.. $(INSTALL_EXAMPLEDIR)
+	@$(ECHO)  Install data dir..... $(INSTALL_DATADIR)
+	@$(ECHO)
+	@$(ECHO)  Dist destination dir. $(DIST_DESTDIR)
+	@$(ECHO)  Dist zip name........ $(DIST_ZIPNAME)
+	@$(ECHO)
+.PHONY: fpc_info
+fpc_info: $(INFORULES)
+.PHONY: fpc_makefile fpc_makefiles fpc_makefile_sub1 fpc_makefile_sub2 \
+	fpc_makefile_dirs
+fpc_makefile:
+	$(FPCMAKE) -w -T$(OS_TARGET) Makefile.fpc
+fpc_makefile_sub1:
+ifdef TARGET_DIRS
+	$(FPCMAKE) -w -T$(OS_TARGET) $(addsuffix /Makefile.fpc,$(TARGET_DIRS))
+endif
+ifdef TARGET_EXAMPLEDIRS
+	$(FPCMAKE) -w -T$(OS_TARGET) $(addsuffix /Makefile.fpc,$(TARGET_EXAMPLEDIRS))
+endif
+fpc_makefile_sub2: $(addsuffix _makefile_dirs,$(TARGET_DIRS) $(TARGET_EXAMPLEDIRS))
+fpc_makefile_dirs: fpc_makefile_sub1 fpc_makefile_sub2
+fpc_makefiles: fpc_makefile fpc_makefile_dirs
+units:
+examples:
+shared:
+sourceinstall: fpc_sourceinstall
+exampleinstall: fpc_exampleinstall
+zipexampleinstall: fpc_zipexampleinstall
+info: fpc_info
+makefiles: fpc_makefiles
+.PHONY: units examples shared sourceinstall exampleinstall zipexampleinstall info makefiles
+ifneq ($(wildcard fpcmake.loc),)
+include fpcmake.loc
+endif
+override FPCOPT:=$(filter-out -FU%,$(FPCOPT))
+override FPCOPT:=$(filter-out -FE%,$(FPCOPT))
+override FPCOPT:=$(filter-out $(addprefix -Fu,$(COMPILER_UNITDIR)),$(FPCOPT))# Compose general fpmake-parameters
+ifdef FPMAKEOPT
+FPMAKE_OPT+=$(FPMAKEOPT)
+endif
+FPMAKE_OPT+=--localunitdir=../..
+FPMAKE_OPT+=--globalunitdir=..
+FPMAKE_OPT+=$(FPC_TARGETOPT)
+FPMAKE_OPT+=$(addprefix -o ,$(FPCOPT))
+FPMAKE_OPT+=--compiler=$(FPC)
+FPMAKE_OPT+=-bu
+.NOTPARALLEL:
+fpmake$(SRCEXEEXT): fpmake.pp
+	$(FPCFPMAKE) fpmake.pp $(FPMAKE_SKIP_CONFIG) $(addprefix -Fu,$(COMPILER_FPMAKE_UNITDIR)) $(FPCMAKEOPT) $(OPT)
+all:	fpmake$(SRCEXEEXT)
+	$(LOCALFPMAKE) compile $(FPMAKE_OPT)
+smart:	fpmake$(SRCEXEEXT)
+	$(LOCALFPMAKE) compile $(FPMAKE_OPT) -o -XX -o -CX
+release:	fpmake$(SRCEXEEXT)
+	$(LOCALFPMAKE) compile $(FPMAKE_OPT) -o -dRELEASE
+debug:	fpmake$(SRCEXEEXT)
+	$(LOCALFPMAKE) compile $(FPMAKE_OPT) -o -dDEBUG
+ifeq ($(FPMAKE_BIN_CLEAN),)
+clean:
+else
+clean:
+	$(FPMAKE_BIN_CLEAN) clean $(FPMAKE_OPT)
+endif
+ifeq ($(FPMAKE_BIN_CLEAN),)
+distclean:	$(addsuffix _distclean,$(TARGET_DIRS)) fpc_cleanall
+else
+distclean:
+ifdef inUnix
+	{ $(FPMAKE_BIN_CLEAN) distclean $(FPMAKE_OPT); if [ $$? != "0" ]; then { echo Something wrong with fpmake exectable. Remove the executable and call make recursively to recover.; $(DEL) $(FPMAKE_BIN_CLEAN); $(MAKE) fpc_cleanall; }; fi;  }
+else
+	$(FPMAKE_BIN_CLEAN) distclean $(FPMAKE_OPT)
+endif
+	-$(DEL) $(LOCALFPMAKE)
+endif
+cleanall: distclean
+install:	fpmake$(SRCEXEEXT)
+ifdef UNIXHier
+	$(LOCALFPMAKE) install $(FPMAKE_OPT) --prefix=$(INSTALL_PREFIX) --baseinstalldir=$(INSTALL_LIBDIR)/fpc/$(FPC_VERSION) --unitinstalldir=$(INSTALL_UNITDIR)
+else
+	$(LOCALFPMAKE) install $(FPMAKE_OPT) --prefix=$(INSTALL_BASEDIR) --baseinstalldir=$(INSTALL_BASEDIR) --unitinstalldir=$(INSTALL_UNITDIR)
+endif
+distinstall:	fpmake$(SRCEXEEXT)
+ifdef UNIXHier
+	$(LOCALFPMAKE) install $(FPMAKE_OPT) --prefix=$(INSTALL_PREFIX) --baseinstalldir=$(INSTALL_LIBDIR)/fpc/$(FPC_VERSION) --unitinstalldir=$(INSTALL_UNITDIR) -ie -fsp 0
+else
+	$(LOCALFPMAKE) install $(FPMAKE_OPT) --prefix=$(INSTALL_BASEDIR) --baseinstalldir=$(INSTALL_BASEDIR) --unitinstalldir=$(INSTALL_UNITDIR) -ie -fsp 0
+endif
+zipinstall:	fpmake$(SRCEXEEXT)
+	$(LOCALFPMAKE) zipinstall $(FPMAKE_OPT) --zipprefix=$(DIST_DESTDIR)/$(ZIPPREFIX)
+zipdistinstall:	fpmake$(SRCEXEEXT)
+	$(LOCALFPMAKE) zipinstall $(FPMAKE_OPT) --zipprefix=$(DIST_DESTDIR)/$(ZIPPREFIX) -ie -fsp 0
+zipsourceinstall:	fpmake$(SRCEXEEXT)
+ifdef UNIXHier
+	$(LOCALFPMAKE) archive $(FPMAKE_OPT) --zipprefix=$(DIST_DESTDIR)/$(ZIPPREFIX) --prefix=share/src/fpc-\$$\(PACKAGEVERSION\)/$(INSTALL_FPCSUBDIR)/\$$\(PACKAGEDIRECTORY\)
+else
+	$(LOCALFPMAKE) archive $(FPMAKE_OPT) --zipprefix=$(DIST_DESTDIR)/$(ZIPPREFIX) --prefix=source\\$(INSTALL_FPCSUBDIR)\\\$$\(PACKAGEDIRECTORY\)
+endif

+ 128 - 0
packages/fcl-pdf/Makefile.fpc

@@ -0,0 +1,128 @@
+#
+#   Makefile.fpc for running fpmake
+#
+
+[package]
+name=fcl-pdf
+version=3.1.1
+
+[require]
+packages=rtl fcl-base
+
+[install]
+fpcpackage=y
+
+[default]
+fpcdir=../..
+
+[prerules]
+FPMAKE_BIN_CLEAN=$(wildcard ./fpmake$(SRCEXEEXT))
+ifdef OS_TARGET
+FPC_TARGETOPT+=--os=$(OS_TARGET)
+endif
+ifdef CPU_TARGET
+FPC_TARGETOPT+=--cpu=$(CPU_TARGET)
+endif
+LOCALFPMAKE=./fpmake$(SRCEXEEXT)
+# Adding a dependency on fpmkunit is not possbile due to an infinite loop. So
+# the fpmkunit-searchpath is added here:
+PACKAGEDIR_FPMKUNIT:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /fpmkunit/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_FPMKUNIT),)
+ifneq ($(wildcard $(PACKAGEDIR_FPMKUNIT)/units_bs/$(SOURCESUFFIX)),)
+UNITDIR_FPMAKE_FPMKUNIT=$(PACKAGEDIR_FPMKUNIT)/units_bs/$(SOURCESUFFIX)
+else
+UNITDIR_FPMAKE_FPMKUNIT=$(PACKAGEDIR_FPMKUNIT)
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_FPMKUNIT)/$(FPCMADE):
+        $(MAKE) -C $(PACKAGEDIR_FPMKUNIT) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_FPMKUNIT)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_FPMKUNIT=
+UNITDIR_FPMKUNIT:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /fpmkunit/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_FPMKUNIT),)
+UNITDIR_FPMKUNIT:=$(firstword $(UNITDIR_FPMKUNIT))
+else
+UNITDIR_FPMKUNIT=
+endif
+endif
+ifdef UNITDIR_FPMAKE_FPMKUNIT
+override COMPILER_FPMAKE_UNITDIR+=$(UNITDIR_FPMAKE_FPMKUNIT)
+endif
+
+[rules]
+# Do not pass the Makefile's unit and binary target locations. Fpmake uses it's own.
+override FPCOPT:=$(filter-out -FU%,$(FPCOPT))
+override FPCOPT:=$(filter-out -FE%,$(FPCOPT))
+# Do not pass the package-unitdirectories. Fpmake adds those and this way they don't apear in the .fpm
+override FPCOPT:=$(filter-out $(addprefix -Fu,$(COMPILER_UNITDIR)),$(FPCOPT))# Compose general fpmake-parameters
+# Compose general fpmake-parameters
+ifdef FPMAKEOPT
+FPMAKE_OPT+=$(FPMAKEOPT)
+endif
+FPMAKE_OPT+=--localunitdir=../..
+FPMAKE_OPT+=--globalunitdir=..
+FPMAKE_OPT+=$(FPC_TARGETOPT)
+FPMAKE_OPT+=$(addprefix -o ,$(FPCOPT))
+FPMAKE_OPT+=--compiler=$(FPC)
+FPMAKE_OPT+=-bu
+.NOTPARALLEL:
+
+fpmake$(SRCEXEEXT): fpmake.pp
+	$(FPCFPMAKE) fpmake.pp $(FPMAKE_SKIP_CONFIG) $(addprefix -Fu,$(COMPILER_FPMAKE_UNITDIR)) $(FPCMAKEOPT) $(OPT)
+all:	fpmake$(SRCEXEEXT)
+	$(LOCALFPMAKE) compile $(FPMAKE_OPT)
+smart:	fpmake$(SRCEXEEXT)
+	$(LOCALFPMAKE) compile $(FPMAKE_OPT) -o -XX -o -CX
+release:	fpmake$(SRCEXEEXT)
+	$(LOCALFPMAKE) compile $(FPMAKE_OPT) -o -dRELEASE
+debug:	fpmake$(SRCEXEEXT)
+	$(LOCALFPMAKE) compile $(FPMAKE_OPT) -o -dDEBUG
+# If no fpmake exists and (dist)clean is called, do not try to build fpmake, it will
+# most often fail because the dependencies are cleared.
+# In case of a clean, simply do nothing
+ifeq ($(FPMAKE_BIN_CLEAN),)
+clean:
+else
+clean:
+	$(FPMAKE_BIN_CLEAN) clean $(FPMAKE_OPT)
+endif
+# In case of a distclean, perform an 'old'-style distclean. This to avoid problems
+# when the package is compiled using fpcmake prior to running this clean using fpmake
+ifeq ($(FPMAKE_BIN_CLEAN),)
+distclean:	$(addsuffix _distclean,$(TARGET_DIRS)) fpc_cleanall
+else
+distclean:
+ifdef inUnix
+        { $(FPMAKE_BIN_CLEAN) distclean $(FPMAKE_OPT); if [ $$? != "0" ]; then { echo Something wrong with fpmake exectable. Remove the executable and call make recursively to recover.; $(DEL) $(FPMAKE_BIN_CLEAN); $(MAKE) fpc_cleanall; }; fi;  }
+else
+        $(FPMAKE_BIN_CLEAN) distclean $(FPMAKE_OPT)
+endif
+	-$(DEL) $(LOCALFPMAKE)
+endif
+cleanall: distclean
+install:	fpmake$(SRCEXEEXT)
+ifdef UNIXHier
+	$(LOCALFPMAKE) install $(FPMAKE_OPT) --prefix=$(INSTALL_PREFIX) --baseinstalldir=$(INSTALL_LIBDIR)/fpc/$(FPC_VERSION) --unitinstalldir=$(INSTALL_UNITDIR)
+else
+	$(LOCALFPMAKE) install $(FPMAKE_OPT) --prefix=$(INSTALL_BASEDIR) --baseinstalldir=$(INSTALL_BASEDIR) --unitinstalldir=$(INSTALL_UNITDIR)
+endif
+# distinstall also installs the example-sources and omits the location of the source-
+# files from the fpunits.cfg files.
+distinstall:	fpmake$(SRCEXEEXT)
+ifdef UNIXHier
+	$(LOCALFPMAKE) install $(FPMAKE_OPT) --prefix=$(INSTALL_PREFIX) --baseinstalldir=$(INSTALL_LIBDIR)/fpc/$(FPC_VERSION) --unitinstalldir=$(INSTALL_UNITDIR) -ie -fsp 0
+else
+	$(LOCALFPMAKE) install $(FPMAKE_OPT) --prefix=$(INSTALL_BASEDIR) --baseinstalldir=$(INSTALL_BASEDIR) --unitinstalldir=$(INSTALL_UNITDIR) -ie -fsp 0
+endif
+zipinstall:	fpmake$(SRCEXEEXT)
+	$(LOCALFPMAKE) zipinstall $(FPMAKE_OPT) --zipprefix=$(DIST_DESTDIR)/$(ZIPPREFIX)
+zipdistinstall:	fpmake$(SRCEXEEXT)
+	$(LOCALFPMAKE) zipinstall $(FPMAKE_OPT) --zipprefix=$(DIST_DESTDIR)/$(ZIPPREFIX) -ie -fsp 0
+zipsourceinstall:	fpmake$(SRCEXEEXT)
+ifdef UNIXHier
+	$(LOCALFPMAKE) archive $(FPMAKE_OPT) --zipprefix=$(DIST_DESTDIR)/$(ZIPPREFIX) --prefix=share/src/fpc-\$$\(PACKAGEVERSION\)/$(INSTALL_FPCSUBDIR)/\$$\(PACKAGEDIRECTORY\)
+else
+	$(LOCALFPMAKE) archive $(FPMAKE_OPT) --zipprefix=$(DIST_DESTDIR)/$(ZIPPREFIX) --prefix=source\\$(INSTALL_FPCSUBDIR)\\\$$\(PACKAGEDIRECTORY\)
+endif

BIN
packages/fcl-pdf/examples/poppy.jpg


+ 72 - 0
packages/fcl-pdf/examples/testfppdf.lpi

@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="9"/>
+    <General>
+      <Flags>
+        <SaveOnlyProjectUnits Value="True"/>
+        <MainUnitHasCreateFormStatements Value="False"/>
+        <MainUnitHasTitleStatement Value="False"/>
+        <SaveJumpHistory Value="False"/>
+        <SaveFoldState Value="False"/>
+      </Flags>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <Title Value="testfppdf"/>
+      <UseAppBundle Value="False"/>
+      <ResourceType Value="res"/>
+    </General>
+    <i18n>
+      <EnableI18N LFM="False"/>
+    </i18n>
+    <VersionInfo>
+      <StringTable ProductVersion=""/>
+    </VersionInfo>
+    <BuildModes Count="1">
+      <Item1 Name="Default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+    </PublishOptions>
+    <RunParams>
+      <local>
+        <FormatVersion Value="1"/>
+      </local>
+    </RunParams>
+    <Units Count="1">
+      <Unit0>
+        <Filename Value="testfppdf.lpr"/>
+        <IsPartOfProject Value="True"/>
+      </Unit0>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <Target>
+      <Filename Value="testfppdf"/>
+    </Target>
+    <SearchPaths>
+      <IncludeFiles Value="$(ProjOutDir)"/>
+      <OtherUnitFiles Value="../src"/>
+      <UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
+    </SearchPaths>
+    <Linking>
+      <Debugging>
+        <UseHeaptrc Value="True"/>
+      </Debugging>
+    </Linking>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="EAbort"/>
+      </Item1>
+      <Item2>
+        <Name Value="ECodetoolError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EFOpenError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 455 - 0
packages/fcl-pdf/examples/testfppdf.lpr

@@ -0,0 +1,455 @@
+{ This program generatesa multi-page PDF document and tests various
+  functionality on each of the 5 pages. }
+{$mode objfpc}
+{$H+}
+program testfppdf;
+
+uses
+  classes, sysutils, fpimage, fpreadjpeg, freetype, fppdf;
+
+Function SetUpDocument : TPDFDocument;
+Var
+  P : TPDFPage;
+  S : TPDFSection;
+  i: integer;
+begin
+  Result:=TPDFDocument.Create(Nil);
+  Result.Infos.Title := 'Test Document';
+  Result.Infos.Author := ApplicationName;
+  Result.Infos.Producer:='fpGUI Toolkit 0.8';
+  Result.Infos.ApplicationName:='pdf_demo';
+  Result.Infos.CreationDate:=Now;
+  Result.StartDocument;
+  S:=Result.Sections.AddSection; // we always need at least one section
+  for i := 1 to 5 do
+  begin
+    P:=Result.Pages.AddPage;
+    P.PaperType := ptA4;
+    P.UnitOfMeasure := uomMillimeters;
+    S.AddPage(P);
+  end;
+end;
+
+Procedure SaveDocument(D : TPDFDocument);
+Var
+  F : TFileStream;
+begin
+  F:=TFileStream.Create('test.pdf',fmCreate);
+  try
+    D.SaveToStream(F);
+    Writeln('Document used ',D.ObjectCount,' PDF objects/commands');
+  finally
+    F.Free;
+  end;
+end;
+
+Procedure EmptyPage;
+Var
+  D : TPDFDocument;
+begin
+  D:=SetupDocument;
+  try
+    SaveDocument(D);
+  finally
+    D.Free;
+  end;
+end;
+
+
+{ all units of measure are in millimeters }
+Procedure SimpleText(D: TPDFDocument; APage: integer);
+Var
+  P : TPDFPage;
+  FtTitle, FtText1, FtText2: integer;
+  lPt1: TPDFCoord;
+begin
+  P:=D.Pages[APage];
+  // create the fonts to be used (use one of the 14 Adobe PDF standard fonts)
+  FtTitle := D.AddFont('helvetica-12', clRed);
+  FtText1 := D.AddFont('FreeSans.ttf', 'FreeSans-12', clGreen); // TODO: this color value means nothing - not used at all
+  FtText2 := D.AddFont('times-8', clGreen);
+
+  { Page title }
+  P.SetFont(FtTitle,23);
+  P.SetColor(clBlack, false);
+  lPt1 := P.Matrix.Transform(25, 20);
+  P.WriteText(lPt1.X, lPt1.Y, 'Sample Text');
+
+  // Write text using FreeSans font
+  P.SetFont(ftText1,12);
+  P.SetColor(clBlack, false);
+  P.WriteText(25, P.GetPaperHeight-70, '(25mm,70mm) FreeSans: 0oO 1lL - wêreld çèûÎÐð£¢ß');
+  lPt1 := P.Matrix.Transform(25, 76);
+  P.WriteText(lPt1.X, lPt1.Y, '(25mm,76mm) - FreeSans font');
+
+  P.WriteUTF8Text(25, P.GetPaperHeight-200, 'Hello Graeme *'#$E2#$95#$AC'*'#$C3#$A4); // 0xE2 0x95 0xAC is UTF-8 for ╬   and   0xC3 0xA4 is UTF-8 for ä
+  lPt1 := P.Matrix.Transform(25, 210);
+  P.WriteUTF8Text(lPt1.X, lPt1.Y, 'В субботу двадцать третьего мая приезжает твоя любимая теща.');
+
+  // Write text using Helvetica font
+  P.SetFont(ftText2,12);
+  P.SetColor(clBlue, false);
+  lPt1 := P.Matrix.Transform(25, 50);
+  P.WriteText(lPt1.X, lPt1.Y, '(25mm,50mm) - Times: 0oO 1lL - wêreld çèûÎÐð£¢ß');
+  P.SetFont(ftText2,16);
+  P.SetColor($c00000, false);
+  lPt1 := P.Matrix.Transform(75, 100);
+  P.WriteText(lPt1.X, lPt1.Y, '(75mm,100mm) - Big text at absolute position');
+end;
+
+Procedure SimpleLinesRaw(D: TPDFDocument; APage: integer);
+var
+  P: TPDFPage;
+  FtTitle: integer;
+  lPt1, lPt2: TPDFCoord;
+begin
+  P:=D.Pages[APage];
+  // create the fonts to be used (use one of the 14 Adobe PDF standard fonts)
+  FtTitle := D.AddFont('helvetica-12', clBlack);
+
+  { Page title }
+  P.SetFont(FtTitle,23);
+  P.SetColor(clBlack, false);
+  lPt1 := P.Matrix.Transform(25, 20);
+  P.WriteText(lPt1.X, lPt1.Y, 'Sample Line Drawing (DrawLine)');
+
+  P.SetColor(clBlack,False); // clblue
+  P.SetPenStyle(ppsSolid);
+  lPt1 := P.Matrix.Transform(30, 100);
+  lPt2 := P.Matrix.Transform(150, 150);
+  P.DrawLine(lPt1, lPt2, 0.2);
+  P.SetColor($0000FF,False); // clblue
+  P.SetPenStyle(ppsDash);
+  lPt1 := P.Matrix.Transform(50, 70);
+  lPt2 := P.Matrix.Transform(180, 100);
+  P.DrawLine(lPt1, lPt2, 0.1);
+  P.SetColor($FF0000,False); // clRed
+  P.SetPenStyle(ppsDashDot);
+  lPt1 := P.Matrix.Transform(40, 140);
+  lPt2 := P.Matrix.Transform(160, 80);
+  P.DrawLine(lPt1, lPt2, 1);
+  P.SetColor(clBlack,False); // clBlack
+  P.SetPenStyle(ppsDashDotDot);
+  lPt1 := P.Matrix.Transform(60, 50);
+  lPt2 := P.Matrix.Transform(60, 120);
+  P.DrawLine(lPt1, lPt2, 1.5);
+  P.SetColor(clBlack,False); // clBlack
+  P.SetPenStyle(ppsDot);
+  lPt1 := P.Matrix.Transform(10, 80);
+  lPt2 := P.Matrix.Transform(130, 130);
+  P.DrawLine(lPt1, lPt2, 0.5);
+end;
+
+Procedure SimpleLines(D: TPDFDocument; APage: integer);
+var
+  P: TPDFPage;
+  FtTitle: integer;
+  TsThinBlack, TsThinBlue, TsThick, TsThinRed, TsThinBlackDot: Integer;
+  lPt1, lPt2: TPDFCoord;
+begin
+  P:=D.Pages[APage];
+  // create the fonts to be used (use one of the 14 Adobe PDF standard fonts)
+  FtTitle := D.AddFont('helvetica-12', clRed);
+
+  { Page title }
+  P.SetFont(FtTitle,23);
+  P.SetColor(clBlack, false);
+  lPt1 := P.Matrix.Transform(25, 20);
+  P.WriteText(lPt1.X, lPt1.Y, 'Sample Line Drawing (DrawLineStyle)');
+
+  // write the text at position 100 mm from left and 120 mm from top
+  TsThinBlack := D.AddLineStyleDef(0.2, clBlack, ppsSolid);
+  TsThinBlue := D.AddLineStyleDef(0.1, clBlue, ppsDash);
+  TsThinRed := D.AddLineStyleDef(1, clRed, ppsDashDot);
+  TsThick := D.AddLineStyleDef(1.5, clBlack, ppsDashDotDot);
+  TsThinBlackDot := D.AddLineStyleDef(0.5, clBlack, ppsDot);
+
+  lPt1 := P.Matrix.Transform(30, 100);
+  lPt2 := P.Matrix.Transform(150, 150);
+  P.DrawLineStyle(lPt1, lPt2, tsThinBlack);
+
+  lPt1 := P.Matrix.Transform(50, 70);
+  lPt2 := P.Matrix.Transform(180, 100);
+  P.DrawLineStyle(lPt1, lPt2, tsThinBlue);
+
+  lPt1 := P.Matrix.Transform(40, 140);
+  lPt2 := P.Matrix.Transform(160, 80);
+  P.DrawLineStyle(lPt1, lPt2, tsThinRed);
+
+  lPt1 := P.Matrix.Transform(60, 50);
+  lPt2 := P.Matrix.Transform(60, 120);
+  P.DrawLineStyle(lPt1, lPt2, tsThick);
+
+  lPt1 := P.Matrix.Transform(10, 80);
+  lPt2 := P.Matrix.Transform(130, 130);
+  P.DrawLineStyle(lPt1.X, lPt1.Y, lPt2.X, lPt2.Y, tsThinBlackDot);  { just to test the other overloaded version too. }
+end;
+
+Procedure SimpleImage(D: TPDFDocument; APage: integer);
+Var
+  P: TPDFPage;
+  FtTitle: integer;
+  IDX: Integer;
+  W, H: Integer;
+  lPt1: TPDFCoord;
+begin
+  P := D.Pages[APage];
+  // create the fonts to be used (use one of the 14 Adobe PDF standard fonts)
+  FtTitle := D.AddFont('helvetica-12', clBlack);
+
+  { Page title }
+  P.SetFont(FtTitle,23);
+  P.SetColor(clBlack, false);
+  lPt1 := P.Matrix.Transform(25, 20);
+  P.WriteText(lPt1.X, lPt1.Y, 'Sample Image Support');
+
+  P.SetFont(FtTitle,10);
+  P.SetColor(clBlack, false);
+
+  IDX := D.Images.AddFromFile('poppy.jpg',False);
+  W := D.Images[IDX].Width;
+  H := D.Images[IDX].Height;
+  { scalled down image (small) }
+  lPt1 := P.Matrix.Transform(25, 100); // left-bottom coordinate of image
+  P.DrawImage(lPt1.X, lPt1.Y, W div 2, H div 2, IDX);
+  lPt1 := P.Matrix.Transform(90, 75);
+  P.WriteText(lPt1.X, lPt1.Y, '[Scaled image]');
+
+
+  { large image }
+  lPt1 := P.Matrix.Transform(35, 190);  // left-bottom coordinate of image
+  P.DrawImage(lPt1.X, lPt1.Y, W, H, IDX);
+  lPt1 := P.Matrix.Transform(160, 150);
+  P.WriteText(lPt1.X, lPt1.Y, '[Default size]');
+end;
+
+Procedure SimpleShapes(D: TPDFDocument; APage: integer);
+Var
+  P : TPDFPage;
+  FtTitle: integer;
+//  FtText: integer;
+  lPt1, lPt2, lPt3: TPDFCoord;
+begin
+  P:=D.Pages[APage];
+  // create the fonts to be used (use one of the 14 Adobe PDF standard fonts)
+  FtTitle := D.AddFont('helvetica-12', clBlack);
+
+  { Page title }
+  P.SetFont(FtTitle,23);
+  P.SetColor(clBlack);
+  lPt1 := P.Matrix.Transform(25, 20);
+  P.WriteText(lPt1.X, lPt1.Y, 'Basic Shapes');
+
+  // ========== Rectangles ============
+
+  { Transform the origin point to the Cartesian coordinate system. }
+  lPt1.X := 30;
+  { PDF origin coordinate is Bottom-Left, and we want to use Image coordinate of Top-Left }
+  lPt1.Y := 60+20; // origin + height
+  lPt2 := P.Matrix.Transform(lPt1);
+  P.SetColor(clRed, true);
+  P.SetColor($37b344, false); // some green color
+  P.DrawRect(lPt2.X, lPt2.Y, 40, 20, 3, true, true);
+
+  { Transform the origin point to the Cartesian coordinate system. }
+  lPt1.X := 20;
+  { we need the Top-Left coordinate }
+  lPt1.Y := 50+20; // origin + height
+  lPt2 := P.Matrix.Transform(lPt1);
+  P.SetColor(clBlue, true);
+  P.SetColor($b737b3, false); // some purple color
+  P.DrawRect(lPt2.X, lPt2.Y, 40, 20, 1, true, true);
+
+  { Transform the origin point to the Cartesian coordinate system. }
+  lPt1.X := 110;
+  { PDF origin coordinate is Bottom-Left, and we want to use Image cooridanet of Top-Left }
+  lPt1.Y := 70+20; // origin + height
+  lPt2 := P.Matrix.Transform(lPt1);
+  P.SetPenStyle(ppsDashDot);
+  P.SetColor(clBlue, true);
+  P.DrawRect(lPt2.X, lPt2.Y, 40, 20, 1, false, true);
+
+  { Transform the origin point to the Cartesian coordinate system. }
+  lPt1.X := 100;
+  { PDF origin coordinate is Bottom-Left, and we want to use Image cooridanet of Top-Left }
+  lPt1.Y := 60+20; // origin + height
+  lPt2 := P.Matrix.Transform(lPt1);
+  P.SetPenStyle(ppsDash);
+  P.SetColor($37b344, true);  // some green color
+  P.DrawRect(lPt2.X, lPt2.Y, 40, 20, 2, false, true);
+
+  { Transform the origin point to the Cartesian coordinate system. }
+  lPt1.X := 90;
+  { we need the Top-Left coordinate }
+  lPt1.Y := 50+20; // origin + height
+  lPt2 := P.Matrix.Transform(lPt1);
+  P.SetPenStyle(ppsSolid);
+  P.SetColor($b737b3, true);  // some purple color
+  P.DrawRect(lPt2.X, lPt2.Y, 40, 20, 4, false, true);
+
+
+  // ========== Ellipses ============
+
+  { Transform the origin point to the Cartesian coordinate system. }
+  lPt2 := P.Matrix.Transform(60, 150);
+  P.SetPenStyle(ppsSolid);
+  P.SetColor($c00000, True);
+  P.DrawEllipse(lPt2.X, lPt2.Y, -40, 20, 3, False, True);
+
+  P.SetColor(clBlue, true);
+  P.SetColor($b737b3, false); // some purple color
+  P.DrawEllipse(lPt2, 10, 10, 1, True, True);
+(*
+  P.DrawRect(mmToPDF(lPt2.X), mmToPDF(lPt2.Y), 2, 2, 1, False, True);
+  FtText := D.AddFont('helvetica-8', clBlack);
+  P.SetFont(ftText,8);
+  P.SetColor(clblack);
+  P.WriteText(mmtoPDF(100), GetPaperHeight-mmToPDF(105),'^---(origin point)');
+*)
+
+  { Transform the origin point to the Cartesian coordinate system. }
+  lPt2 := P.Matrix.Transform(140, 150);
+  P.SetPenStyle(ppsDashDot);
+  P.SetColor($b737b3, True);
+  P.DrawEllipse(lPt2, 35, 20, 1, False, True);
+
+
+  // ========== Lines Pen Styles ============
+
+  { Transform the origin point to the Cartesian coordinate system. }
+  lPt1.X := 30;
+  lPt1.Y := 200;
+  lPt2 := P.Matrix.Transform(lPt1);
+  lPt1.X := 70;
+  lPt1.Y := 200;
+  lPt3 := P.Matrix.Transform(lPt1);
+  P.SetPenStyle(ppsSolid);
+  P.SetColor(clBlack, True);
+  P.DrawLine(lPt2.X, lPt2.Y, lPt3.X, lPt3.Y, 1);
+
+  lPt1.X := 30;
+  lPt1.Y := 210;
+  lPt2 := P.Matrix.Transform(lPt1);
+  lPt1.X := 70;
+  lPt3 := P.Matrix.Transform(lPt1);
+  P.SetPenStyle(ppsDash);
+  P.SetColor(clBlack, True);
+  P.DrawLine(lPt2.X, lPt2.Y, lPt3.X, lPt3.Y, 1);
+
+  lPt1.X := 30;
+  lPt1.Y := 220;
+  lPt2 := P.Matrix.Transform(lPt1);
+  lPt1.X := 70;
+  lPt3 := P.Matrix.Transform(lPt1);
+  P.SetPenStyle(ppsDot);
+  P.SetColor(clBlack, True);
+  P.DrawLine(lPt2.X, lPt2.Y, lPt3.X, lPt3.Y, 1);
+
+  lPt1.X := 30;
+  lPt1.Y := 230;
+  lPt2 := P.Matrix.Transform(lPt1);
+  lPt1.X := 70;
+  lPt3 := P.Matrix.Transform(lPt1);
+  P.SetPenStyle(ppsDashDot);
+  P.SetColor(clBlack, True);
+  P.DrawLine(lPt2.X, lPt2.Y, lPt3.X, lPt3.Y, 1);
+
+  lPt1.X := 30;
+  lPt1.Y := 240;
+  lPt2 := P.Matrix.Transform(lPt1);
+  lPt1.X := 70;
+  lPt3 := P.Matrix.Transform(lPt1);
+  P.SetPenStyle(ppsDashDotDot);
+  P.SetColor(clBlack, True);
+  P.DrawLine(lPt2.X, lPt2.Y, lPt3.X, lPt3.Y, 1);
+
+
+  // ========== Line Attribute ============
+
+
+  { Transform the origin point to the Cartesian coordinate system. }
+  lPt1.X := 100;
+  lPt1.Y := 170;
+  lPt2 := P.Matrix.Transform(lPt1);
+  lPt1.X := 140;
+  lPt3 := P.Matrix.Transform(lPt1);
+  P.SetPenStyle(ppsSolid);
+  P.SetColor(clBlack, True);
+  P.DrawLine(lPt2.X, lPt2.Y, lPt3.X, lPt3.Y, 0.2);
+
+  { Transform the origin point to the Cartesian coordinate system. }
+  lPt1.X := 100;
+  lPt1.Y := 180;
+  lPt2 := P.Matrix.Transform(lPt1);
+  lPt1.X := 140;
+  lPt3 := P.Matrix.Transform(lPt1);
+  P.DrawLine(lPt2.X, lPt2.Y, lPt3.X, lPt3.Y, 0.3);
+
+  { Transform the origin point to the Cartesian coordinate system. }
+  lPt1.X := 100;
+  lPt1.Y := 190;
+  lPt2 := P.Matrix.Transform(lPt1);
+  lPt1.X := 140;
+  lPt3 := P.Matrix.Transform(lPt1);
+  P.DrawLine(lPt2.X, lPt2.Y, lPt3.X, lPt3.Y, 0.5);
+
+  { Transform the origin point to the Cartesian coordinate system. }
+  lPt1.X := 100;
+  lPt1.Y := 200;
+  lPt2 := P.Matrix.Transform(lPt1);
+  lPt1.X := 140;
+  lPt3 := P.Matrix.Transform(lPt1);
+  P.DrawLine(lPt2.X, lPt2.Y, lPt3.X, lPt3.Y, 1);
+
+  lPt1.X := 100;
+  lPt1.Y := 210;
+  lPt2 := P.Matrix.Transform(lPt1);
+  lPt1.X := 140;
+  lPt3 := P.Matrix.Transform(lPt1);
+  P.SetColor(clRed, True);
+  P.DrawLine(lPt2.X, lPt2.Y, lPt3.X, lPt3.Y, 2);
+
+  lPt1.X := 100;
+  lPt1.Y := 220;
+  lPt2 := P.Matrix.Transform(lPt1);
+  lPt1.X := 140;
+  lPt3 := P.Matrix.Transform(lPt1);
+  P.SetColor($37b344, True);
+  P.DrawLine(lPt2.X, lPt2.Y, lPt3.X, lPt3.Y, 3);
+
+  lPt1.X := 100;
+  lPt1.Y := 230;
+  lPt2 := P.Matrix.Transform(lPt1);
+  lPt1.X := 140;
+  lPt3 := P.Matrix.Transform(lPt1);
+  P.SetColor(clBlue, True);
+  P.DrawLine(lPt2.X, lPt2.Y, lPt3.X, lPt3.Y, 4);
+
+  lPt1.X := 100;
+  lPt1.Y := 240;
+  lPt2 := P.Matrix.Transform(lPt1);
+  lPt1.X := 140;
+  lPt3 := P.Matrix.Transform(lPt1);
+  P.SetColor($b737b3, True);
+  P.DrawLine(lPt2.X, lPt2.Y, lPt3.X, lPt3.Y, 5);
+end;
+
+Var
+  D: TPDFDocument;
+begin
+  D := SetupDocument;
+  try
+    D.FontDirectory := ExtractFIlePath(Paramstr(0))+'fonts'+PathDelim;
+
+    SimpleText(D, 0);
+    SimpleShapes(D, 1);
+    SimpleLines(D, 2);
+    SimpleLinesRaw(D, 3);
+    SimpleImage(D, 4);
+
+    SaveDocument(D);
+  finally
+    D.Free;
+  end;
+end.
+

+ 48 - 0
packages/fcl-pdf/fpmake.pp

@@ -0,0 +1,48 @@
+{$ifndef ALLPACKAGES}
+{$mode objfpc}{$H+}
+program fpmake;
+
+uses fpmkunit;
+
+Var
+  P : TPackage;
+  T : TTarget;
+begin
+  With Installer do
+    begin
+{$endif ALLPACKAGES}
+    P:=AddPackage('fcl-pdf');
+
+{$ifdef ALLPACKAGES}
+    P.Directory:=ADirectory;
+{$endif ALLPACKAGES}
+
+    P.Author := 'Michael Van Canneyt & Graeme Geldenhuys';
+    P.License := 'LGPL with modification, ';
+    P.HomepageURL := 'www.freepascal.org';
+    P.Email := '';
+    P.Description := 'PDF generating and TTF file info library';
+    P.NeedLibC:= false;
+    P.OSes:=P.OSes-[embedded,win16];
+    P.Dependencies.Add('rtl-objpas');
+    P.Dependencies.Add('fcl-base');
+    P.Dependencies.Add('fcl-image');
+    P.Dependencies.Add('paszlib');
+    P.Version:='3.1.1';
+    T:=P.Targets.AddUnit('src/fpttfencodings.pp');
+    T:=P.Targets.AddUnit('src/fpparsettf.pp');
+    With T do
+      Dependencies.AddUnit('fpttfencodings');
+    T:=P.Targets.AddUnit('src/fpttf.pp');
+    T:=P.Targets.AddUnit('src/fppdf.pp');
+    With T do
+      begin
+      Dependencies.AddUnit('fpparsettf');
+      end;
+    
+    // md5.ref
+{$ifndef ALLPACKAGES}
+    Run;
+    end;
+end.
+{$endif ALLPACKAGES}

+ 29 - 0
packages/fcl-pdf/readme.txt

@@ -0,0 +1,29 @@
+The fcl-pdf package contains a PDF generating unit fppdf that does not depend
+on any external libraries.
+
+The PDF generator has the following features:
+- Support for basic shapes.
+- Support for basic line styles.
+- Dictionary support.
+- Multi-page PDF.
+- Image support.
+- TTF Font support.
+- Font embedding.
+- Unicode font support.
+- Stream Compression.
+- Image embedding.
+- Several paper types.
+- Portrait/Landscape.
+- Support for multiple units.
+- Rotation matrix system.
+- PDF creator information.
+
+Todo:
+- Implement TFPCustomCanvas descendent (TPDFCanvas) that draws on a PDF.
+- Partial embedding of (unicode) fonts for smaller PDFs.
+- On windows, allow to use native font mechanisms for extracting info from TTF files.
+
+Optionally:
+- PDF Forms.
+- Archive format.
+- Signature.

+ 1257 - 0
packages/fcl-pdf/src/fpparsettf.pp

@@ -0,0 +1,1257 @@
+{
+    This file is part of the Free Component Library (FCL)
+    Copyright (c) 2014 by Michael Van Canneyt
+
+    This unit reads and extracts info from a TTF font file.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+unit fpparsettf;
+
+{$mode objfpc}
+{$h+}
+{ $R+}
+
+{.$define gdebug}
+
+interface
+
+uses
+  Classes, SysUtils, fpttfencodings;
+
+type
+  ETTF = Class(Exception);
+
+  // Tables recognized in this unit.
+  TTTFTableType = (ttUnknown,ttHead,tthhea,ttmaxp,tthmtx,ttcmap,ttname,ttOS2,ttpost);
+
+  TPDFFontDefinition = Record
+    FontType : String;
+    FontName : String;
+    Ascender : Integer;
+    Descender : Integer;
+    CapHeight : Integer;
+    Flags : Integer;
+    BBox : Array[0..3] of Integer;
+    ItalicAngle : Integer;
+    StemV : Integer;
+    MissingWidth : integer;
+    FontUp : Integer;
+    FontUt : Integer;
+    Encoding : String;
+    FontFile : String;
+    Diffs : String;
+    CharWidths : String;
+    OriginalSize : integer;
+  end;
+
+  TSmallintArray = Packed Array of Smallint;
+  TWordArray = Packed Array of Smallint;
+
+  TFixedVersionRec = packed record
+    case Integer of
+      0:  (Minor, Major: Word);
+      1:  (Version: Cardinal);
+  end;
+
+  TTableDirectory = Packed Record
+    FontVersion : TFixedVersionRec;
+    Numtables : Word;
+    SearchRange : Word;
+    EntrySelector : Word;
+    RangeShift : Word;
+  end;
+
+  TTableDirectoryEntry = Packed Record
+    Tag: Array[1..4] of char;
+    checkSum : Cardinal;
+    offset : Cardinal;
+    Length : Cardinal;
+  end;
+  TTableDirectoryEntries = Array of TTableDirectoryEntry;
+
+  TLongHorMetric = Packed record
+    AdvanceWidth : Word;
+    LSB: Smallint;              { leftSideBearing }
+  end;
+  TLongHorMetrics = Packed Array of TLongHorMetric;
+
+Type
+  TPostScript = Packed Record
+    Format : TFixedVersionRec;
+    ItalicAngle : LongWord;
+    UnderlinePosition : SmallInt;
+    underlineThickness : SmallInt;
+    isFixedPitch : Cardinal;
+    minMemType42 : Cardinal;
+    maxMemType42 : Cardinal;
+    minMemType1 : Cardinal;
+    maxMemType1 : Cardinal;
+  end;
+
+  TMaxP = Packed Record
+    VersionNumber : TFixedVersionRec;
+    numGlyphs : Word;
+    maxPoints : Word;
+    maxContours : Word;
+    maxCompositePoints : word;
+    maxCompositeContours : word;
+    maxZones : Word;
+    maxTwilightPoints : word;
+    maxStorage : Word;
+    maxFunctionDefs : Word;
+    maxInstructionDefs : Word;
+    maxStackElements : Word;
+    maxSizeOfInstructions : word;
+    maxComponentElements : Word;
+    maxComponentDepth : Word;
+  end;
+
+  TOS2Data = Packed Record
+    version : Word;
+    xAvgCharWidth : SmallInt;
+    usWeightClass : Word;
+    usWidthClass : Word;
+    fsType : SmallInt;
+    ySubscriptXSize : SmallInt;
+    ySubscriptYSize : SmallInt;
+    ySubscriptXOffset : SmallInt;
+    ySubscriptYOffset : Smallint;
+    ySuperscriptXSize : Smallint;
+    ySuperscriptYSize : Smallint;
+    ySuperscriptXOffset : Smallint;
+    ySuperscriptYOffset : Smallint;
+    yStrikeoutSize : SmallInt;
+    yStrikeoutPosition : Smallint;
+    sFamilyClass : SmallInt;    // we could split this into a record of Class & SubClass values.
+    panose : Array[0..9] of byte;
+    ulUnicodeRange1 : Cardinal;
+    ulUnicodeRange2 : Cardinal;
+    ulUnicodeRange3 : Cardinal;
+    ulUnicodeRange4 : Cardinal;
+    achVendID : Array[0..3] of char;
+    fsSelection : word;
+    usFirstCharIndex : Word;
+    usLastCharIndex : Word;
+    sTypoAscender: Smallint;
+    sTypoDescender : Smallint;
+    sTypoLineGap : Smallint;
+    usWinAscent : Word;
+    usWinDescent : Word;
+    ulCodePageRange1 : Cardinal;
+    ulCodePageRange2 : Cardinal;
+    sxHeight : smallint;
+    sCapHeight : smallint;
+    usDefaultChar : word;
+    usBreakChar : word;
+    usMaxContext  : word;
+  end;
+
+  { Nicely described at [https://www.microsoft.com/typography/otspec/head.htm] }
+  THead = Packed record
+    FileVersion : TFixedVersionRec;
+    FontRevision : TFixedVersionRec;
+    CheckSumAdjustment : Cardinal;
+    MagicNumber : Cardinal;
+    Flags : Word;
+    UnitsPerEm: word;
+    Created : Int64;
+    Modified : Int64;
+    BBox: Packed array[0..3] of Smallint;
+    MacStyle : word;
+    LowestRecPPEM : word;
+    FontDirectionHint : smallint;
+    IndexToLocFormat : Smallint;
+    glyphDataFormat : Smallint;
+  end;
+
+  { structure described at [https://www.microsoft.com/typography/otspec/hhea.htm] }
+  THHead = packed record
+    TableVersion : TFixedVersionRec;
+    Ascender : Smallint;
+    Descender : Smallint;
+    LineGap : Smallint;
+    AdvanceWidthMax : Word;
+    MinLeftSideBearing : Smallint;
+    MinRightSideBearing : Smallint;
+    XMaxExtent : Smallint;
+    CaretSlopeRise : Smallint;
+    CaretSlopeRun : Smallint;
+    Reserved : Array[0..4] of Smallint;
+    metricDataFormat : Smallint;
+    numberOfHMetrics : Word;
+  end;
+
+  { Character to glyph mapping
+    Structure described at [https://www.microsoft.com/typography/otspec/cmap.htm] }
+  TCmapHeader = packed record
+    Version: word;
+    SubTableCount: word;
+  end;
+
+  TCmapSubTableEntry = packed record
+    PlatformID: word;
+    EncodingID: word;
+    Offset: Cardinal;
+  end;
+  TCmapSubTables = Array of TCmapSubTableEntry;
+
+  TCmapFmt4 = packed record
+    Format: word;
+    Length: word;
+    LanguageID: word;
+    SegmentCount2: word;
+    SearchRange: word;
+    EntrySelector: word;
+    RangeShift: word;
+  end;
+
+  TUnicodeMapSegment = Packed Record
+    StartCode : Word;
+    EndCode : Word;
+    IDDelta : Smallint;
+    IDRangeOffset : Word;
+  end;
+  TUnicodeMapSegmentArray = Array of TUnicodeMapSegment;
+
+  TNameRecord = Packed Record
+    PlatformID : Word;
+    EncodingID : Word;
+    LanguageID : Word;
+    NameID : Word;
+    StringLength : Word;
+    StringOffset : Word;
+  end;
+
+  TNameEntry = Packed Record
+    Info: TNameRecord;
+    Value : String;
+  end;
+  TNameEntries = Array of TNameEntry;
+
+
+  TTFFileInfo = class(TObject)
+  private
+    FFilename: string;
+    FTableDir : TTableDirectory;
+    FTables : TTableDirectoryEntries;
+    FMaxp : TMaxP;
+    FCmapH : TCMapHeader;
+    FSubtables : TCmapSubTables;
+    FUnicodeMap : TCmapFmt4;
+    FUnicodeMapSegments : TUnicodeMapSegmentArray;
+    FHead : THead;
+    FHHEad : THHead;
+    FOS2Data : TOS2Data;
+    FPostScript : TPostScript;
+    FWidths: TLongHorMetrics; // hmtx data
+    // Needed to create PDF font def.
+    FOriginalSize : Cardinal;
+    MissingWidth: Integer;
+    FNameEntries: TNameEntries;
+    { This only applies to TFixedVersionRec values. }
+    function FixMinorVersion(const AMinor: word): word;
+  Protected
+    // Stream reading functions.
+    Function IsNativeData : Boolean; virtual;
+    function ReadShort(AStream: TStream): Smallint; inline;
+    function ReadULong(AStream: TStream): Longword; inline;
+    function ReadUShort(AStream: TStream): Word; inline;
+    // Parse the various well-known tables
+    procedure ParseHead(AStream : TStream); virtual;
+    procedure ParseHhea(AStream : TStream); virtual;
+    procedure ParseMaxp(AStream : TStream); virtual;
+    procedure ParseHmtx(AStream : TStream); virtual;
+    procedure ParseCmap(AStream : TStream); virtual;
+    procedure ParseName(AStream : TStream); virtual;
+    procedure ParseOS2(AStream : TStream); virtual;
+    procedure ParsePost(AStream : TStream); virtual;
+    // Make differences for postscript fonts
+    procedure PrepareEncoding(Const AEnCoding : String);
+    function MakeDifferences: String; virtual;
+    // Utility function to convert FShort to natural units
+    Function ToNatural(AUnit: Smallint) : Smallint;
+    // Some utility functions to create the PDF font definition
+    Procedure MakePDFFontDefinitionFile(Const FontFile,Section,AEncoding: string); virtual;
+    Function Flags : Integer;
+    Function Bold: Boolean;
+    Function StemV: SmallInt;
+    Function Embeddable : Boolean;
+    Function Ascender: SmallInt;
+    Function Descender: SmallInt;
+    { Also know as the linegap. "Leading" is the gap between two lines. }
+    Function Leading: SmallInt;
+    Function CapHeight: SmallInt;
+    { Returns the Glyph Index value in the TTF file, where AValue is the ordinal value of a character. }
+    function GetGlyphIndex(AValue: word): word;
+    { Returns the glyph advance width, based on the AIndex (glyph index) value. The result is in font units. }
+    function GetAdvanceWidth(AIndex: word): word;
+  public
+    Chars: TWordArray;
+    CharWidth: array[0..255] of SmallInt;
+    CharNames: PTTFEncodingNames;
+    CharCodes: PTTFEncodingValues;
+    CharBase:  PTTFEncodingNames;
+    PostScriptName: string;
+    FamilyName: string;
+    destructor Destroy; override;
+    // Load a TTF file from file or stream.
+    Procedure LoadFromFile(const AFileName : String);
+    Procedure LoadFromStream(AStream: TStream); virtual;
+    // Checks if Embedded is allowed, and also prepares CharWidths array
+    procedure PrepareFontDefinition(const Encoding:string; Embed: Boolean);
+    // Fill record with PDF Font definition data.
+    Procedure FillPDFFontDefinition(Out ADef: TPDFFontDefinition; Const AFontFile,AEncoding : String);
+    // Write Font Definition data to a file named FontFile.
+    procedure MakePDFFontDef(const FontFile: string; const Encoding: string; Embed: Boolean);
+    // The following are only valid after the file was succesfully read.
+    // Font file header info.
+    Property Directory : TTableDirectory Read FTableDir;
+    Property Tables : TTableDirectoryEntries Read FTables;
+    // The various tables as present in the font file.
+    Property Head : THead Read FHead;
+    Property HHead : THHead Read FHHead;
+    property CmapH : TCMapHeader Read FCmapH;
+    property CmapSubtables : TCmapSubTables Read FSubtables;
+    property CmapUnicodeMap : TCmapFmt4 Read FUnicodeMap;
+    property CmapUnicodeMapSegments : TUnicodeMapSegmentArray Read FUnicodeMapSegments;
+    Property Widths : TLongHorMetrics Read FWidths;
+    Property MaxP : TMaxP Read FMaxP;
+    Property OS2Data : TOS2Data Read FOS2Data;
+    Property PostScript : TPostScript Read FPostScript;
+    property NameEntries: TNameEntries read FNameEntries;
+  end;
+
+type
+  TConvertResult = (trNoError, trNullSrc, trNullDest, trDestExhausted,
+    trInvalidChar, trUnfinishedChar);
+
+  TConvertOption = (toInvalidCharError, toInvalidCharToSymbol,
+    toUnfinishedCharError, toUnfinishedCharToSymbol);
+  TConvertOptions = set of TConvertOption;
+
+// Convert string to known table type
+Function GetTableType(Const AName : String) : TTTFTableType;
+// Utility functions for text encoding conversions
+function ConvertUTF8ToUTF16(Dest: PWideChar; DestWideCharCount: SizeUInt; Src: PChar; SrcCharCount: SizeUInt;
+                            Options: TConvertOptions; out ActualWideCharCount: SizeUInt): TConvertResult;
+function UTF8ToUTF16(const P: PChar; ByteCnt: SizeUInt): UnicodeString;
+function UTF8ToUTF16(const S: AnsiString): UnicodeString;
+function StrToUTF16Hex(const AValue: UnicodeString; AIncludeBOM: boolean = True): AnsiString;
+
+
+Const
+  TTFTableNames : Array[TTTFTableType] of String
+                 = ('','head','hhea','maxp','hmtx','cmap','name','OS/2','post');
+
+
+Const
+  // Platform IDs used in the Name section
+  NamePlatFormIDAppleUnicode = 0;
+  NamePlatFormIDMacIntosh    = 1;
+  NamePlatFormIDISO          = 2;
+  NamePlatFormIDMicrosoft    = 3;
+
+  // Name IDs used in the Name section
+  NameIDCopyRight      = 0;
+  NameIDFontFamily     = 1;
+  NameIDFontSubFamily  = 2;
+  NameIDFontIdentifier = 3;
+  NameIDFullFontName   = 4;
+  NamdIDVersionString  = 5;
+  NameIDPostScriptName = 6;
+  NameIDTradeMark      = 7;
+
+  NameMSEncodingUndefined = 0;
+  NameMSEncodingUGL       = 1;
+
+implementation
+
+uses
+  inifiles;
+
+resourcestring
+  rsFontEmbeddingNotAllowed = 'Font licence does not allow embedding';
+
+Function GetTableType(Const AName : String) : TTTFTableType;
+begin
+  Result:=High(TTTFTableType);
+  While (Result<>ttUnknown) and (CompareText(AName,TTFTableNames[Result])<>0) do
+    Result:=Pred(Result);
+end;
+
+{------------------------------------------------------------------------------
+  Name:    ConvertUTF8ToUTF16
+  Params:  Dest                - Pointer to destination string
+           DestWideCharCount   - Wide char count allocated in destination string
+           Src                 - Pointer to source string
+           SrcCharCount        - Char count allocated in source string
+           Options             - Conversion options, if none is set, both
+             invalid and unfinished source chars are skipped
+
+             toInvalidCharError       - Stop on invalid source char and report
+                                      error
+             toInvalidCharToSymbol    - Replace invalid source chars with '?'
+             toUnfinishedCharError    - Stop on unfinished source char and
+                                      report error
+             toUnfinishedCharToSymbol - Replace unfinished source char with '?'
+
+           ActualWideCharCount - Actual wide char count converted from source
+                               string to destination string
+  Returns:
+    trNoError        - The string was successfully converted without
+                     any error
+    trNullSrc        - Pointer to source string is nil
+    trNullDest       - Pointer to destination string is nil
+    trDestExhausted  - Destination buffer size is not big enough to hold
+                     converted string
+    trInvalidChar    - Invalid source char has occured
+    trUnfinishedChar - Unfinished source char has occured
+
+  Converts the specified UTF-8 encoded string to UTF-16 encoded (system endian)
+ ------------------------------------------------------------------------------}
+function ConvertUTF8ToUTF16(Dest: PWideChar; DestWideCharCount: SizeUInt;
+  Src: PChar; SrcCharCount: SizeUInt; Options: TConvertOptions;
+  out ActualWideCharCount: SizeUInt): TConvertResult;
+var
+  DestI, SrcI: SizeUInt;
+  B1, B2, B3, B4: Byte;
+  W: Word;
+  C: Cardinal;
+
+  function UnfinishedCharError: Boolean;
+  begin
+    if toUnfinishedCharToSymbol in Options then
+    begin
+      Dest[DestI] := System.WideChar('?');
+      Inc(DestI);
+      Result := False;
+    end
+    else
+      if toUnfinishedCharError in Options then
+      begin
+        ConvertUTF8ToUTF16 := trUnfinishedChar;
+        Result := True;
+      end
+      else Result := False;
+  end;
+
+  function InvalidCharError(Count: SizeUInt): Boolean; inline;
+  begin
+    if not (toInvalidCharError in Options) then
+    begin
+      if toInvalidCharToSymbol in Options then
+      begin
+        Dest[DestI] := System.WideChar('?');
+        Inc(DestI);
+      end;
+
+      Dec(SrcI, Count);
+
+      // skip trailing UTF-8 char bytes
+      while (Count > 0) do
+      begin
+        if (Byte(Src[SrcI]) and %11000000) <> %10000000 then Break;
+        Inc(SrcI);
+        Dec(Count);
+      end;
+
+      Result := False;
+    end
+    else
+      if toInvalidCharError in Options then
+      begin
+        ConvertUTF8ToUTF16 := trUnfinishedChar;
+        Result := True;
+      end;
+  end;
+
+begin
+  ActualWideCharCount := 0;
+
+  if not Assigned(Src) then
+  begin
+    Result := trNullSrc;
+    Exit;
+  end;
+
+  if not Assigned(Dest) then
+  begin
+    Result := trNullDest;
+    Exit;
+  end;
+  SrcI := 0;
+  DestI := 0;
+
+  while (DestI < DestWideCharCount) and (SrcI < SrcCharCount) do
+  begin
+    B1 := Byte(Src[SrcI]);
+    Inc(SrcI);
+
+    if B1 < 128 then // single byte UTF-8 char
+    begin
+      Dest[DestI] := System.WideChar(B1);
+      Inc(DestI);
+    end
+    else
+    begin
+      if SrcI >= SrcCharCount then
+        if UnfinishedCharError then Exit(trInvalidChar)
+        else Break;
+
+      B2 := Byte(Src[SrcI]);
+      Inc(SrcI);
+
+      if (B1 and %11100000) = %11000000 then // double byte UTF-8 char
+      begin
+        if (B2 and %11000000) = %10000000 then
+        begin
+          Dest[DestI] := System.WideChar(((B1 and %00011111) shl 6) or (B2 and %00111111));
+          Inc(DestI);
+        end
+        else // invalid character, assume single byte UTF-8 char
+          if InvalidCharError(1) then Exit(trInvalidChar);
+      end
+      else
+      begin
+        if SrcI >= SrcCharCount then
+          if UnfinishedCharError then Exit(trInvalidChar)
+          else Break;
+
+        B3 := Byte(Src[SrcI]);
+        Inc(SrcI);
+
+        if (B1 and %11110000) = %11100000 then // triple byte UTF-8 char
+        begin
+          if ((B2 and %11000000) = %10000000) and ((B3 and %11000000) = %10000000) then
+          begin
+            W := ((B1 and %00011111) shl 12) or ((B2 and %00111111) shl 6) or (B3 and %00111111);
+            if (W < $D800) or (W > $DFFF) then // to single wide char UTF-16 char
+            begin
+              Dest[DestI] := System.WideChar(W);
+              Inc(DestI);
+            end
+            else // invalid UTF-16 character, assume double byte UTF-8 char
+              if InvalidCharError(2) then Exit(trInvalidChar);
+          end
+          else // invalid character, assume double byte UTF-8 char
+            if InvalidCharError(2) then Exit(trInvalidChar);
+        end
+        else
+        begin
+          if SrcI >= SrcCharCount then
+            if UnfinishedCharError then Exit(trInvalidChar)
+            else Break;
+
+          B4 := Byte(Src[SrcI]);
+          Inc(SrcI);
+
+          if ((B1 and %11111000) = %11110000) and ((B2 and %11000000) = %10000000)
+            and ((B3 and %11000000) = %10000000) and ((B4 and %11000000) = %10000000) then
+          begin // 4 byte UTF-8 char
+            C := ((B1 and %00011111) shl 18) or ((B2 and %00111111) shl 12)
+              or ((B3 and %00111111) shl 6)  or (B4 and %00111111);
+            // to double wide char UTF-16 char
+            Dest[DestI] := System.WideChar($D800 or ((C - $10000) shr 10));
+            Inc(DestI);
+            if DestI >= DestWideCharCount then Break;
+            Dest[DestI] := System.WideChar($DC00 or ((C - $10000) and %0000001111111111));
+            Inc(DestI);
+          end
+          else // invalid character, assume triple byte UTF-8 char
+            if InvalidCharError(3) then Exit(trInvalidChar);
+        end;
+      end;
+    end;
+  end;
+
+  if DestI >= DestWideCharCount then
+  begin
+    DestI := DestWideCharCount - 1;
+    Result := trDestExhausted;
+  end
+  else
+    Result := trNoError;
+
+  Dest[DestI] := #0;
+  ActualWideCharCount := DestI + 1;
+end;
+
+function UTF8ToUTF16(const P: PChar; ByteCnt: SizeUInt): UnicodeString;
+var
+  L: SizeUInt;
+begin
+  if ByteCnt=0 then
+    exit('');
+  SetLength(Result, ByteCnt);
+  // wide chars of UTF-16 <= bytes of UTF-8 string
+  if ConvertUTF8ToUTF16(PWideChar(Result), Length(Result) + 1, P, ByteCnt,
+    [toInvalidCharToSymbol], L) = trNoError
+  then SetLength(Result, L - 1)
+  else Result := '';
+end;
+
+function UTF8ToUTF16(const S: AnsiString): UnicodeString;
+begin
+  Result:=UTF8ToUTF16(PChar(S),length(S));
+end;
+
+function StrToUTF16Hex(const AValue: UnicodeString; AIncludeBOM: boolean = True): AnsiString;
+var
+  pc: ^Word;
+  i: integer;
+begin
+  if AIncludeBOM then
+    Result := 'FEFF'   // BOM marker to indicate UTF-16BE (big-endian) encoding scheme
+  else
+    Result := '';
+  for i := 1 to Length(AValue) do
+  begin
+    pc := @AValue[i];
+    Result := Result + AnsiString(IntToHex(pc^, 4));
+  end;
+end;
+
+function TTFFileInfo.ReadULong(AStream: TStream): Longword;inline;
+begin
+  Result:=0;
+  AStream.ReadBuffer(Result,SizeOf(Result));
+  if Not IsNativeData then
+    Result:=BEtoN(Result);
+end;
+
+function TTFFileInfo.ReadUShort(AStream: TStream): Word;inline;
+begin
+  Result:=0;
+  AStream.ReadBuffer(Result,SizeOf(Result));
+  if Not IsNativeData then
+    Result:=BEtoN(Result);
+end;
+
+function TTFFileInfo.ReadShort(AStream: TStream): Smallint;inline;
+begin
+  Result:=SmallInt(ReadUShort(AStream));
+end;
+
+procedure TTFFileInfo.ParseHead(AStream : TStream);
+var
+  i : Integer;
+begin
+  AStream.ReadBuffer(FHead,SizeOf(FHead));
+  if IsNativeData then
+    exit;
+  FHead.FileVersion.Version := BEtoN(FHead.FileVersion.Version);
+  FHead.FileVersion.Minor := FixMinorVersion(FHead.FileVersion.Minor);
+  FHead.FontRevision.Version := BEtoN(FHead.FontRevision.Version);
+  FHead.FontRevision.Minor := FixMinorVersion(FHead.FontRevision.Minor);
+  FHead.Created := BEtoN(FHead.Created);
+  FHead.Modified := BEtoN(FHead.Modified);
+  For i:=0 to 3 do
+    FHead.BBox[i]:=betOn(FHead.BBox[i]);
+  FHead.CheckSumAdjustment:=beton(FHead.CheckSumAdjustment);
+  FHead.MagicNumber:=beton(FHead.MagicNumber);
+  FHead.Flags:=Beton(FHead.Flags);
+  FHead.UnitsPerEm:=beton(FHead.UnitsPerEm);
+  FHead.MacStyle:=Beton(FHead.MacStyle);
+  FHead.LowestRecPPEM:=Beton(FHead.LowestRecPPEM);
+  FHead.FontDirectionHint:=Beton(FHead.FontDirectionHint);
+  FHead.IndexToLocFormat:=Beton(FHead.IndexToLocFormat);
+  FHead.glyphDataFormat:=Beton(FHead.glyphDataFormat);
+end;
+
+procedure TTFFileInfo.ParseHhea(AStream : TStream);
+
+begin
+  AStream.ReadBuffer(FHHEad,SizeOf(FHHEad));
+  if IsNativeData then
+    exit;
+  FHHEad.TableVersion.Version := BeToN(FHHEad.TableVersion.Version);
+  FHHEad.TableVersion.Minor := FixMinorVersion(FHHEad.TableVersion.Minor);
+  FHHEad.Ascender:=BeToN(FHHEad.Ascender);
+  FHHEad.Descender:=BeToN(FHHEad.Descender);
+  FHHEad.LineGap:=BeToN(FHHEad.LineGap);
+  FHHEad.MinLeftSideBearing:=BeToN(FHHEad.MinLeftSideBearing);
+  FHHEad.MinRightSideBearing:=BeToN(FHHEad.MinRightSideBearing);
+  FHHEad.XMaxExtent:=BeToN(FHHEad.XMaxExtent);
+  FHHEad.CaretSlopeRise:=BeToN(FHHEad.CaretSlopeRise);
+  FHHEad.CaretSlopeRun:=BeToN(FHHEad.CaretSlopeRun);
+  FHHEad.metricDataFormat:=BeToN(FHHEad.metricDataFormat);
+  FHHEad.numberOfHMetrics:=BeToN(FHHEad.numberOfHMetrics);
+  FHHead.AdvanceWidthMax := BeToN(FHHead.AdvanceWidthMax);
+end;
+
+procedure TTFFileInfo.ParseMaxp(AStream : TStream);
+
+begin
+  AStream.ReadBuffer(FMaxP,SizeOf(TMaxP));
+  if IsNativeData then
+    exit;
+  With FMaxP do
+    begin
+    VersionNumber.Version := BEtoN(VersionNumber.Version);
+    VersionNumber.Minor := FixMinorVersion(VersionNumber.Minor);
+    numGlyphs:=Beton(numGlyphs);
+    maxPoints:=Beton(maxPoints);
+    maxContours:=Beton(maxContours);
+    maxCompositePoints :=BeToN(maxCompositePoints);
+    maxCompositeContours :=BeToN(maxCompositeContours);
+    maxZones :=BeToN(maxZones);
+    maxTwilightPoints :=BeToN(maxTwilightPoints);
+    maxStorage :=BeToN(maxStorage);
+    maxFunctionDefs :=BeToN(maxFunctionDefs);
+    maxInstructionDefs :=BeToN(maxInstructionDefs);
+    maxStackElements :=BeToN(maxStackElements);
+    maxSizeOfInstructions :=BeToN(maxSizeOfInstructions);
+    maxComponentElements :=BeToN(maxComponentElements);
+    maxComponentDepth :=BeToN(maxComponentDepth);
+    end;
+end;
+
+procedure TTFFileInfo.ParseHmtx(AStream : TStream);
+
+var
+  i : Integer;
+
+begin
+  SetLength(FWidths,FHHead.numberOfHMetrics);
+  AStream.ReadBuffer(FWidths[0],SizeOf(TLongHorMetric)*Length(FWidths));
+  if IsNativeData then
+    exit;
+  for I:=0 to FHHead.NumberOfHMetrics-1 do
+    begin
+    FWidths[I].AdvanceWidth:=beton(FWidths[I].AdvanceWidth);
+    FWidths[I].LSB:=beton(FWidths[I].LSB);
+    end;
+end;
+
+
+procedure TTFFileInfo.ParseCmap(AStream : TStream);
+var
+  SegCount: Word;
+  GiD,I,J,UE: Integer;
+  TT,TableStartPos: LongWord;
+  Segm : TUnicodeMapSegment;
+  GlyphIDArray : Array of word;
+  S : TStream;
+
+begin
+  TableStartPos:=AStream.Position;
+  FCMapH.Version:=ReadUShort(AStream);
+  FCMapH.SubtableCount:=ReadUShort(AStream);
+  SetLength(FSubtables,CMapH.SubtableCount);
+  for I:= 0 to FCMapH.SubtableCount-1 do
+    begin
+    FSubtables[i].PlatformID:=ReadUShort(AStream);
+    FSubtables[i].EncodingID:=ReadUShort(AStream);
+    FSubtables[i].Offset:=ReadULong(AStream); // 4 bytes - Offset of subtable
+    end;
+  UE:=FCMapH.SubtableCount-1;
+  While (UE>=0) and ((FSubtables[UE].PlatformID<>3) or (FSubtables[UE].EncodingID<> 1)) do
+    Dec(UE);
+  if (UE=-1) then
+    Raise ETTF.Create('No Format 4 map (unicode) table found');
+  TT:=TableStartPos+FSubtables[UE].Offset;
+  AStream.Position:=TT;
+  FUnicodeMap.Format:= ReadUShort(AStream);               // 2 bytes - Format of subtable
+  if (FUnicodeMap.Format<>4) then
+    Raise ETTF.CreateFmt('Unexpected unicode subtable format, expected 4, got %s',[FUnicodeMap.Format]);
+  FUnicodeMap.Length:=ReadUShort(AStream);
+  S:=TMemoryStream.Create;
+  try
+    // Speed up the process, read everything in a single mem block.
+    S.CopyFrom(AStream,FUnicodeMap.Length-4);
+    S.Position:=0;
+    FUnicodeMap.LanguageID:=ReadUShort(S);
+    FUnicodeMap.SegmentCount2:=ReadUShort(S);            // 2 bytes - Segments count
+    FUnicodeMap.SearchRange:=ReadUShort(S);
+    FUnicodeMap.EntrySelector:=ReadUShort(S);
+    FUnicodeMap.RangeShift:=ReadUShort(S);
+    SegCount:=FUnicodeMap.SegmentCount2 div 2;
+    SetLength(FUnicodeMapSegments,SegCount);
+    for i:=0 to SegCount-1 do
+      FUnicodeMapSegments[i].EndCode:=ReadUShort(S);
+    ReadUShort(S);
+    for i:=0 to SegCount-1 do
+      FUnicodeMapSegments[i].StartCode:=ReadUShort(S);
+    for i:=0 to SegCount-1 do
+      FUnicodeMapSegments[i].IDDelta:=ReadShort(S);
+    for i:=0 to SegCount-1 do
+      FUnicodeMapSegments[i].IDRangeOffset:=ReadUShort(S);
+    UE:=S.Position;
+    UE:=(S.Size-UE) div 2;
+    SetLength(GlyphIDArray,UE);
+    For J:=0 to UE-1 do
+      GlyphIDArray[J]:=ReadUShort(S);
+    J:=0;
+    for i:=0 to SegCount-1 do
+      With FUnicodeMapSegments[i] do
+        if (EndCode>J) then
+          J:=EndCode;
+    SetLength(Chars,J+1);
+    for i:=0 to SegCount-1 do
+      begin
+      Segm:=FUnicodeMapSegments[i];
+      for J:=Segm.StartCode to Segm.EndCode do
+        if J<>$FFFF then // Last block has $FFFF as start/end code.
+          begin
+          if Segm.IDRangeOffset=0 then
+            Gid:=J+Segm.IDDelta
+          else
+            begin
+            Gid:=GlyphIDArray[Segm.IDRangeOffset div 2 + i-segcount - Segm.startCode+j];
+            if (Gid>0) then
+              Gid:= Gid+Segm.IDDelta;
+            end;
+          if (Gid>=65536) then
+            Gid:=Gid-65536;
+          if Gid>0 then
+            Chars[J]:=Gid
+          else
+            Chars[J]:=0;
+          end;
+      end;
+  finally
+    S.Free;
+  end;
+end;
+
+procedure TTFFileInfo.ParseName(AStream : TStream);
+var
+  I,J,Count : Integer;
+  StringOffset: Word;
+  TableStartPos: LongWord;
+  S : AnsiString;
+  W : Widestring;
+  FMT : Word;
+  N : TNameRecord;
+  E : TNameEntries;
+  WA : Array of word;
+
+begin
+  TableStartPos:= AStream.Position;                   // memorize Table start position
+  Fmt:=ReadUShort(AStream);                  // skip 2 bytes - Format
+  Count:=ReadUShort(AStream);                        // 2 bytes
+  StringOffset:=ReadUShort(AStream);                 // 2 bytes
+  E := FNameEntries;
+  SetLength(E,Count);
+  //  Read Descriptors
+  for I:=0 to Count-1 do
+  begin
+    AStream.ReadBuffer(N,SizeOf(TNameRecord));
+    N.PlatFormID:=BeTon(N.PlatFormID);
+    N.EncodingID:=BeTon(N.EncodingID);
+    N.LanguageID:=BeTon(N.LanguageID);
+    N.NameID:=BeTon(N.NameID);
+    N.StringLength:=BeTon(N.StringLength);
+    N.StringOffset:=BeToN(N.StringOffset);
+    E[i].Info:=N;
+  end;  { for i ... }
+  //  Read Values
+  for I:=0 to Count-1 do
+  begin
+    AStream.Position:=TableStartPos+StringOffset+E[i].Info.StringOffset;
+    if E[i].Info.EncodingID=1 then
+    begin
+      SetLength(WA,E[i].Info.StringLength div 2);
+      SetLength(W,Length(WA));
+      AStream.Read(WA[0],SizeOf(Word)*Length(W));    // 1 byte
+      For J:=0 to Length(WA)-1 do
+        W[J+1]:=WideChar(Beton(WA[J]));
+      E[i].Value:=W;
+    end
+    else
+    begin
+      SetLength(S,E[i].Info.StringLength);
+      AStream.Read(S[1],SizeOf(AnsiChar)*Length(S));    // 1 byte
+      E[i].Value:=S;
+    end;
+    {$IFDEF gdebug}
+      writeln('-------------------');
+      writeln('LanguageID = ', E[i].Info.LanguageID);
+      writeln('EncodingID = ', E[i].Info.EncodingID);
+      writeln('NameID = ', E[i].Info.NameID);
+      writeln('Value = ', E[i].Value);
+    {$ENDIF}
+    if (PostScriptName='')
+       and (E[i].Info.NameID=NameIDPostScriptName)
+       and (E[i].Info.EncodingID=NameMSEncodingUGL) then
+      PostScriptName:=E[i].Value;
+    if (FamilyName = '')
+        and (E[i].Info.NameID = NameIDFontFamily)
+        and (E[i].Info.LanguageID = 1033)
+        and (E[i].Info.EncodingID = 1) then
+      FamilyName := E[i].Value;
+  end; { for i ... }
+end;
+
+procedure TTFFileInfo.ParseOS2(AStream : TStream);
+
+begin
+  FillWord(FOS2Data,SizeOf(TOS2Data) div 2,0);
+  // -18, so version 1 will not overflow
+  AStream.ReadBuffer(FOS2Data,SizeOf(TOS2Data)-18);
+  if Not isNativeData then
+    With FOS2Data do
+      begin
+      version:=BeToN(version);
+      xAvgCharWidth:=BeToN(xAvgCharWidth);
+      usWeightClass:=BeToN(usWeightClass);
+      usWidthClass:=BeToN(usWidthClass);
+      fsType:=BeToN(fsType);
+      ySubscriptXSize:=BeToN(ySubscriptXSize);
+      ySubscriptYSize:=BeToN(ySubscriptYSize);
+      ySubscriptXOffset:=BeToN(ySubscriptXOffset);
+      ySubscriptYOffset:=BeToN(ySubscriptYOffset);
+      ySuperscriptXSize:=BeToN(ySuperscriptXSize);
+      ySuperscriptYSize:=BeToN(ySuperscriptYSize);
+      ySuperscriptXOffset:=BeToN(ySuperscriptXOffset);
+      ySuperscriptYOffset:=BeToN(ySuperscriptYOffset);
+      yStrikeoutSize:=BeToN(yStrikeoutSize);
+      yStrikeoutPosition:=BeToN(yStrikeoutPosition);
+      sFamilyClass:=BeToN(sFamilyClass);
+      ulUnicodeRange1:=BeToN(ulUnicodeRange1);
+      ulUnicodeRange2:=BeToN(ulUnicodeRange2);
+      ulUnicodeRange3:=BeToN(ulUnicodeRange3);
+      ulUnicodeRange4:=BeToN(ulUnicodeRange4);
+      fsSelection:=BeToN(fsSelection);
+      usFirstCharIndex:=BeToN(usFirstCharIndex);
+      usLastCharIndex:=BeToN(usLastCharIndex);
+      sTypoAscender:=BeToN(sTypoAscender);
+      sTypoDescender:=BeToN(sTypoDescender);
+      sTypoLineGap:=BeToN(sTypoLineGap);
+      usWinAscent:=BeToN(usWinAscent);
+      usWinDescent:=BeToN(usWinDescent);
+      // We miss 7 fields
+      end;
+  With FOS2Data do
+    begin
+    // Read remaining 7 fields' data depending on version
+    if Version>=1 then
+      begin
+      ulCodePageRange1:=ReadULong(AStream);
+      ulCodePageRange2:=ReadULong(AStream);
+      end;
+    if Version>=2 then
+      begin
+      sxHeight:=ReadShort(AStream);
+      sCapHeight:=ReadShort(AStream);
+      usDefaultChar:=ReadUShort(AStream);
+      usBreakChar:=ReadUShort(AStream);
+      usMaxContext:=ReadUShort(AStream);
+      end;
+    end;
+end;
+
+procedure TTFFileInfo.ParsePost(AStream : TStream);
+
+begin
+  AStream.ReadBuffer(FPostScript,SizeOf(TPostScript));
+  if not IsNativeData then
+    With FPostScript do
+      begin
+      Format.Version := BEtoN(Format.Version);
+      Format.Minor := FixMinorVersion(Format.Minor);
+      ItalicAngle:=BeToN(ItalicAngle);
+      UnderlinePosition:=BeToN(UnderlinePosition);
+      underlineThickness:=BeToN(underlineThickness);
+      isFixedPitch:=BeToN(isFixedPitch);
+      minMemType42:=BeToN(minMemType42);
+      maxMemType42:=BeToN(maxMemType42);
+      minMemType1:=BeToN(minMemType1);
+      maxMemType1:=BeToN(maxMemType1);
+      end;
+end;
+
+procedure TTFFileInfo.LoadFromFile(const AFileName: String);
+
+Var
+  AStream: TFileStream;
+begin
+  FFilename := AFilename;
+  AStream:= TFileStream.Create(AFileName,fmOpenRead);
+  try
+    LoadFromStream(AStream);
+  finally
+    AStream.Free;
+  end;
+end;
+
+procedure TTFFileInfo.LoadFromStream(AStream : TStream);
+var
+  i: Integer;
+  tt : TTTFTableType;
+begin
+  FOriginalSize:= AStream.Size;
+  AStream.ReadBuffer(FTableDir,Sizeof(TTableDirectory));
+  if not isNativeData then
+    With FTableDir do
+      begin
+      FontVersion.Version := BEtoN(FontVersion.Version);
+      FontVersion.Minor := FixMinorVersion(FontVersion.Minor);
+      Numtables:=BeToN(Numtables);
+      SearchRange:=BeToN(SearchRange);
+      EntrySelector:=BeToN(EntrySelector);
+      RangeShift:=BeToN(RangeShift);
+      end;
+  SetLength(FTables,FTableDir.Numtables);
+  AStream.ReadBuffer(FTables[0],FTableDir.NumTables*Sizeof(TTableDirectoryEntry));
+  if Not IsNativeData then
+    For I:=0 to Length(FTables)-1 do
+      With FTables[I] do
+        begin
+        checkSum:=BeToN(checkSum);
+        offset:=BeToN(offset);
+        Length:=BeToN(Length);
+        end;
+  for I:=0 to FTableDir.NumTables-1 do
+    begin
+    TT:=GetTableType(FTables[I].Tag);
+    if (TT<>ttUnknown) then
+      begin
+      AStream.Position:=FTables[i].Offset;
+      Case TT of
+        tthead: ParseHead(AStream);
+        ttHhea: ParseHhea(AStream);
+        ttmaxp: ParseMaxp(AStream);
+        tthmtx: ParseHmtx(AStream);
+        ttcmap: ParseCmap(AStream);
+        ttname: ParseName(AStream);
+        ttos2 : ParseOS2(AStream);
+        ttPost: ParsePost(AStream);                                  // lecture table "Post"
+      end;
+      end;
+    end;
+end;
+
+procedure TTFFileInfo.PrepareFontDefinition(const Encoding: string; Embed: Boolean);
+var
+  I : Integer;
+begin
+  if embed and not Embeddable then
+    raise ETTF.Create(rsFontEmbeddingNotAllowed);
+  PrepareEncoding(Encoding);
+//  MissingWidth:=ToNatural(Widths[Chars[CharCodes^[32]]].AdvanceWidth);  // Char(32) - Space character
+  MissingWidth:=Widths[Chars[CharCodes^[32]]].AdvanceWidth;  // Char(32) - Space character
+  for I:=0 to 255 do
+    begin
+    if (Widths[Chars[CharCodes^[i]]].AdvanceWidth> 0) and (CharNames^[i]<> '.notdef') then
+      CharWidth[I]:= ToNatural(Widths[Chars[CharCodes^[I]]].AdvanceWidth)
+    else
+      CharWidth[I]:= MissingWidth;
+    end;
+end;
+
+procedure TTFFileInfo.FillPDFFontDefinition(out ADef: TPDFFontDefinition; const AFontFile, AEncoding: String);
+
+Var
+  I : Integer;
+  S : String;
+
+begin
+  ADef.FontType:='TrueType';  // DON'T LOCALIZE
+  ADef.FontName:=PostScriptName;
+  ADef.Ascender:=Ascender;
+  ADef.Descender:=Descender;
+  ADef.CapHeight:=Capheight;
+  ADef.Flags:=Flags;
+  For I:=0 to 3 do
+    ADef.BBox[i]:=ToNatural(FHead.BBox[I]);
+  ADef.ItalicAngle:=FPostScript.ItalicAngle;
+  ADef.StemV:=StemV;
+  ADef.MissingWidth:=MissingWidth;
+  ADef.FontUp:=ToNatural(FPostScript.UnderlinePosition);
+  ADef.FontUt:=ToNatural(FPostScript.UnderlineThickness);
+  ADef.Encoding:=AEncoding;
+  ADef.OriginalSize:=FOriginalSize;
+  ADef.FontFile:=ChangeFileExt(AFontFile,'.z');
+  if (Lowercase(AEncoding)<>'cp1252') then
+    ADef.Diffs:=MakeDifferences;
+  S:='';
+  for I:=32 to 255 do
+    begin
+    if I>32 then
+      S:=S+' ';
+    S:=S+IntToStr(CharWidth[I]);
+    end;
+  ADef.CharWidths:=S;
+end;
+
+procedure TTFFileInfo.PrepareEncoding(const AEnCoding: String);
+var
+  TE : TTTFEncoding;
+  V : PTTFEncodingValues;
+begin
+  TE:=GetEncoding(AEncoding);
+  if (TE<>teUnknown) then
+    GetEncodingTables(Te,CharNames,CharCodes);
+  // Needed to mak difference
+  GetEncodingTables(Te,CharBase,V);
+end;
+
+procedure TTFFileInfo.MakePDFFontDefinitionFile(const FontFile, Section, AEncoding: string);
+
+var
+  Ini : TMemIniFile;
+  S: String;
+  I : Integer;
+  Def : TPDFFontDefinition;
+
+begin
+  FillPDFFontDefinition(Def,FontFile,AEncoding);
+  Ini:=TMemIniFile.Create(FontFile);
+  With Ini Do
+    try
+      WriteString(Section,'FontType',Def.FontType);
+      WriteString(Section,'FontName',Def.FontName);
+      WriteInteger(Section,'Ascent',Def.Ascender);
+      WriteInteger(Section,'Descent',Def.Descender);
+      WriteInteger(Section,'CapHeight',Def.CapHeight);
+      WriteInteger(Section,'Flags',Def.Flags);
+      S:='';
+      for i:=0 to 3 do
+        begin
+        if I>0 then
+          S:=S+' ';
+        S:=S+IntToStr(Def.BBox[I]);
+        end;
+      WriteString(Section,'FontBBox',S);
+      WriteInteger(Section,'ItalicAngle',Def.ItalicAngle);
+      WriteInteger(Section,'StemV',Def.StemV);
+      WriteInteger(Section,'MissingWidth',Def.MissingWidth);
+      WriteInteger(Section,'FontUp',Def.FontUp);
+      WriteInteger(Section,'FontUt',Def.FontUt);
+      WriteString(Section,'Encoding',Def.Encoding);
+      WriteString(Section,'FontFile',Def.FontFile);
+      WriteInteger(Section,'OriginalSize',Def.OriginalSize);
+      WriteString(Section,'Diffs',Def.Diffs);
+      WriteString(Section,'CharWidth',Def.CharWidths);
+      UpdateFile;
+    finally
+      Ini.Free;
+    end;
+end;
+
+function TTFFileInfo.MakeDifferences: String;
+var
+  i,l: Integer;
+begin
+  Result:= '';
+  L:= 0;
+  for i:=32 to 255 do
+    if CharNames^[i]<>CharBase^[i]  then
+      begin
+      if (i<>l+1) then
+        Result:= Result+IntToStr(i)+' ';
+      l:=i;
+      Result:= Result+'/'+CharNames^[i]+' ';
+      end;
+end;
+
+function TTFFileInfo.Bold: Boolean;
+begin
+  Bold:=(FOS2Data.fsSelection and 32)<>0;
+end;
+
+function TTFFileInfo.StemV: SmallInt;
+begin
+  if Bold then
+    StemV:= 120
+  else
+    StemV:= 70;
+end;
+
+function TTFFileInfo.Embeddable: Boolean;
+begin
+  With FOS2Data do
+    Result:=(FsType<> 2) and ((FsType and 512)= 0);
+end;
+
+function TTFFileInfo.Ascender: SmallInt;
+begin
+  Result:=ToNatural(FOS2Data.sTypoAscender);         // 2 bytes
+end;
+
+function TTFFileInfo.Descender: SmallInt;
+begin
+  Result := ToNatural(FOS2Data.sTypoDescender);        // 2 bytes
+end;
+
+function TTFFileInfo.Leading: SmallInt;
+begin
+  Result := ToNatural(FOS2Data.sTypoLineGap);
+end;
+
+function TTFFileInfo.CapHeight: SmallInt;
+begin
+  With FOS2Data do
+    begin
+    if Version>= 2 then
+      Result:=ToNatural(sCapHeight)
+    else
+      Result:=Ascender;
+    end;
+end;
+
+function TTFFileInfo.GetGlyphIndex(AValue: word): word;
+begin
+  result := Chars[AValue];
+end;
+
+function TTFFileInfo.GetAdvanceWidth(AIndex: word): word;
+begin
+  Result := Widths[AIndex].AdvanceWidth;
+end;
+
+destructor TTFFileInfo.Destroy;
+begin
+  SetLength(FNameEntries, 0);
+  inherited Destroy;
+end;
+
+{ Implementation based on a PHP ttf reader unit.
+  http://www.4real.gr/TTF.php.txt }
+function TTFFileInfo.FixMinorVersion(const AMinor: word): word;
+var
+  d: double;
+begin
+  d := AMinor / 65536;
+  Result := round(d*10000);
+end;
+
+function TTFFileInfo.IsNativeData: Boolean;
+begin
+  Result:=False;
+end;
+
+function TTFFileInfo.ToNatural(AUnit: Smallint): Smallint;
+begin
+  if FHead.UnitsPerEm=0 then
+    Result:=0
+  else
+    Result:=Round(AUnit*1000/FHead.UnitsPerEm);
+end;
+
+function TTFFileInfo.Flags: Integer;
+begin
+  Result:=32;
+  if FPostScript.IsFixedPitch<>0 then
+    Result:=Result+1;
+  if FPostScript.ItalicAngle<>0 then
+    Flags:= Flags+64;
+end;
+
+procedure TTFFileInfo.MakePDFFontDef(const FontFile: string; const Encoding:string; Embed: Boolean);
+begin
+  PrepareFontDefinition(Encoding, Embed);
+  MakePDFFontDefinitionFile(FontFile,PostScriptName,Encoding);
+end;
+
+
+end.
+

+ 3569 - 0
packages/fcl-pdf/src/fppdf.pp

@@ -0,0 +1,3569 @@
+{
+    This file is part of the Free Component Library (FCL)
+    Copyright (c) 2014 by Michael Van Canneyt
+
+    This unit generates PDF files, without dependencies on GUI libraries.
+    (Based on original ideas from the fpGUI pdf generator by Jean-Marc Levecque 
+     <[email protected]>)
+    
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+unit fppdf;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes,
+  SysUtils,
+  StrUtils,
+  contnrs,
+  fpImage,
+  zstream;
+
+Const
+  clBlack = $000000;
+  clBlue  = $0000FF;
+  clGreen = $00FF00;
+  clRed   = $FF0000;
+
+type
+  TPDFPaperType = (ptCustom, ptA4, ptA5, ptLetter, ptLegal, ptExecutive, ptComm10, ptMonarch, ptDL, ptC5, ptB5);
+  TPDFPaperOrientation = (ppoPortrait,ppoLandscape);
+  TPDFPenStyle = (ppsSolid,ppsDash,ppsDot,ppsDashDot,ppsDashDotDot);
+  TPDFPageLayout = (lSingle, lTwo, lContinuous);
+  TPDFUnitOfMeasure = (uomInches, uomMillimeters, uomCentimeters, uomPixels);
+
+  TPDFOption = (poOutLine, poCompressText, poCompressFonts);
+  TPDFOptions = set of TPDFOption;
+
+  EPDF = Class(Exception);
+  TPDFDocument = Class;
+  TARGBColor = Cardinal;
+  TPDFFloat = Single;
+
+
+  TPDFDimensions = record
+    T,L,R,B: TPDFFloat;
+  end;
+
+
+  TPDFPaper = record
+    H, W: integer;
+    Printable: TPDFDimensions;
+  end;
+
+
+  TPDFCoord = record
+    X,Y: TPDFFloat;
+  end;
+
+
+  TPDFCoordArray = array of TPDFCoord;
+
+  { We use a special 3x3 matrix for transformations of coordinates. As the
+    only allowed transformations are translations and scalations, we need a
+    matrix with the following content ([x,y] is a variable):
+        [0,0]   0   [2,0]
+          0   [1,1] [2,1]
+          0     0     1
+    [0,0]: X scalation
+    [2,0]: X translation
+    [1,1]: Y scalation
+    [2,1]: Y translation
+  }
+  TPDFMatrix = object
+    _00, _20, _11, _21: TPDFFloat;
+    function Transform(APoint: TPDFCoord): TPDFCoord; overload;
+    function Transform(X, Y: TPDFFloat): TPDFCoord; overload;
+    function ReverseTransform(APoint: TPDFCoord): TPDFCoord;
+  end;
+
+
+  TPDFObject = class(TObject)
+  Protected
+    Class Function FloatStr(F: TPDFFloat) : String;
+    procedure Write(const AStream: TStream); virtual;
+    Class procedure WriteString(const AValue: string; AStream: TStream);
+  public
+    Constructor Create(Const ADocument : TPDFDocument); virtual; overload;
+  end;
+
+
+  TPDFDocumentObject = Class(TPDFObject)
+  Private
+    FDocument : TPDFDocument;
+  Public
+    Constructor Create(Const ADocument : TPDFDocument); override; overload;
+    Procedure SetWidth(AWidth : TPDFFloat; AStream : TStream);
+    Property Document : TPDFDocument Read FDocument ;
+  end;
+
+
+  TPDFBoolean = class(TPDFObject)
+  private
+    FValue: Boolean;
+  protected
+    procedure Write(const AStream: TStream); override;
+  public
+    constructor Create(Const ADocument : TPDFDocument; const AValue: Boolean);overload;
+  end;
+
+
+  TPDFMoveTo = class(TPDFObject)
+  private
+    FPos : TPDFCoord;
+  protected
+    procedure Write(const AStream: TStream); override;
+  public
+    class function Command(APos: TPDFCoord): String;
+    class function Command(AX,AY: TPDFFloat): String;
+    constructor Create(Const ADocument : TPDFDocument; const AX,AY : TPDFFloat);overload;
+    constructor Create(Const ADocument : TPDFDocument; const APos : TPDFCoord);overload;
+  end;
+
+
+  TPDFInteger = class(TPDFObject)
+  private
+    FInt: integer;
+  protected
+    procedure Inc;
+    procedure Write(const AStream: TStream); override;
+  public
+    constructor Create(Const ADocument : TPDFDocument; const AValue: integer);overload;
+    property Value: integer read FInt write FInt;
+  end;
+
+
+  TPDFReference = class(TPDFObject)
+  private
+    FValue: integer;
+  protected
+    procedure Write(const AStream: TStream); override;
+  public
+    constructor Create(Const ADocument : TPDFDocument; Const AValue: integer);overload;
+    property Value: integer read FValue write FValue;
+  end;
+
+
+  TPDFName = class(TPDFObject)
+  private
+    FName : string;
+    function  ConvertCharsToHex: string;
+  protected
+    procedure Write(const AStream: TStream); override;
+  public
+    constructor Create(Const ADocument : TPDFDocument; const AValue: string); overload;
+    property Name : String read FName;
+  end;
+
+
+  TPDFString = class(TPDFDocumentObject)
+  private
+    FValue: string;
+  protected
+    procedure Write(const AStream: TStream); override;
+  public
+    constructor Create(Const ADocument : TPDFDocument; const AValue: string); overload;
+  end;
+
+
+  TPDFUTF8String = class(TPDFDocumentObject)
+  private
+    FValue: UTF8String;
+    FFontIndex: integer;
+    { Remap each character to the equivalant dictionary character code }
+    function RemapedText: String;
+  protected
+    procedure Write(const AStream: TStream); override;
+  public
+    constructor Create(Const ADocument : TPDFDocument; const AValue: UTF8String; const AFontIndex: integer); overload;
+    property FontIndex: integer read FFontIndex;
+  end;
+
+
+  TPDFArray = class(TPDFDocumentObject)
+  private
+    FArray: TFPObjectList;
+  protected
+    procedure Write(const AStream: TStream); override;
+    procedure AddItem(const AValue: TPDFObject);
+    // Add integers in S as TPDFInteger elements to the array
+    Procedure AddIntArray(S : String);
+  public
+    constructor Create(Const ADocument : TPDFDocument); override;
+    destructor Destroy; override;
+  end;
+
+
+  TPDFStream = class(TPDFObject)
+  private
+    FItems: TFPObjectList;
+  protected
+    procedure Write(const AStream: TStream); override;
+    procedure AddItem(const AValue: TPDFObject);
+  public
+    constructor Create(Const ADocument : TPDFDocument; OwnsObjects : Boolean = True); overload;
+    destructor Destroy; override;
+  end;
+
+
+  TPDFEmbeddedFont = class(TPDFObject)
+  private
+    FTxtFont: integer;
+    FTxtSize: string;
+  protected
+    procedure Write(const AStream: TStream); override;
+    Class function WriteEmbeddedFont(const ADocument: TPDFDocument; const Src: TMemoryStream; const AStream: TStream): int64;
+  public
+    constructor Create(Const ADocument : TPDFDocument;const AFont: integer; const ASize: string); overload;
+  end;
+
+
+  TPDFText = class(TPDFObject)
+  private
+    FX: TPDFFloat;
+    FY: TPDFFloat;
+    FString: TPDFString;
+  protected
+    procedure Write(const AStream: TStream); override;
+  public
+    constructor Create(Const ADocument : TPDFDocument; const AX, AY: TPDFFloat; const AText: string); overload;
+    destructor Destroy; override;
+    Property X : TPDFFloat Read FX Write FX;
+    Property Y : TPDFFloat Read FY Write FY;
+    Property Text : TPDFString Read FString;
+  end;
+
+
+  TPDFUTF8Text = class(TPDFObject)
+  private
+    FX: TPDFFloat;
+    FY: TPDFFloat;
+    FString: TPDFUTF8String;
+    FFontIndex: integer;
+  protected
+    procedure Write(const AStream: TStream); override;
+  public
+    constructor Create(Const ADocument : TPDFDocument; const AX, AY: TPDFFloat; const AText: UTF8String; const AFontIndex: integer); overload;
+    destructor Destroy; override;
+    Property X : TPDFFloat Read FX Write FX;
+    Property Y : TPDFFloat Read FY Write FY;
+    Property Text : TPDFUTF8String Read FString;
+    property FontIndex: integer read FFontIndex;
+  end;
+
+
+  TPDFLineSegment = class(TPDFDocumentObject)
+  private
+    FWidth: TPDFFloat;
+    P1, p2: TPDFCoord;
+  protected
+    procedure Write(const AStream: TStream); override;
+  public
+    Class Function Command(APos : TPDFCoord) : String;
+    Class Function Command(APos1,APos2 : TPDFCoord) : String;
+    constructor Create(Const ADocument : TPDFDocument; const AWidth, X1,Y1, X2,Y2: TPDFFloat);overload;
+  end;
+
+
+  TPDFRectangle = class(TPDFDocumentObject)
+  private
+    FWidth: TPDFFloat;
+    FTopLeft: TPDFCoord;
+    FDimensions: TPDFCoord;
+    FFill: Boolean;
+    FStroke: Boolean;
+  protected
+    procedure Write(const AStream: TStream); override;
+  public
+    constructor Create(const ADocument: TPDFDocument; const APosX, APosY, AWidth, AHeight, ALineWidth: TPDFFloat; const AFill, AStroke: Boolean);overload;
+  end;
+
+
+  TPDFCurveC = class(TPDFDocumentObject)
+  private
+    FP1,FP2,FP3: TPDFCoord;
+    FWidth: TPDFFloat;
+    FStroke: Boolean;
+  protected
+    Class Function Command(Const X1,Y1,X2,Y2,X3,Y3 : TPDFFloat) : String; overload;
+    Class Function Command(Const AP1,AP2,AP3: TPDFCoord) : String; overload;
+    procedure Write(const AStream: TStream); override;
+  public
+    constructor Create(Const ADocument : TPDFDocument; const X1,Y1,X2,Y2,X3,Y3,AWidth : TPDFFloat;AStroke: Boolean = True);overload;
+    constructor Create(Const ADocument : TPDFDocument; const AP1,AP2,AP3 : TPDFCoord; AWidth: TPDFFloat; AStroke: Boolean = True);overload;
+  end;
+
+
+  TPDFCurveV = class(TPDFDocumentObject)
+  private
+    FP2,FP3: TPDFCoord;
+    FWidth: TPDFFloat;
+    FStroke : Boolean;
+  protected
+    procedure Write(const AStream: TStream); override;
+  public
+    constructor Create(Const ADocument : TPDFDocument; const X2,Y2,X3,Y3,AWidth : TPDFFloat;AStroke: Boolean = True);overload;
+    constructor Create(Const ADocument : TPDFDocument; const AP2,AP3 : TPDFCoord; AWidth: TPDFFloat;AStroke: Boolean = True);overload;
+  end;
+
+
+  TPDFCurveY = class(TPDFDocumentObject)
+  private
+    FP1,FP3: TPDFCoord;
+    FWidth: TPDFFloat;
+    FStroke : Boolean;
+  protected
+    procedure Write(const AStream: TStream); override;
+  public
+    constructor Create(Const ADocument : TPDFDocument; const X1,Y1,X3,Y3,AWidth : TPDFFloat;AStroke: Boolean = True);overload;
+    constructor Create(Const ADocument : TPDFDocument; const AP1,AP3 : TPDFCoord; AWidth: TPDFFloat;AStroke: Boolean = True);overload;
+  end;
+
+
+  TPDFEllipse = class(TPDFDocumentObject)
+  private
+    FCenter,
+    FDimensions: TPDFCoord;
+    FFill : Boolean;
+    FStroke : Boolean;
+    FLineWidth : TPDFFloat;
+  protected
+    procedure Write(const AStream: TStream); override;
+  public
+    constructor Create(Const ADocument : TPDFDocument; const APosX, APosY, AWidth, AHeight, ALineWidth: TPDFFloat; const AFill : Boolean = True; AStroke: Boolean = True);overload;
+  end;
+
+
+  TPDFSurface = class(TPDFObject)
+  private
+    FPoints: TPDFCoordArray;
+    FFill : Boolean;
+    FClose : Boolean;
+  protected
+    procedure Write(const AStream: TStream); override;
+  public
+    constructor Create(Const ADocument : TPDFDocument; const APoints: TPDFCoordArray; AClose : Boolean; AFill : Boolean = True); overload;
+  end;
+
+
+  TPDFImage = class(TPDFDocumentObject)
+  private
+    FNumber: integer;
+    FPos: TPDFCoord;
+    FWidth: integer;
+    FHeight: integer;
+  protected
+    procedure Write(const AStream: TStream); override;
+  public
+    constructor Create(Const ADocument : TPDFDocument; const ALeft, ABottom: TPDFFloat; AWidth, AHeight, ANumber: integer); overload;
+  end;
+
+
+  TPDFLineStyle = class(TPDFObject)
+  private
+    FStyle: TPDFPenStyle;
+    FPhase: integer;
+  protected
+    procedure Write(const AStream: TStream);override;
+  public
+    constructor Create(Const ADocument : TPDFDocument; AStyle: TPDFPenStyle; APhase: integer); overload;
+  end;
+
+
+  TPDFColor = class(TPDFDocumentObject)
+  private
+    FRed: string;
+    FGreen: string;
+    FBlue: string;
+    FStroke: Boolean;
+  protected
+    procedure Write(const AStream: TStream);override;
+  public
+    constructor Create(Const ADocument : TPDFDocument; const AStroke: Boolean; AColor: TARGBColor); overload;
+  end;
+
+
+  TPDFDictionaryItem = class(TPDFObject)
+  private
+    FKey: TPDFName;
+    FObj: TPDFObject;
+  protected
+    procedure Write(const AStream: TStream);override;
+  public
+    constructor Create(Const ADocument : TPDFDocument; const AKey: string; const AValue: TPDFObject);
+    destructor Destroy; override;
+    Property Value : TPDFObject Read FObj;
+  end;
+
+
+  TPDFDictionary = class(TPDFDocumentObject)
+  private
+    FElements: TFPObjectList; // list of TPDFDictionaryItem
+    function GetE(AIndex : Integer): TPDFDictionaryItem;
+    function GetEC: Integer;
+    function GetV(AIndex : Integer): TPDFObject;
+  protected
+    procedure AddElement(const AKey: string; const AValue: TPDFObject);
+    procedure AddName(const AKey,AName : String);
+    procedure AddInteger(const AKey : String; AInteger : Integer);
+    procedure AddReference(const AKey : String; AReference : Integer);
+    procedure AddString(const AKey, AString : String);
+    function IndexOfKey(const AValue: string): integer;
+    procedure Write(const AStream: TStream); override;
+    procedure WriteDictionary(const AObject: integer; const AStream: TStream);
+  public
+    constructor Create(Const ADocument : TPDFDocument); override;
+    destructor Destroy; override;
+    Function LastElement : TPDFDictionaryItem;
+    Function LastValue : TPDFObject;
+    Function FindElement(Const AKey : String) : TPDFDictionaryItem;
+    Function FindValue(Const AKey : String) : TPDFObject;
+    Function ElementByName(Const AKey : String) : TPDFDictionaryItem;
+    Function ValueByName(Const AKey : String) : TPDFObject;
+    Property Elements[AIndex : Integer] : TPDFDictionaryItem Read GetE;
+    Property Values[AIndex : Integer] : TPDFObject Read GetV;
+    Property ElementCount : Integer Read GetEC;
+  end;
+
+
+  TPDFXRef = class(TPDFObject)
+  private
+    FOffset: integer;
+    FDict: TPDFDictionary;
+    FStream: TPDFStream;
+  protected
+    procedure Write(const AStream: TStream);override;
+  public
+    constructor Create(Const ADocument : TPDFDocument); override;
+    destructor Destroy; override;
+    property Offset: integer read FOffset write FOffset;
+    Property Dict : TPDFDictionary Read FDict;
+  end;
+
+
+  TPDFInfos = Class(TPersistent)
+  private
+    FApplicationName: String;
+    FAuthor: String;
+    FCreationDate: TDateTime;
+    FProducer: String;
+    FTitle: String;
+  public
+    constructor Create; virtual;
+    Property Author : String Read FAuthor Write FAuthor;
+    Property Title : String Read FTitle Write FTitle;
+    Property ApplicationName : String Read FApplicationName Write FApplicationName;
+    Property Producer : String Read FProducer Write FProducer;
+    Property CreationDate : TDateTime Read FCreationDate Write FCreationDate;
+  end;
+
+
+  { When the WriteXXX() and DrawXXX() methods specify coordinates, they do it as
+    per the PDF specification, from the bottom-left. }
+  TPDFPage = Class(TPDFDocumentObject)
+  private
+    FObjects : TObjectList;
+    FOrientation: TPDFPaperOrientation;
+    FPaper: TPDFPaper;
+    FPaperType: TPDFPaperType;
+    FFontIndex: integer;
+    FUnitOfMeasure: TPDFUnitOfMeasure;
+    FMatrix: TPDFMatrix;
+    procedure CalcPaperSize;
+    function GetO(AIndex : Integer): TPDFObject;
+    function GetObjectCount: Integer;
+    procedure SetOrientation(AValue: TPDFPaperOrientation);
+    procedure SetPaperType(AValue: TPDFPaperType);
+    procedure AddTextToLookupLists(AText: UTF8String);
+    procedure SetUnitOfMeasure(AValue: TPDFUnitOfMeasure);
+    procedure AdjustMatrix;
+  protected
+    procedure DoUnitConversion(var APoint: TPDFCoord); virtual;
+  Public
+    Constructor Create(Const ADocument : TPDFDocument); override;
+    Destructor Destroy; override;
+    Procedure AddObject(AObject : TPDFObject);
+    // Commands. These will create objects in the objects list of the page.
+    Procedure SetFont(AFontIndex : Integer; AFontSize : Integer);
+    // used for stroking and nonstroking colors - purpose determined by the AStroke parameter
+    Procedure SetColor(AColor : TARGBColor; AStroke : Boolean = True);
+    Procedure SetPenStyle(AStyle : TPDFPenStyle);
+    Procedure WriteText(X, Y: TPDFFloat; AText : String); overload;
+    Procedure WriteText(APos: TPDFCoord; AText : String); overload;
+    Procedure WriteUTF8Text(X, Y: TPDFFloat; AText : UTF8String);
+    procedure DrawLine(X1, Y1, X2, Y2, ALineWidth : TPDFFloat); overload;
+    procedure DrawLine(APos1: TPDFCoord; APos2: TPDFCoord; ALineWidth: TPDFFloat); overload;
+    Procedure DrawLineStyle(X1, Y1, X2, Y2: TPDFFloat; AStyle: Integer); overload;
+    Procedure DrawLineStyle(APos1: TPDFCoord; APos2: TPDFCoord; AStyle: Integer); overload;
+    { X, Y coordinates are the bottom-left coordinate of the rectangle. The W and H parameters are in the UnitOfMeasure units. }
+    Procedure DrawRect(const X, Y, W, H, ALineWidth: TPDFFloat; const AFill, AStroke : Boolean); overload;
+    Procedure DrawRect(const APos: TPDFCoord; const W, H, ALineWidth: TPDFFloat; const AFill, AStroke : Boolean); overload;
+    { X, Y coordinates are the bottom-left coordinate of the image. AWidth and AHeight are in image pixels. }
+    Procedure DrawImage(const X, Y: TPDFFloat; const AWidth, AHeight, ANumber: integer); overload;
+    Procedure DrawImage(const APos: TPDFCoord; const AWidth, AHeight, ANumber: integer); overload;
+    { X, Y coordinates are the bottom-left coordinate of the boundry rectangle.
+      The W and H parameters are in the UnitOfMeasure units. A negative AWidth will
+      cause the ellpise to draw to the left of the origin point. }
+    Procedure DrawEllipse(const APosX, APosY, AWidth, AHeight, ALineWidth: TPDFFloat; const AFill: Boolean = True; AStroke: Boolean = True); overload;
+    Procedure DrawEllipse(const APos: TPDFCoord; const AWidth, AHeight, ALineWidth: TPDFFloat; const AFill: Boolean = True; AStroke: Boolean = True); overload;
+    { This returns the paper height, converted to whatever UnitOfMeasure is set too }
+    function GetPaperHeight: TPDFFloat;
+    Function HasImages : Boolean;
+    // Quick settings for Paper.
+    Property PaperType : TPDFPaperType Read FPaperType Write SetPaperType default ptA4;
+    Property Orientation : TPDFPaperOrientation Read FOrientation Write SetOrientation;
+    // Set this if you want custom paper size.
+    Property Paper : TPDFPaper Read FPaper Write FPaper;
+    // Unit of Measure - how the PDF Page should convert the coordinates and dimensions
+    property UnitOfMeasure: TPDFUnitOfMeasure read FUnitOfMeasure write SetUnitOfMeasure default uomMillimeters;
+    Property ObjectCount: Integer Read GetObjectCount;
+    Property Objects[AIndex : Integer] : TPDFObject Read GetO; default;
+    // returns the last used FontIndex used in SetFont()
+    property FontIndex: integer read FFontIndex;
+    { A 3x3 matrix used to translate the PDF Cartesian coordinate system to an Image coordinate system. }
+    property Matrix: TPDFMatrix read FMatrix write FMatrix;
+  end;
+
+
+  TPDFSection = Class(TCollectionItem)
+  private
+    FTitle: String;
+    FPages : TFPList; // not owned
+    function GetP(AIndex : Integer): TPDFPage;
+    function GetP: INteger;
+  Public
+    Destructor Destroy; override;
+    Procedure AddPage(APage : TPDFPage);
+    Property Title : String Read FTitle Write FTitle;
+    Property Pages[AIndex : Integer] : TPDFPage Read GetP;
+    Property PageCount : INteger Read GetP;
+  end;
+
+
+  TPDFSectionList = Class(TCollection)
+  private
+    function GetS(AIndex : Integer): TPDFSection;
+  Public
+    Function AddSection : TPDFSection;
+    Property Section[AIndex : Integer] : TPDFSection Read GetS; Default;
+  end;
+
+
+  TTextDictionary = class(TObject)
+  private
+    FChar: UnicodeChar;
+    FCodePoint: AnsiString;
+  public
+    property Char: UnicodeChar read FChar write FChar;
+    property CodePoint: AnsiString read FCodePoint write FCodePoint;
+  end;
+
+  TPDFFont = CLass(TCollectionItem)
+  private
+    FColor: TARGBColor;
+    FName: String;
+    FFontFile: string;
+    { stores lookup code for each letter of text used and associated 2-byte Unicode code point }
+    FDictionary: TObjectList;
+  public
+    constructor Create(ACollection: TCollection); override;
+    destructor  Destroy; override;
+    function FindIndexOf(const AValue: UnicodeChar): integer;
+    Property FontFile: string read FFontFile write FFontFile;
+    Property Name : String Read FName Write FName;
+    Property Color : TARGBColor Read FColor Write FColor;
+    property Dictionary: TObjectList read FDictionary;
+  end;
+
+
+  TPDFFontDefs = Class(TCollection)
+  private
+    function GetF(AIndex : Integer): TPDFFont;
+  Public
+    Function AddFontDef : TPDFFont;
+    Property FontDefs[AIndex : Integer] : TPDFFont Read GetF; Default;
+  end;
+
+
+  TPDFPages = Class(TPDFDocumentObject)
+  private
+    FList : TFPObjectList;
+    function GetP(AIndex : Integer): TPDFPage;
+  public
+    Destructor Destroy; override;
+    Function AddPage : TPDFPage;
+    Property Pages[AIndex : Integer] : TPDFPage Read GetP; Default;
+  end;
+
+
+  TPDFImageItem = Class(TCollectionItem)
+  private
+    FImage: TFPCustomImage;
+    FOwnsImage: Boolean;
+    FStreamed: TBytes;
+    FWidth,FHeight : Integer;
+    function GetHeight: Integer;
+    function GetStreamed: TBytes;
+    function GetWidth: Integer;
+    procedure SetImage(AValue: TFPCustomImage);
+    procedure SetStreamed(AValue: TBytes);
+  Public
+    Destructor Destroy; override;
+    Procedure CreateStreamedData;
+    Function WriteImageStream(AStream: TStream): int64; virtual;
+    function Equals(AImage: TFPCustomImage): boolean; reintroduce;
+    Property Image : TFPCustomImage Read FImage Write SetImage;
+    Property StreamedData : TBytes Read GetStreamed Write SetStreamed;
+    Property OwnsImage : Boolean Read FOwnsImage Write FOwnsImage;
+    Property Width : Integer Read GetWidth;
+    Property Height : Integer Read GetHeight;
+  end;
+
+
+  TPDFImages = CLass(TCollection)
+  private
+    function GetI(AIndex : Integer): TPDFImageItem;
+  Public
+    Function AddImageItem : TPDFImageItem;
+    Function AddFromFile(Const AFileName : String; KeepImage : Boolean = False): Integer;
+    Property Images[AIndex : Integer] : TPDFImageItem Read GetI; default;
+  end;
+
+
+  TFontDef = record
+    FType: string;
+    FName: string;
+    FAscent: string;
+    FDescent: string;
+    FCapHeight: string;
+    FFlags: string;
+    FFontBBox: string;
+    FItalicAngle: string;
+    FStemV: string;
+    FMissingWidth: string;
+    FEncoding: string;
+    FFile: string;
+    FOriginalSize: string;
+    FDiffs: WideString;
+    FCharWidth: WideString;
+  end;
+
+
+  TPDFToUnicode = class(TPDFDocumentObject)
+  private
+    FFontDef: TFontDef;
+    FEmbeddedFontNum: integer;
+  protected
+    procedure Write(const AStream: TStream);override;
+  public
+    constructor Create(const ADocument: TPDFDocument; const AEmbeddedFontNum: integer; AFontDef : TFontDef); overload;
+    property FontDef: TFontDef read FFontDef;
+    property EmbeddedFontNum: integer read FEmbeddedFontNum;
+  end;
+
+
+
+  TPDFLineStyleDef = Class(TCollectionItem)
+  private
+    FColor: TARGBColor;
+    FLineWidth: TPDFFloat;
+    FPenStyle: TPDFPenStyle;
+  Published
+    Property LineWidth : TPDFFloat Read FLineWidth Write FLineWidth;
+    Property Color : TARGBColor Read FColor Write FColor Default clBlack;
+    Property PenStyle : TPDFPenStyle Read FPenStyle Write FPenStyle Default ppsSolid;
+  end;
+
+
+  TPDFLineStyleDefs = Class(TCollection)
+  private
+    function GetI(AIndex : Integer): TPDFLineStyleDef;
+  Public
+    Function AddLineStyleDef : TPDFLineStyleDef;
+    Property Defs[AIndex : Integer] : TPDFLineStyleDef Read GetI; Default;
+  end;
+
+
+  TPDFDocument = class(TComponent)
+  private
+    FCatalogue: integer;
+    FCurrentColor: string;
+    FCurrentWidth: string;
+    FDefaultOrientation: TPDFPaperOrientation;
+    FDefaultPaperType: TPDFPaperTYpe;
+    FFontDirectory: string;
+    FFontFiles: TStrings;
+    FFonts: TPDFFontDefs;
+    FImages: TPDFImages;
+    FInfos: TPDFInfos;
+    FLineStyleDefs: TPDFLineStyleDefs;
+    FObjectCount: Integer;
+    FOptions: TPDFOptions;
+    FPages: TPDFPages;
+    FPreferences: Boolean;
+    FPageLayout: TPDFPageLayout;
+    FSections: TPDFSectionList;
+    FTrailer: TPDFDictionary;
+    FZoomValue: string;
+    FGlobalXRefs: TFPObjectList; // list of TPDFXRef
+    function GetX(AIndex : Integer): TPDFXRef;
+    function GetXC: Integer;
+    procedure SetFontFiles(AValue: TStrings);
+    procedure SetFonts(AValue: TPDFFontDefs);
+    procedure SetInfos(AValue: TPDFInfos);
+    procedure SetLineStyles(AValue: TPDFLineStyleDefs);
+  protected
+    // Returns next prevoutline
+    function CreateSectionOutLine(Const SectionIndex,OutLineRoot,ParentOutLine,NextSect,PrevSect : Integer): Integer; virtual;
+    Function CreateSectionsOutLine : Integer; virtual;
+    Function CreateSectionPageOutLine(Const S: TPDFSection; Const PageOutLine, PageIndex, NewPage,  ParentOutline, NextOutline, PrevOutLine : Integer) : Integer;virtual;
+    procedure AddFontNameToPages(const AName: String; ANum : Integer);
+    procedure WriteXRefTable(const AStream: TStream);
+    procedure WriteObject(const AObject: integer; const AStream: TStream);
+    procedure CreateRefTable;virtual;
+    procedure CreateTrailer;virtual;
+    procedure CreateFontEntries; virtual;
+    procedure CreateImageEntries; virtual;
+    function CreateContentsEntry: integer;virtual;
+    function CreateCatalogEntry: integer;virtual;
+    procedure CreateInfoEntry;virtual;
+    procedure CreatePreferencesEntry;virtual;
+    function CreatePagesEntry(Parent: integer): integer;virtual;
+    function CreatePageEntry(Parent, PageNum: integer): integer;virtual;
+    function CreateOutlines: integer;virtual;
+    function CreateOutlineEntry(Parent, SectNo, PageNo: integer; ATitle: string): integer;virtual;
+    function LoadFont(AFont: TPDFFont; Out FontDef : TFontDef): string;
+    procedure CreateStdFont(EmbeddedFontName: string; EmbeddedFontNum: integer);virtual;
+    procedure CreateTTFFont(const EmbeddedFontNum: integer; FontDef : TFontDef);virtual;
+    procedure CreateTp1Font(const EmbeddedFontNum: integer);virtual;
+    procedure CreateFontDescriptor(const EmbeddedFontNum: integer; FontDef : TFontDef);virtual;
+    procedure CreateToUnicode(const EmbeddedFontNum: integer; FontDef : TFontDef);virtual;
+    procedure CreateFontWidth(FontDef : TFontDef);virtual;
+    procedure CreateFontFileEntry(const EmbeddedFontNum: integer;FontDef : TFontDef);virtual;
+    procedure CreateImageEntry(ImgWidth, ImgHeight, NumImg: integer);virtual;
+    procedure CreatePageStream(APage : TPDFPage; PageNum: integer);
+    Function CreateGlobalXRef: TPDFXRef;
+    Function AddGlobalXRef(AXRef : TPDFXRef) : Integer;
+    function IndexOfGlobalXRef(const AValue: string): integer;
+    Function FindGlobalXRef(Const AName : String) : TPDFXRef;
+    Function GlobalXRefByName(Const AName : String) : TPDFXRef;
+    Property GlobalXRefs[AIndex : Integer] : TPDFXRef Read GetX;
+    Property GlobalXRefCount : Integer Read GetXC;
+    Property CurrentColor: string Read FCurrentColor Write FCurrentColor;
+    Property CurrentWidth: string Read FCurrentWidth Write FCurrentWidth;
+  public
+    constructor Create(AOwner : TComponent); override;
+    procedure StartDocument;
+    destructor Destroy; override;
+    procedure SaveToStream(const AStream: TStream);
+    // Create objects, owned by this document.
+    Function CreateEmbeddedFont(AFontIndex, AFontSize : Integer) : TPDFEmbeddedFont;
+    Function CreateText(X,Y : TPDFFloat; AText : String) : TPDFText;
+    Function CreateUTF8Text(X,Y : TPDFFloat; AText : UTF8String; const AFontIndex: integer) : TPDFUTF8Text;
+    Function CreateRectangle(const X,Y,W,H, ALineWidth: TPDFFloat; const AFill, AStroke: Boolean) : TPDFRectangle;
+    Function CreateColor(AColor : TARGBColor; AStroke : Boolean) : TPDFColor;
+    Function CreateBoolean(AValue : Boolean) : TPDFBoolean;
+    Function CreateInteger(AValue : Integer) : TPDFInteger;
+    Function CreateReference(AValue : Integer) : TPDFReference;
+    Function CreateString(Const AValue : String) : TPDFString;
+    Function CreateUTF8String(Const AValue : UTF8String; const AFontIndex: integer) : TPDFUTF8String;
+    Function CreateLineStyle(APenStyle: TPDFPenStyle) : TPDFLineStyle;
+    Function CreateName(AValue : String) : TPDFName;
+    Function CreateStream(OwnsObjects : Boolean = True) : TPDFStream;
+    Function CreateDictionary : TPDFDictionary;
+    Function CreateXRef : TPDFXRef;
+    Function CreateArray : TPDFArray;
+    Function CreateImage(const ALeft, ABottom: TPDFFloat; AWidth, AHeight, ANumber: integer) : TPDFImage;
+    Function AddFont(AName : String; AColor : TARGBColor = clBlack) : Integer; overload;
+    Function AddFont(AFontFile: String; AName : String; AColor : TARGBColor = clBlack) : Integer; overload;
+    Function AddLineStyleDef(ALineWidth : TPDFFloat; AColor : TARGBColor = clBlack; APenStyle : TPDFPenStyle = ppsSolid) : Integer;
+    Property Options : TPDFOptions Read FOptions Write FOPtions;
+    property PageLayout: TPDFPageLayout read FPageLayout write FPageLayout default lSingle;
+    Property Infos : TPDFInfos Read FInfos Write SetInfos;
+    Property Fonts : TPDFFontDefs Read FFonts Write SetFonts;
+    Property LineStyles : TPDFLineStyleDefs Read FLineStyleDefs Write SetLineStyles;
+    Property Pages : TPDFPages Read FPages;
+    Property Images : TPDFImages Read FImages;
+    Property Catalogue: integer Read FCatalogue;
+    Property Trailer: TPDFDictionary Read FTrailer;
+    Property FontFiles : TStrings Read FFontFiles Write SetFontFiles;
+    Property FontDirectory: string Read FFontDirectory Write FFontDirectory;
+    Property Sections : TPDFSectionList Read FSections;
+    Property DefaultPaperType : TPDFPaperTYpe Read FDefaultPaperType Write FDefaultPaperType;
+    Property DefaultOrientation : TPDFPaperOrientation Read FDefaultOrientation Write FDefaultOrientation;
+    Property ObjectCount : Integer Read FObjectCount;
+  end;
+
+
+const
+  CRLF        =#13#10;
+  PDF_VERSION ='%PDF-1.3';
+  PDF_FILE_END = '%%EOF';
+  PDF_MAX_GEN_NUM = 65535;
+  PDF_UNICODE_HEADER = 'FEFF001B%s001B';
+  PDF_LANG_STRING = 'en';
+
+  { Info from http://www.papersizes.org/a-sizes-all-units.htm }
+  PDFPaperSizes : Array[TPDFPaperType,0..1] of Integer = (
+    // Height,Width (units in pixels (or Points))
+      (0,0),          // ptCustom
+      (842,595),      // ptA4
+      (595,420),      // ptA5
+      (792,612),      // ptLetter
+      (1008,612),     // ptLegal
+      (756,522),      // ptExecutive
+      (684,297),      // ptComm10
+      (540,279),      // ptMonarch
+      (624,312),      // ptDL
+      (649,459),      // ptC5
+      (709,499)       // ptB5
+    );
+
+  PDFPaperPrintables : Array[TPDFPaperType,0..3] of Integer = (
+     // Top,Left,Right,Bottom (units in pixels)
+      (0,0,0,0),          // ptCustom
+      (10,11,586,822),    // ptA4
+      (10,11,407,588),    // ptA5
+      (13,13,599,780),    // ptLetter
+      (13,13,599,996),    // ptLegal
+      (14,13,508,744),    // ptExecutive
+      (13,13,284,672),    // ptComm10
+      (13,13,266,528),    // ptMonarch
+      (14,13,297,611),    // ptDL
+      (13,13,446,637),    // ptC5
+      (14,13,485,696)     // ptB5
+    );
+
+  PageLayoutNames : Array[TPDFPageLayout] of String
+                  = ('SinglePage','TwoColumnLeft','OneColumn');
+
+
+// Helper procedures - made them global for unit testing purposes
+procedure CompressStream(AFrom: TStream; ATo: TStream; ACompressLevel: TCompressionLevel = clDefault; ASkipHeader: boolean = False);
+procedure CompressString(const AFrom: string; var ATo: string);
+procedure DecompressStream(AFrom: TStream; ATo: TStream);
+
+function mmToPDF(mm: single): TPDFFloat;
+function cmToPDF(cm: single): TPDFFloat;
+function InchesToPDF(Inches: single): TPDFFloat;
+
+implementation
+
+uses
+  fpparsettf;
+
+Resourcestring
+  rsErrReportFontFileMissing = 'Font File "%s" does not exist.';
+  SErrDictElementNotFound = 'Error: Dictionary element "%s" not found.';
+  SerrInvalidSectionPage = 'Error: Invalid section page index.';
+  SErrNoGlobalDict = 'Error: no global XRef named "%s".';
+  SErrInvalidPageIndex = 'Invalid page index: %d';
+
+Const
+  // TODO: we should improve this to take into account the line width
+  cPenStyleBitmasks: array[TPDFPenStyle] of string = (
+    '',               // ppsSolid
+    '5 3',            // ppsDash (dash space ...)
+    '1 3',            // ppsDot (dot space ...)
+    '5 3 1 3',        // ppsDashDot (dash space dot space ...)
+    '5 3 1 3 1 3'     // ppsDashDotDot (dash space dot space dot space ...)
+    );
+
+const
+  cInchToMM = 25.4;
+  cInchToCM = 2.54;
+  cDefaultDPI = 72;
+
+  // mm = (pixels * 25.4) / dpi
+  // pixels = (mm * dpi) / 25.4
+  // cm = ((pixels * 25.4) / dpi) / 10
+
+
+// These symbols must be preceded by a slash:  %, (, ), <, >, [, ], {, }, / and #
+function InsertEscape(const AValue: string): string;
+var
+  S: string;
+begin
+  Result:='';
+  S:=AValue;
+  if Pos('\', S) > 0 then
+    S:=AnsiReplaceStr(S, '\', '\\');
+  if Pos('(', S) > 0 then
+    S:=AnsiReplaceStr(S, '(', '\(');
+  if Pos(')', S) > 0 then
+    S:=AnsiReplaceStr(S, ')', '\)');
+  Result:=S;
+end;
+
+function DateToPdfDate(const ADate: TDateTime): string;
+begin
+  Result:=FormatDateTime('"D:"yyyymmddhhnnss', ADate);
+end;
+
+function FormatPDFInt(const Value: integer; PadLen: integer): string;
+begin
+  Result:=IntToStr(Value);
+  Dec(PadLen,Length(Result));
+  if PadLen>0 then
+    Result:=StringOfChar('0',Padlen)+Result;
+end;
+
+function IntToStrZeros(const AValue, ADigits: integer): string;
+begin
+   result := SysUtils.Format('%.*d', [ADigits, AValue]) ;
+end;
+
+procedure CompressStream(AFrom: TStream; ATo: TStream; ACompressLevel: TCompressionLevel = clDefault; ASkipHeader: boolean = False);
+var
+  c: TCompressionStream;
+begin
+  if AFrom.Size = 0 then
+  begin
+    ATo.Size := 0;
+    Exit; //==>
+  end;
+
+  c := TCompressionStream.Create(ACompressLevel, ATo, ASkipHeader);
+  try
+    AFrom.Position := 0;
+    c.CopyFrom(AFrom, AFrom.Size);
+    c.Flush;
+  finally
+    c.Free;
+  end;
+end;
+
+procedure CompressString(const AFrom: string; var ATo: string);
+var
+  lStreamFrom : TStringStream;
+  lStreamTo  : TStringStream;
+begin
+  { TODO : Possible improvement would be to perform this compression directly on
+           the string as a buffer, and not go through the stream stage. }
+  lStreamFrom := TStringStream.Create(AFrom);
+  try
+    lStreamTo  := TStringStream.Create('');
+    try
+      lStreamFrom.Position := 0;
+      lStreamTo.Size := 0;
+      CompressStream(lStreamFrom, lStreamTo);
+      ATo  := lStreamTo.DataString;
+    finally
+      lStreamTo.Free;
+    end;
+  finally
+    lStreamFrom.Free;
+  end;
+end;
+
+procedure DecompressStream(AFrom: TStream; ATo: TStream);
+
+{$IFDEF VER2_6}
+{$DEFINE NOHEADERWORKADOUND}
+{$ENDIF}
+{$IFDEF VER3_0}
+{$DEFINE NOHEADERWORKADOUND}
+{$ENDIF}
+
+Const
+  BufSize = 1024; // 1K
+
+var
+  d: TDecompressionStream;
+  I,count : Integer;
+  Buffer : Array[0..BufSize-1] of byte;
+
+begin
+  if AFrom.Size = 0 then
+  begin
+    ATo.Size := 0;
+    Exit; //==>
+  end;
+
+  AFrom.Position := 0;
+  AFrom.Seek(0,soFromEnd);
+{$IFDEF NOHEADERWORKADOUND}
+  // Work around a paszlib bug, FPC bugtracker 26827
+  I:=0;
+  AFrom.Write(I,SizeOf(I));
+  AFrom.Position:=0;
+{$ENDIF}
+  D:=TDecompressionStream.Create(AFrom, False);
+  try
+    repeat
+       Count:=D.Read(Buffer,BufSize);
+       ATo.WriteBuffer(Buffer,Count);
+     until (Count<BufSize);
+  finally
+    d.Free;
+  end;
+end;
+
+function mmToPDF(mm: single): TPDFFloat;
+begin
+  Result := mm * (cDefaultDPI / cInchToMM);
+end;
+
+function PDFtoMM(APixels: TPDFFloat): single;
+begin
+  Result := (APixels * cInchToMM) / cDefaultDPI;
+end;
+
+function cmToPDF(cm: single): TPDFFloat;
+begin
+  Result := cm *(cDefaultDPI / cInchToCM);
+end;
+
+function PDFtoCM(APixels: TPDFFloat): single;
+begin
+  Result := (APixels * cInchToCM) / cDefaultDPI;
+end;
+
+function InchesToPDF(Inches: single): TPDFFloat;
+begin
+  Result := Inches * cDefaultDPI;
+end;
+
+function PDFtoInches(APixels: TPDFFloat): single;
+begin
+  Result := APixels / cDefaultDPI;
+end;
+
+{ TPDFInfos }
+
+constructor TPDFInfos.Create;
+begin
+  inherited Create;
+  FProducer := 'fpGUI Toolkit 0.8';
+end;
+
+{ TPDFMatrix }
+
+function TPDFMatrix.Transform(APoint: TPDFCoord): TPDFCoord;
+begin
+  Result.x := _00 * APoint.x + _20;
+  Result.y := _11 * APoint.y + _21;
+end;
+
+function TPDFMatrix.Transform(X, Y: TPDFFloat): TPDFCoord;
+begin
+  Result.x := _00 * X + _20;
+  Result.y := _11 * Y + _21;
+end;
+
+function TPDFMatrix.ReverseTransform(APoint: TPDFCoord): TPDFCoord;
+begin
+  Result.x := (APoint.x - _20) / _00;
+  Result.y := (APoint.y - _21) / _11;
+end;
+
+{ TPDFFont }
+
+constructor TPDFFont.Create(ACollection: TCollection);
+begin
+  inherited Create(ACollection);
+  FDictionary := TObjectList.create;
+end;
+
+destructor TPDFFont.Destroy;
+begin
+  FDictionary.Free;
+  inherited Destroy;
+end;
+
+function TPDFFont.FindIndexOf(const AValue: UnicodeChar): integer;
+var
+  i: integer;
+begin
+  result := -1; // default to not found
+  for i := 0 to FDictionary.Count-1 do
+  begin
+    if TTextDictionary(FDictionary[i]).Char = AValue then
+    begin
+      result := i;
+      exit;
+    end;
+  end;
+end;
+
+{ TPDFMoveTo }
+
+class function TPDFMoveTo.Command(APos: TPDFCoord): String;
+
+begin
+  Result:=Command(APos.X,APos.Y);
+end;
+
+class function TPDFMoveTo.Command(AX, AY: TPDFFloat): String;
+begin
+  Result:=FloatStr(AX)+' '+FloatStr(AY)+' m'+CRLF;
+end;
+
+procedure TPDFMoveTo.Write(const AStream: TStream);
+begin
+  WriteString(Command(FPos),AStream);
+end;
+
+constructor TPDFMoveTo.Create(const ADocument: TPDFDocument; const AX,
+  AY: TPDFFloat);
+begin
+  Inherited Create(ADocument);
+  FPos.X:=AX;
+  FPos.Y:=AY;
+end;
+
+constructor TPDFMoveTo.Create(const ADocument: TPDFDocument;
+  const APos: TPDFCoord);
+begin
+  Inherited Create(ADocument);
+  FPos:=APos;
+end;
+
+{ TPDFEllipse }
+
+procedure TPDFEllipse.Write(const AStream: TStream);
+Var
+  X,Y,W2,H2,WS,HS : TPDFFloat;
+begin
+  if FStroke then
+    SetWidth(FLineWidth, AStream);
+
+  X:=FCenter.X;
+  Y:=FCenter.Y;
+  W2:=FDimensions.X/2;
+  H2:=FDimensions.Y/2;
+  WS:=W2*11/20;
+  HS:=H2*11/20;
+  // Starting point
+  WriteString(TPDFMoveTo.Command(X,Y+H2),AStream);
+  WriteString(TPDFCurveC.Command(X, Y+H2-HS, X+W2-WS, Y, X+W2, Y),AStream);
+  WriteString(TPDFCurveC.Command(X+W2+WS, Y, X+W2*2, Y+H2-HS, X+W2*2, Y+H2),AStream);
+  WriteString(TPDFCurveC.Command(X+W2*2, Y+H2+HS, X+W2+WS, Y+H2*2, X+W2, Y+H2*2),AStream);
+  WriteString(TPDFCurveC.Command(X+W2-WS, Y+H2*2, X, Y+H2+HS, X, Y+H2),AStream);
+
+  if FStroke and FFill then
+    WriteString('b'+CRLF, AStream)
+  else if FFill then
+    WriteString('f'+CRLF, AStream)
+  else if FStroke then
+    WriteString('S'+CRLF, AStream);
+  (*
+  // should we default to this if no stroking or filling is required?
+  else
+    WriteString('n'+CRLF, AStream); // see PDF 1.3 Specification document on page 152
+  *)
+end;
+
+constructor TPDFEllipse.Create(const ADocument: TPDFDocument; const APosX, APosY, AWidth, AHeight,
+  ALineWidth: TPDFFloat; const AFill: Boolean; AStroke: Boolean);
+begin
+  Inherited Create(ADocument);
+  FLineWidth:=ALineWidth;
+  FCenter.X:=APosX;
+  FCenter.Y:=APosY;
+  FDimensions.X:=AWidth;
+  FDimensions.Y:=AHeight;
+  FFill:=AFill;
+  FStroke:=AStroke;
+end;
+
+{ TPDFCurveY }
+
+procedure TPDFCurveY.Write(const AStream: TStream);
+
+begin
+  if FStroke then
+    SetWidth(FWidth,AStream);
+  WriteString(FloatStr(FP1.X)+' '+FloatStr(FP1.Y)+' '+
+              FloatStr(FP3.X)+' '+FloatStr(FP3.Y)+' y'+CRLF,AStream);
+  if FStroke then
+    WriteString('S'+CRLF, AStream);
+end;
+
+constructor TPDFCurveY.Create(const ADocument: TPDFDocument; const X1, Y1, X3,
+  Y3, AWidth: TPDFFloat; AStroke: Boolean);
+begin
+  Inherited Create(ADocument);
+  FP1.X:=X1;
+  FP1.Y:=Y1;
+  FP3.X:=X3;
+  FP3.Y:=Y3;
+  FWidth:=AWidth;
+  FStroke:=AStroke;
+end;
+
+constructor TPDFCurveY.Create(const ADocument: TPDFDocument; const AP1,
+  AP3: TPDFCoord; AWidth: TPDFFloat; AStroke: Boolean);
+begin
+  Inherited Create(ADocument);
+  FP1:=AP1;
+  FP3:=AP3;
+  FWidth:=AWidth;
+  FStroke:=AStroke;
+end;
+
+
+{ TPDFCurveV }
+
+procedure TPDFCurveV.Write(const AStream: TStream);
+
+begin
+  if FStroke then
+    SetWidth(FWidth,AStream);
+  WriteString(FloatStr(FP2.X)+' '+FloatStr(FP2.Y)+' '+
+              FloatStr(FP3.X)+' '+FloatStr(FP3.Y)+' v'+CRLF,AStream);
+  if FStroke then
+    WriteString('S'+CRLF, AStream);
+end;
+
+constructor TPDFCurveV.Create(const ADocument: TPDFDocument; const X2, Y2, X3,
+  Y3, AWidth: TPDFFloat;AStroke: Boolean = True);
+begin
+  Inherited Create(ADocument);
+  FP2.X:=X2;
+  FP2.Y:=Y2;
+  FP3.X:=X3;
+  FP3.Y:=Y3;
+  FWidth:=AWidth;
+  FStroke:=AStroke;
+end;
+
+constructor TPDFCurveV.Create(const ADocument: TPDFDocument; const AP2,
+  AP3: TPDFCoord; AWidth: TPDFFloat;AStroke: Boolean = True);
+begin
+  Inherited Create(ADocument);
+  FP2:=AP2;
+  FP3:=AP3;
+  FWidth:=AWidth;
+  FStroke:=AStroke;
+end;
+
+{ TPDFCurveC }
+
+class function TPDFCurveC.Command(const X1, Y1, X2, Y2, X3, Y3: TPDFFloat
+  ): String;
+begin
+  Result:=FloatStr(X1)+' '+FloatStr(Y1)+' '+
+          FloatStr(X2)+' '+FloatStr(Y2)+' '+
+          FloatStr(X3)+' '+FloatStr(Y3)+' c'+CRLF
+end;
+
+class function TPDFCurveC.Command(const AP1, AP2, AP3: TPDFCoord): String;
+begin
+  Result:=Command(AP1.X,AP1.Y,AP2.X,AP2.Y,AP3.X,AP3.Y);
+end;
+
+procedure TPDFCurveC.Write(const AStream: TStream);
+begin
+  if FStroke then
+    SetWidth(FWidth,AStream);
+  WriteString(Command(FP1,FP2,FP3),AStream);
+  if FStroke then
+    WriteString('S'+CRLF, AStream);
+end;
+
+constructor TPDFCurveC.Create(const ADocument: TPDFDocument; const X1, Y1, X2, Y2, X3, Y3,AWidth: TPDFFloat;AStroke: Boolean = True);
+begin
+  Inherited Create(ADocument);
+  FP1.X:=X1;
+  FP1.Y:=Y1;
+  FP2.X:=X2;
+  FP2.Y:=Y2;
+  FP3.X:=X3;
+  FP3.Y:=Y3;
+  FWidth:=AWidth;
+  FStroke:=AStroke;
+end;
+
+constructor TPDFCurveC.Create(const ADocument: TPDFDocument; const AP1, AP2, AP3: TPDFCoord; AWidth: TPDFFloat;AStroke: Boolean = True);
+begin
+  Inherited Create(ADocument);
+  FP1:=AP1;
+  FP2:=AP2;
+  FP3:=AP3;
+  FWidth:=AWidth;
+  FStroke:=AStroke;
+end;
+
+{ TPDFLineStyleDefs }
+
+function TPDFLineStyleDefs.GetI(AIndex : Integer): TPDFLineStyleDef;
+begin
+  Result:=TPDFLineStyleDef(Items[AIndex]);
+end;
+
+function TPDFLineStyleDefs.AddLineStyleDef: TPDFLineStyleDef;
+begin
+  Result:=Add as TPDFLineStyleDef;
+end;
+
+{ TPDFPages }
+
+function TPDFPages.GetP(AIndex : Integer): TPDFPage;
+begin
+  if Assigned(Flist) then
+    Result:=TPDFPage(FList[Aindex])
+  else
+    Raise EListError.CreateFmt(SErrInvalidPageIndex,[AIndex]);
+end;
+
+destructor TPDFPages.Destroy;
+begin
+  FreeAndNil(FList);
+  inherited Destroy;
+end;
+
+function TPDFPages.AddPage: TPDFPage;
+begin
+  if (Flist=Nil) then
+    FList:=TFPObjectList.Create;
+  Result:=TPDFPage.Create(Document);
+  Flist.Add(Result);
+end;
+
+{ TPDFPage }
+
+function TPDFPage.GetO(AIndex : Integer): TPDFObject;
+begin
+  Result:=TPDFObject(FObjects[AIndex]);
+end;
+
+function TPDFPage.GetObjectCount: Integer;
+begin
+  if FObjects=Nil then
+    Result:=0
+  else
+    Result:=FObjects.Count;
+end;
+
+procedure TPDFPage.SetOrientation(AValue: TPDFPaperOrientation);
+begin
+  if FOrientation=AValue then Exit;
+  FOrientation:=AValue;
+  CalcPaperSize;
+end;
+
+procedure TPDFPage.CalcPaperSize;
+var
+  PP: TPDFPaper;
+  O1, O2: Integer;
+begin
+  if PaperType = ptCustom then
+    Exit;
+  O1 := 0;
+  O2 := 1;
+  if Orientation = ppoLandScape then
+  begin
+    O1 := 1;
+    O2 := 0;
+  end;
+  PP.H:=PDFPaperSizes[PaperType][O1];
+  PP.W:=PDFPaperSizes[PaperType][O2];
+  PP.Printable.T:=PDFPaperPrintables[PaperType][O1];
+  PP.Printable.L:=PDFPaperPrintables[PaperType][O2];
+  PP.Printable.R:=PDFPaperPrintables[PaperType][2+O1];
+  PP.Printable.B:=PDFPaperPrintables[PaperType][2+O2];
+  Paper:=PP;
+end;
+
+procedure TPDFPage.SetPaperType(AValue: TPDFPaperType);
+begin
+  if FPaperType=AValue then Exit;
+  FPaperType:=AValue;
+  CalcPaperSize;
+end;
+
+procedure TPDFPage.AddTextToLookupLists(AText: UTF8String);
+var
+  i: integer;
+  c: UnicodeChar;
+  str: UnicodeString;
+  idx: integer;
+  dict: TTextDictionary;
+begin
+  if AText = '' then
+    Exit;
+  str := UTF8ToUTF16(AText);
+  for i := 1 to Length(str) do
+  begin
+    c := str[i];
+    idx := Document.Fonts[FFontIndex].FindIndexOf(c);
+    if idx = -1 then
+    begin
+      dict := TTextDictionary.Create;
+      dict.Char := c;
+      dict.CodePoint := AnsiString(IntToHex(Word(c), 4));;
+      Document.Fonts[FFontIndex].Dictionary.Add(dict);
+    end;
+  end;
+end;
+
+procedure TPDFPage.DoUnitConversion(var APoint: TPDFCoord);
+begin
+  case FUnitOfMeasure of
+    uomMillimeters:
+      begin
+        APoint.X := mmToPDF(APoint.X);
+        APoint.Y := mmToPDF(APoint.Y);
+      end;
+    uomCentimeters:
+      begin
+        APoint.X := cmToPDF(APoint.X);
+        APoint.Y := cmToPDF(APoint.Y);
+      end;
+    uomInches:
+      begin
+        APoint.X := InchesToPDF(APoint.X);
+        APoint.Y := InchesToPDF(APoint.Y);
+      end;
+  end;
+end;
+
+procedure TPDFPage.SetUnitOfMeasure(AValue: TPDFUnitOfMeasure);
+begin
+  if FUnitOfMeasure = AValue then
+    Exit;
+  FUnitOfMeasure := AValue;
+  AdjustMatrix;
+end;
+
+procedure TPDFPage.AdjustMatrix;
+begin
+  FMatrix._21 := GetPaperHeight;
+end;
+
+constructor TPDFPage.Create(const ADocument: TPDFDocument);
+begin
+  inherited Create(ADocument);
+  FFontIndex := -1;
+  FPaperType := ptA4;
+  FUnitOfMeasure := uomMillimeters;
+  CalcPaperSize;
+  If Assigned(ADocument) then
+  begin
+    PaperType := ADocument.DefaultPaperType;
+    Orientation := ADocument.DefaultOrientation;
+  end;
+
+  FMatrix._00 := 1;
+  FMatrix._20 := 0;
+  FMatrix._11 := -1; // flip coordinates
+  FMatrix._21 := GetPaperHeight;
+end;
+
+destructor TPDFPage.Destroy;
+begin
+  FreeAndNil(FObjects);
+  inherited Destroy;
+end;
+
+procedure TPDFPage.AddObject(AObject: TPDFObject);
+begin
+  if FObjects=Nil then
+    FObjects:=TObjectList.Create;
+  FObjects.Add(AObject);
+end;
+
+procedure TPDFPage.SetFont(AFontIndex: Integer; AFontSize: Integer);
+
+Var
+  F : TPDFEmbeddedFont;
+
+begin
+  F:=Document.CreateEmbeddedFont(AFontIndex,AFontSize);
+  AddObject(F);
+  FFontIndex := AFontIndex;
+end;
+
+procedure TPDFPage.SetColor(AColor: TARGBColor; AStroke : Boolean = True);
+
+Var
+  C : TPDFColor;
+
+begin
+  C:=Document.CreateColor(AColor,AStroke);
+  AddObject(C);
+end;
+
+procedure TPDFPage.SetPenStyle(AStyle: TPDFPenStyle);
+
+Var
+  L : TPDFLineStyle;
+
+begin
+  L:=Document.CreateLineStyle(AStyle);
+  AddObject(L);
+end;
+
+procedure TPDFPage.WriteText(X, Y: TPDFFloat; AText: String);
+var
+  T: TPDFText;
+  p: TPDFCoord;
+begin
+  p.X := X;
+  p.Y := Y;
+  DoUnitConversion(p);
+  T := Document.CreateText(p.X, p.Y, AText);
+  AddObject(T);
+end;
+
+procedure TPDFPage.WriteText(APos: TPDFCoord; AText: String);
+begin
+  WriteText(APos.X, APos.Y, AText);
+end;
+
+procedure TPDFPage.WriteUTF8Text(X, Y: TPDFFloat; AText: UTF8String);
+Var
+  T : TPDFUTF8Text;
+begin
+  if FFontIndex = -1 then
+    raise EPDF.Create('No FontIndex was set - please use SetFont() first.');
+  T := Document.CreateUTF8Text(X,Y,AText,FFontIndex);
+  AddObject(T);
+  AddTextToLookupLists(AText);
+end;
+
+procedure TPDFPage.DrawLine(X1, Y1, X2, Y2, ALineWidth: TPDFFloat);
+var
+  L : TPDFLineSegment;
+  p1, p2: TPDFCoord;
+begin
+  p1.X := X1;
+  p1.Y := Y1;
+  p2.X := X2;
+  p2.Y := Y2;
+  DoUnitConversion(p1);
+  DoUnitConversion(p2);
+  L := TPDFLineSegment.Create(Document, ALineWidth, p1.X, p1.Y, p2.X, p2.Y);
+  AddObject(L);
+end;
+
+procedure TPDFPage.DrawLine(APos1: TPDFCoord; APos2: TPDFCoord; ALineWidth: TPDFFloat);
+begin
+  DrawLine(APos1.X, APos1.Y, APos2.X, APos2.Y, ALineWidth);
+end;
+
+procedure TPDFPage.DrawLineStyle(X1, Y1, X2, Y2: TPDFFloat; AStyle: Integer);
+var
+  S: TPDFLineStyleDef;
+begin
+  S := Document.LineStyles[AStyle];
+  SetColor(S.Color, False);
+  SetPenStyle(S.PenStyle);
+  DrawLine(X1, Y1, X2, Y2, S.LineWidth);
+end;
+
+procedure TPDFPage.DrawLineStyle(APos1: TPDFCoord; APos2: TPDFCoord; AStyle: Integer);
+begin
+  DrawLineStyle(APos1.X, APos1.Y, APos2.X, APos2.Y, AStyle);
+end;
+
+procedure TPDFPage.DrawRect(const X, Y, W, H, ALineWidth: TPDFFloat; const AFill, AStroke: Boolean);
+var
+  R: TPDFRectangle;
+  p1, p2: TPDFCoord;
+begin
+  p1.X := X;
+  p1.Y := Y;
+  DoUnitConversion(p1);
+  p2.X := W;
+  p2.Y := H;
+  DoUnitConversion(p2);
+  R := Document.CreateRectangle(p1.X, p1.Y, p2.X, p2.Y, ALineWidth, AFill, AStroke);
+  AddObject(R);
+end;
+
+procedure TPDFPage.DrawRect(const APos: TPDFCoord; const W, H, ALineWidth: TPDFFloat; const AFill, AStroke: Boolean);
+begin
+  DrawRect(APos.X, APos.Y, W, H, ALineWidth, AFill, AStroke);
+end;
+
+procedure TPDFPage.DrawImage(const X, Y: TPDFFloat; const AWidth, AHeight, ANumber: integer);
+var
+  p1: TPDFCoord;
+begin
+  p1.X := X;
+  p1.Y := Y;
+  DoUnitConversion(p1);
+  AddObject(Document.CreateImage(p1.X, p1.Y, AWidth, AHeight, ANumber));
+end;
+
+procedure TPDFPage.DrawImage(const APos: TPDFCoord; const AWidth, AHeight, ANumber: integer);
+begin
+  DrawImage(APos.X, APos.Y, AWidth, AHeight, ANumber);
+end;
+
+procedure TPDFPage.DrawEllipse(const APosX, APosY, AWidth, AHeight,
+    ALineWidth: TPDFFloat; const AFill: Boolean; AStroke: Boolean);
+var
+  p1, p2: TPDFCoord;
+begin
+  p1.X := APosX;
+  p1.Y := APosY;
+  DoUnitConversion(p1);
+  p2.X := AWidth;
+  p2.Y := AHeight;
+  DoUnitConversion(p2);
+  AddObject(TPDFEllipse.Create(Document, p1.X, p1.Y, p2.X, p2.Y, ALineWidth, AFill, AStroke));
+end;
+
+procedure TPDFPage.DrawEllipse(const APos: TPDFCoord; const AWidth, AHeight, ALineWidth: TPDFFloat;
+    const AFill: Boolean; AStroke: Boolean);
+begin
+  DrawEllipse(APos.X, APos.Y, AWidth, AHeight, ALineWidth, AFill, AStroke);
+end;
+
+function TPDFPage.GetPaperHeight: TPDFFloat;
+begin
+  case FUnitOfMeasure of
+    uomMillimeters:
+      begin
+        Result := PDFtoMM(Paper.H);
+      end;
+    uomCentimeters:
+      begin
+        Result := PDFtoCM(Paper.H);
+      end;
+    uomInches:
+      begin
+        Result := PDFtoInches(Paper.H);
+      end;
+    uomPixels:
+      begin
+        Result := Paper.H;
+      end;
+  end;
+end;
+
+function TPDFPage.HasImages: Boolean;
+
+Var
+  I,M : Integer;
+begin
+  Result:=False;
+  M:=ObjectCount;
+  I:=0;
+  While (Not Result) and (I<M) do
+    begin
+    Result:=FObjects[i] is TPDFImage;
+    Inc(I);
+    end;
+end;
+
+{ TPDFFontDefs }
+
+function TPDFFontDefs.GetF(AIndex : Integer): TPDFFont;
+begin
+  Result:=Items[AIndex] as TPDFFont;
+end;
+
+function TPDFFontDefs.AddFontDef: TPDFFont;
+begin
+  Result:=Add as TPDFFont;
+end;
+
+{ TPDFSection }
+
+function TPDFSection.GetP(AIndex : Integer): TPDFPage;
+begin
+  If Assigned(FPages) then
+    Result:=TPDFPage(FPages[Aindex])
+  else
+    Raise EPDF.CreateFmt(SerrInvalidSectionPage,[AIndex]);
+end;
+
+function TPDFSection.GetP: INteger;
+begin
+  if Assigned(FPages) then
+    Result:=FPages.Count
+  else
+    Result:=0;
+end;
+
+destructor TPDFSection.Destroy;
+begin
+  FreeAndNil(FPages);
+  inherited Destroy;
+end;
+
+procedure TPDFSection.AddPage(APage: TPDFPage);
+begin
+  if Not Assigned(FPages) then
+    FPages:=TFPList.Create;
+  FPages.Add(APage);
+end;
+
+{ TPDFSectionList }
+
+function TPDFSectionList.GetS(AIndex : Integer): TPDFSection;
+begin
+  Result:=Items[AIndex] as TPDFSection
+end;
+
+function TPDFSectionList.AddSection: TPDFSection;
+begin
+  Result:=Add as TPDFSection;
+end;
+
+{ TPDFDocumentObject }
+
+constructor TPDFDocumentObject.Create(const ADocument: TPDFDocument);
+begin
+  inherited Create(ADocument);
+  FDocument:=ADocument;
+end;
+
+procedure TPDFDocumentObject.SetWidth(AWidth: TPDFFloat; AStream : TStream);
+
+Var
+  S : String;
+begin
+  S:=FloatStr(AWidth)+' w'; // stroke width
+  if (S<>Document.CurrentWidth) then
+    begin
+    WriteString('1 J'+CRLF, AStream); // line cap set to rounded edge
+    WriteString(S+CRLF, AStream);
+    Document.CurrentWidth:=S;
+    end;
+end;
+
+class procedure TPDFObject.WriteString(const AValue: string; AStream: TStream);
+
+Var
+  L : Integer;
+
+begin
+  L:=Length(AValue);
+  if L>0 then
+    AStream.Write(AValue[1],L);
+end;
+
+// Font=Name-Size:x:y
+function ExtractBaseFontName(const AValue: string): string;
+var
+  FontName, S1, S2: string;
+  P : Integer;
+
+begin
+  P:=Pos('-', AValue);
+  if (P>0) then
+    FontName:=Copy(AValue,1,P-1)
+  else
+    FontName:='';
+  P:=Pos(':',AValue); // First attribute
+  if (P>0) then
+    begin
+    S1:=Copy(AValue,P+1,Length(AValue)-P);
+    S1:=Upcase(S1[1])+Copy(S1,2,Pred(Length(S1)));
+    P:=Pos(':',S1);
+    if (P>0) then
+      begin
+      S2:=Copy(S1,P+1,Length(S1)-P);
+      if Length(S2)>0 then
+        S2[1]:=Upcase(S2[1]);
+      S1:=Copy(S1,1,P-1);
+      if Length(S1)>0 then
+        S1[1]:=Upcase(S1[1]);
+      S1:=S1+S2;
+      end;
+    S1:='-'+S1;
+    end;
+  Result:=FontName+S1;
+end;
+
+{ TPDFImageItem }
+
+procedure TPDFImageItem.SetImage(AValue: TFPCustomImage);
+begin
+  if FImage=AValue then Exit;
+  FImage:=AValue;
+  SetLength(FStreamed,0);
+end;
+
+function TPDFImageItem.GetStreamed: TBytes;
+begin
+  if Length(FStreamed)=0 then
+    CreateStreamedData;
+  Result:=FStreamed;
+end;
+
+function TPDFImageItem.GetHeight: Integer;
+begin
+  If Assigned(FImage) then
+    Result:=FImage.Height
+  else
+    Result:=FHeight;
+end;
+
+function TPDFImageItem.GetWidth: Integer;
+begin
+  If Assigned(FImage) then
+    Result:=FImage.Width
+  else
+    Result:=FWidth;
+end;
+
+procedure TPDFImageItem.SetStreamed(AValue: TBytes);
+begin
+  If AValue=FStreamed then exit;
+  SetLength(FStreamed,0);
+  FStreamed:=AValue;
+end;
+
+destructor TPDFImageItem.Destroy;
+begin
+  if FOwnsImage then
+    FreeAndNil(FImage);
+  inherited Destroy;
+end;
+
+procedure TPDFImageItem.CreateStreamedData;
+
+Var
+  I,X,Y : Integer;
+  C : TFPColor;
+begin
+  FWidth:=Image.Width;
+  FHeight:=Image.Height;
+  SetLength(FStreamed,FWidth*FHeight*3);
+  I:=0;
+  for Y:=0 to FHeight-1 do
+    for X:=0 to FWidth-1 do
+      begin
+      C:=Image.Colors[x,y];
+      FStreamed[I]:=C.Red shr 8;
+      FStreamed[I+1]:=C.Green shr 8;
+      FStreamed[I+2]:=C.blue shr 8;
+      Inc(I,3);
+      end;
+end;
+
+function TPDFImageItem.WriteImageStream(AStream: TStream): int64;
+
+var
+  Img : TBytes;
+
+begin
+  TPDFObject.WriteString(CRLF+'stream'+CRLF,AStream);
+  Img:=StreamedData;
+  Result:=Length(Img);
+  AStream.WriteBuffer(Img[0],Result);
+  TPDFObject.WriteString(CRLF, AStream);
+  TPDFObject.WriteString('endstream', AStream);
+end;
+
+function TPDFImageItem.Equals(AImage: TFPCustomImage): boolean;
+var
+  x, y: Integer;
+begin
+  Result := True;
+  for x := 0 to Image.Width-1 do
+    for y := 0 to Image.Height-1 do
+      if Image.Pixels[x, y] <> AImage.Pixels[x, y] then
+      begin
+        Result := False;
+        Exit;
+      end;
+end;
+
+
+
+{ TPDFImages }
+
+function TPDFImages.GetI(AIndex : Integer): TPDFImageItem;
+begin
+  Result:=Items[AIndex] as TPDFImageItem;
+end;
+
+function TPDFImages.AddImageItem: TPDFImageItem;
+begin
+  Result:=Add as TPDFImageItem;
+end;
+
+function TPDFImages.AddFromFile(const AFileName: String; KeepImage: Boolean): Integer;
+
+Var
+  I : TFPMemoryImage;
+  IP : TPDFImageItem;
+
+begin
+  I:=TFPMemoryImage.Create(0,0);
+  I.LoadFromFile(AFileName);
+  IP:=AddImageItem;
+  IP.Image:=I;
+  if Not KeepImage then
+    begin
+    IP.CreateStreamedData;
+    IP.FImage:=Nil; // not through property, that would clear the image
+    i.Free;
+    end;
+  Result:=Count-1;
+end;
+
+{ TPDFObject }
+
+constructor TPDFObject.Create(const ADocument: TPDFDocument);
+begin
+  If Assigned(ADocument) then
+    Inc(ADocument.FObjectCount);
+end;
+
+class function TPDFObject.FloatStr(F: TPDFFloat): String;
+begin
+  Result:=FormatFloat('0.##',F);
+end;
+
+procedure TPDFObject.Write(const AStream: TStream);
+begin
+  Assert(AStream<>Nil);
+end;
+
+procedure TPDFBoolean.Write(const AStream: TStream);
+begin
+  if FValue then
+    WriteString('true', AStream)
+  else
+    WriteString('false', AStream);
+end;
+
+constructor TPDFBoolean.Create(Const ADocument : TPDFDocument; const AValue: Boolean);
+begin
+  inherited Create(ADocument);
+  FValue:=AValue;
+end;
+
+procedure TPDFInteger.Write(const AStream: TStream);
+begin
+  WriteString(IntToStr(FInt), AStream);
+end;
+
+procedure TPDFInteger.Inc;
+begin
+  system.Inc(FInt);
+end;
+
+constructor TPDFInteger.Create(Const ADocument : TPDFDocument; const AValue: integer);
+begin
+  inherited Create(ADocument);
+  FInt:=AValue;
+end;
+
+
+procedure TPDFReference.Write(const AStream: TStream);
+begin
+  WriteString(IntToStr(FValue)+' 0 R', AStream);
+end;
+
+constructor TPDFReference.Create(Const ADocument : TPDFDocument; const AValue: integer);
+begin
+  inherited Create(ADocument);
+  FValue:=AValue;
+end;
+
+procedure TPDFName.Write(const AStream: TStream);
+begin
+  if FName <> '' then
+    if Pos('Length1', FName) > 0 then
+      WriteString('/Length1', AStream)
+    else
+      WriteString('/'+FName {ConvertCharsToHex}, AStream);
+end;
+
+constructor TPDFName.Create(const ADocument: TPDFDocument; const AValue: string);
+begin
+  inherited Create(ADocument);
+  FName:=AValue;
+end;
+
+function TPDFName.ConvertCharsToHex: string;
+var
+  s: string;
+  i: integer;
+  d: integer;
+begin
+  s := '';
+  for i := 1 to Length(Name) do
+  begin
+    d := Ord(Name[i]);
+    if (d < 33) or (d > 126) then
+      s := s + '#' + IntToHex(d, 2)
+    else
+      s := s + Name[i];
+  end;
+  Result := s;
+end;
+
+procedure TPDFString.Write(const AStream: TStream);
+var
+  s: AnsiString;
+  cs: AnsiString;
+begin
+  s := Utf8ToAnsi(FValue);
+  if poCompressText in Document.Options then
+  begin
+    // do nothing yet
+//    CompressString(s, cs);
+    WriteString('('+s+')', AStream);
+  end
+  else
+    WriteString('('+s+')', AStream);
+end;
+
+constructor TPDFString.Create(Const ADocument : TPDFDocument; const AValue: string);
+begin
+  inherited Create(ADocument);
+  FValue:=AValue;
+  if (Pos('(', FValue) > 0) or (Pos(')', FValue) > 0) or (Pos('\', FValue) > 0) then
+    FValue:=InsertEscape(FValue);
+end;
+
+{ TPDFUTF8String }
+
+function TPDFUTF8String.RemapedText: String;
+var
+  s: UnicodeString;
+  i: integer;
+  idx: integer;  // character code
+  c: UnicodeChar;
+begin
+  Result := '';
+  s := UTF8ToUTF16(FValue);
+  // lookup the alphabet code for each character
+  for i := 1 to Length(s) do
+  begin
+    c := s[i];
+    idx := Document.Fonts[FontIndex].FindIndexOf(c);
+    Result := Result + IntToStrZeros(idx+1,2);   // PDF expects 1-based numbering
+  end;
+end;
+
+procedure TPDFUTF8String.Write(const AStream: TStream);
+begin
+  if poCompressText in Document.Options then
+  begin
+    // do nothing yet
+    WriteString('('+UTF8ToUTF16(FValue)+')', AStream);
+  end
+  else
+    WriteString('<'+RemapedText+'>', AStream);
+end;
+
+constructor TPDFUTF8String.Create(const ADocument: TPDFDocument; const AValue: UTF8String; const AFontIndex: integer);
+begin
+  inherited Create(ADocument);
+  FValue := AValue;
+  FFontIndex := AFontIndex;
+  if (Pos('(', FValue) > 0) or (Pos(')', FValue) > 0) or (Pos('\', FValue) > 0) then
+    FValue:=InsertEscape(FValue);
+end;
+
+{ TPDFArray }
+
+procedure TPDFArray.Write(const AStream: TStream);
+var
+  i: integer;
+begin
+  WriteString('[', AStream);
+  for i:=0 to Pred(FArray.Count) do
+    begin
+    if i > 0 then
+      WriteString(' ', AStream);
+    TPDFObject(FArray[i]).Write(AStream);
+    end;
+  WriteString(']', AStream);
+end;
+
+procedure TPDFArray.AddItem(const AValue: TPDFObject);
+begin
+  FArray.Add(AValue);
+end;
+
+procedure TPDFArray.AddIntArray(S: String);
+
+Var
+  P : Integer;
+
+begin
+  P:=Pos(' ',S);
+  while (P>0) do
+  begin
+    AddItem(Document.CreateInteger(StrToInt(Copy(S,1,Pred(P)))));
+    Delete(S,1,P);
+    P:=Pos(' ',S);
+  end;
+  if S <> '' then
+    AddItem(Document.CreateInteger(StrToInt(S)));
+end;
+
+constructor TPDFArray.Create(const ADocument: TPDFDocument);
+begin
+  inherited Create(ADocument);
+  FArray:=TFPObjectList.Create;
+end;
+
+destructor TPDFArray.Destroy;
+
+begin
+  // TPDFInteger, TPDFReference, TPDFName
+  FreeAndNil(FArray);
+  inherited;
+end;
+
+procedure TPDFStream.Write(const AStream: TStream);
+var
+  i: integer;
+begin
+  for i:=0 to FItems.Count-1 do
+    TPDFObject(FItems[i]).Write(AStream);
+end;
+
+procedure TPDFStream.AddItem(const AValue: TPDFObject);
+begin
+  FItems.Add(AValue);
+end;
+
+constructor TPDFStream.Create(Const ADocument : TPDFDocument; OwnsObjects : Boolean = True);
+begin
+  inherited Create(ADocument);
+  FItems:=TFPObjectList.Create(OwnsObjects);
+end;
+
+destructor TPDFStream.Destroy;
+begin
+  FreeAndNil(FItems);
+  inherited;
+end;
+
+procedure TPDFEmbeddedFont.Write(const AStream: TStream);
+begin
+  WriteString('/F'+IntToStr(FTxtFont)+' '+FTxtSize+' Tf'+CRLF, AStream);
+end;
+
+Class function TPDFEmbeddedFont.WriteEmbeddedFont(const ADocument: TPDFDocument; const Src: TMemoryStream; const AStream: TStream): int64;
+var
+  PS: int64;
+  CompressedStream: TMemoryStream;
+begin
+  WriteString(CRLF+'stream'+CRLF, AStream);
+  PS:=AStream.Position;
+  if poCompressFonts in ADocument.Options then
+  begin
+    CompressedStream := TMemoryStream.Create;
+    CompressStream(Src, CompressedStream);
+    CompressedStream.Position := 0;
+    CompressedStream.SaveToStream(AStream);
+    CompressedStream.Free;
+  end
+  else
+  begin
+    Src.Position := 0;
+    Src.SaveToStream(AStream);
+  end;
+  Result:=AStream.Position-PS;
+  WriteString(CRLF, AStream);
+  WriteString('endstream', AStream);
+end;
+
+constructor TPDFEmbeddedFont.Create(Const ADocument : TPDFDocument;const AFont: integer; const ASize: string);
+begin
+  inherited Create(ADocument);
+  FTxtFont:=AFont;
+  FTxtSize:=ASize;
+end;
+
+
+procedure TPDFText.Write(const AStream: TStream);
+begin
+  WriteString('BT'+CRLF, AStream);
+  WriteString(FloatStr(FX)+' '+FloatStr(FY)+' TD'+CRLF, AStream);
+  FString.Write(AStream);
+  WriteString(' Tj'+CRLF, AStream);
+  WriteString('ET'+CRLF, AStream);
+end;
+
+constructor TPDFText.Create(Const ADocument : TPDFDocument; const AX, AY: TPDFFloat; const AText: string);
+begin
+  inherited Create(ADocument);
+  FX:=AX;
+  FY:=AY;
+  FString:=ADocument.CreateString(AText);
+end;
+
+destructor TPDFText.Destroy;
+begin
+  FreeAndNil(FString);
+  inherited;
+end;
+
+{ TPDFUTF8Text }
+
+procedure TPDFUTF8Text.Write(const AStream: TStream);
+begin
+  WriteString('BT'+CRLF, AStream);
+  WriteString(FloatStr(FX)+' '+FloatStr(FY)+' TD'+CRLF, AStream);
+  FString.Write(AStream);
+  WriteString(' Tj'+CRLF, AStream);
+  WriteString('ET'+CRLF, AStream);
+end;
+
+constructor TPDFUTF8Text.Create(const ADocument: TPDFDocument; const AX, AY: TPDFFloat; const AText: UTF8String;
+  const AFontIndex: integer);
+begin
+  inherited Create(ADocument);
+  FX := AX;
+  FY := AY;
+  FFontIndex := AFontIndex;
+  FString := ADocument.CreateUTF8String(AText, AFontIndex);
+end;
+
+destructor TPDFUTF8Text.Destroy;
+begin
+  FreeAndNil(FString);
+  inherited Destroy;
+end;
+
+{ TPDFLineSegment  }
+
+procedure TPDFLineSegment.Write(const AStream: TStream);
+
+begin
+  SetWidth(FWidth,AStream);
+  WriteString(TPDFMoveTo.Command(P1), AStream);
+  WriteString(Command(P2),AStream);
+  WriteString('S'+CRLF, AStream);
+end;
+
+class function TPDFLineSegment.Command(APos: TPDFCoord): String;
+begin
+  Result:=FloatStr(APos.X)+' '+FloatStr(APos.Y)+' l'+CRLF
+end;
+
+class function TPDFLineSegment.Command(APos1, APos2: TPDFCoord): String;
+begin
+  Result:=TPDFMoveTo.Command(APos1)+Command(APos2);
+end;
+
+constructor TPDFLineSegment.Create(const ADocument: TPDFDocument; const AWidth,
+  X1, Y1, X2, Y2: TPDFFloat);
+begin
+  inherited Create(ADocument);
+  FWidth:=AWidth;
+  P1.X:=X1;
+  P1.Y:=Y1;
+  P2.X:=X2;
+  P2.Y:=Y2;
+end;
+
+procedure TPDFRectangle.Write(const AStream: TStream);
+begin
+  if FStroke then
+    SetWidth(FWidth, AStream);
+  WriteString(FloatStr(FTopLeft.X)+' '+FloatStr(FTopLeft.Y)+' '+FloatStr(FDimensions.X)+' '+FloatStr(FDimensions.Y)+' re'+CRLF, AStream);
+  if FStroke and FFill then
+    WriteString('b'+CRLF, AStream)
+  else if FFill then
+    WriteString('f'+CRLF, AStream)
+  else if FStroke then
+    WriteString('S'+CRLF, AStream);
+  (*
+  // should we default to this if no stroking or filling is required?
+  else
+    WriteString('n'+CRLF, AStream); // see PDF 1.3 Specification document on page 152
+  *)
+end;
+
+constructor TPDFRectangle.Create(const ADocument: TPDFDocument; const APosX, APosY, AWidth, AHeight,
+    ALineWidth: TPDFFloat; const AFill, AStroke: Boolean);
+begin
+  inherited Create(ADocument);
+  FTopLeft.X := APosX;
+  FTopLeft.Y := APosY;
+  FDimensions.X := AWidth;
+  FDimensions.Y := AHeight;
+  FWidth := ALineWidth;
+  FFill := AFill;
+  FStroke := AStroke;
+end;
+
+procedure TPDFSurface.Write(const AStream: TStream);
+var
+  i: integer;
+begin
+  WriteString(TPDFMoveTo.Command(FPoints[0].X,FPoints[0].Y),AStream);
+  for i:=1 to Pred(Length(FPoints)) do
+    WriteString(FloatStr( FPoints[i].X)+' '+FloatStr( FPoints[i].Y)+' l'+CRLF, AStream);
+  if FClose then
+    WriteString('h'+CRLF, AStream);
+  if FFill then
+    WriteString('f'+CRLF, AStream);
+end;
+
+constructor TPDFSurface.Create(Const ADocument : TPDFDocument; const APoints: TPDFCoordArray; AClose : Boolean; AFill : Boolean = True);
+begin
+  inherited Create(ADocument);
+  FPoints:=APoints;
+  FClose:=AClose;
+  FFill:=AFill;
+end;
+
+procedure TPDFImage.Write(const AStream: TStream);
+begin
+  WriteString('q'+CRLF, AStream);   // save graphics state
+  WriteString(IntToStr(FWidth)+' 0 0 '+IntToStr(FHeight)+' '+FloatStr( FPos.X)+' '+FloatStr( FPos.Y)+' cm'+CRLF, AStream);
+  WriteString('/I'+IntToStr(FNumber)+' Do'+CRLF, AStream);
+  WriteString('Q'+CRLF, AStream);   // restore graphics state
+end;
+
+constructor TPDFImage.Create(Const ADocument : TPDFDocument; const ALeft, ABottom: TPDFFloat; AWidth, AHeight, ANumber: integer);
+begin
+  inherited Create(ADocument);
+  FNumber:=ANumber;
+  FPos.X:=ALeft;
+  FPos.Y:=ABottom;
+  FWidth:=AWidth;
+  FHeight:=AHeight;
+end;
+
+procedure TPDFLineStyle.Write(const AStream: TStream);
+begin
+  WriteString(Format('[%s] %d d'+CRLF,[cPenStyleBitmasks[FStyle],FPhase]), AStream);
+end;
+
+constructor TPDFLineStyle.Create(Const ADocument : TPDFDocument; AStyle: TPDFPenStyle; APhase: integer);
+begin
+  inherited Create(ADocument);
+  FStyle:=AStyle;
+  FPhase:=APhase;
+end;
+
+procedure TPDFColor.Write(const AStream: TStream);
+
+Var
+  S : String;
+begin
+  S:=FRed+' '+FGreen+' '+FBlue;
+  if FStroke then
+    S:=S+' RG'
+  else
+    S:=S+' rg';
+  if (S<>Document.CurrentColor) then
+    begin
+    WriteString(S+CRLF, AStream);
+    Document.CurrentColor:=S;
+    end;
+end;
+
+Function ARGBGetRed(AColor : TARGBColor) : Byte;
+
+begin
+  Result:=((AColor shr 16) and $FF)
+end;
+
+Function ARGBGetGreen(AColor : TARGBColor) : Byte;
+
+begin
+  Result:=((AColor shr 8) and $FF)
+end;
+
+Function ARGBGetBlue(AColor : TARGBColor) : Byte;
+
+begin
+  Result:=AColor and $FF;
+end;
+
+Function ARGBGetAlpha(AColor : TARGBColor) : Byte;
+
+begin
+  Result:=((AColor shr 24) and $FF)
+end;
+
+constructor TPDFColor.Create(Const ADocument : TPDFDocument; const AStroke: Boolean; AColor: TARGBColor);
+begin
+  inherited Create(ADocument);
+  FRed:=FloatStr( ARGBGetRed(AColor)/256);
+  FGreen:=FloatStr( ARGBGetGreen(AColor)/256);
+  FBlue:=FloatStr( ARGBGetBlue(AColor)/256);
+  FStroke:=AStroke;
+end;
+
+procedure TPDFDictionaryItem.Write(const AStream: TStream);
+begin
+  FKey.Write(AStream);
+  TPDFObject.WriteString(' ', AStream);
+  FObj.Write(AStream);
+  TPDFObject.WriteString(CRLF, AStream);
+end;
+
+constructor TPDFDictionaryItem.Create(Const ADocument : TPDFDocument;const AKey: string; const AValue: TPDFObject);
+begin
+  inherited Create(ADocument);
+  FKey:=ADocument.CreateName(AKey);
+  FObj:=AValue;
+end;
+
+destructor TPDFDictionaryItem.Destroy;
+begin
+  FreeAndNil(FKey);
+  // TPDFBoolean,TPDFDictionary,TPDFInteger,TPDFName,TPDFReference,TPDFString,TPDFArray
+  FreeAndNil(FObj);
+  inherited;
+end;
+
+function TPDFDictionary.GetE(AIndex : Integer): TPDFDictionaryItem;
+begin
+  Result:=TPDFDictionaryItem(FElements[AIndex]);
+end;
+
+function TPDFDictionary.GetEC: Integer;
+begin
+  Result:=FElements.Count;
+end;
+
+function TPDFDictionary.GetV(AIndex : Integer): TPDFObject;
+begin
+  Result:=Elements[AIndex].Value;
+end;
+
+procedure TPDFDictionary.AddElement(const AKey: string; const AValue: TPDFObject);
+var
+  DicElement: TPDFDictionaryItem;
+begin
+  DicElement:=TPDFDictionaryItem.Create(Document,AKey, AValue);
+  FElements.Add(DicElement);
+end;
+
+procedure TPDFDictionary.AddName(const AKey, AName: String);
+begin
+  AddElement(AKey,Document.CreateName(AName));
+end;
+
+procedure TPDFDictionary.AddInteger(const AKey: String; AInteger: Integer);
+begin
+  AddElement(AKey,Document.CreateInteger(AInteger));
+end;
+
+procedure TPDFDictionary.AddReference(const AKey: String; AReference: Integer);
+begin
+  AddElement(AKey,Document.CreateReference(AReference));
+end;
+
+procedure TPDFDictionary.AddString(const AKey, AString: String);
+begin
+  AddElement(AKey,Document.CreateString(AString));
+end;
+
+function TPDFDictionary.IndexOfKey(const AValue: string): integer;
+var
+  i: integer;
+begin
+  Result:=-1;
+  I:=0;
+  While (Result=-1) and (I<ElementCount) do
+    begin
+    if GetE(I).FKey.Name=AValue then
+      Result:=I;
+    Inc(I);
+    end;
+end;
+
+procedure TPDFDictionary.Write(const AStream: TStream);
+begin
+  WriteDictionary(-1,AStream);
+end;
+
+procedure TPDFDictionary.WriteDictionary(const AObject: integer; const AStream: TStream);
+var
+  ISize,i, NumImg, NumFnt: integer;
+  Value: string;
+  M : TMemoryStream;
+  E : TPDFDictionaryItem;
+  D : TPDFDictionary;
+begin
+  if GetE(0).FKey.Name='' then
+    GetE(0).Write(AStream)  // write a charwidth array of a font
+  else
+  begin
+    WriteString('<<'+CRLF, AStream);
+    for i:=0 to ElementCount-1 do
+      GetE(I).Write(AStream);
+    NumImg:=-1;
+    NumFnt:=-1;
+    for i:=0 to ElementCount-1 do
+      begin
+      E:=GetE(i);
+      if AObject > -1 then
+        begin
+          if (E.FKey.Name='Name') then
+          begin
+            if (TPDFObject(E.Value) is TPDFName) and (TPDFName(E.Value).Name[1]='I') then
+            begin
+              NumImg:=StrToInt(Copy(TPDFName(E.Value).Name, 2, Length(TPDFName(E.Value).Name) - 1));
+              // write image stream length in xobject dictionary
+              ISize:=Length(Document.Images[NumImg].StreamedData);
+              D:=Document.GlobalXRefs[AObject].Dict;
+              D.AddInteger('Length',ISize);
+              LastElement.Write(AStream);
+              WriteString('>>', AStream);
+              // write image stream in xobject dictionary
+              Document.Images[NumImg].WriteImageStream(AStream);
+            end;
+          end;
+          if Pos('Length1', E.FKey.Name) > 0 then
+          begin
+            M:=TMemoryStream.Create;
+            try
+              Value:=E.FKey.Name;
+              NumFnt:=StrToInt(Copy(Value, Succ(Pos(' ', Value)), Length(Value) - Pos(' ', Value)));
+              m.LoadFromFile(Document.FontFiles[NumFnt]);
+              // write fontfile stream length in xobject dictionary
+              D:=Document.GlobalXRefs[AObject].Dict;
+              D.AddInteger('Length',M.Size);
+              LastElement.Write(AStream);
+              WriteString('>>', AStream);
+              // write fontfile stream in xobject dictionary
+              TPDFEmbeddedFont.WriteEmbeddedFont(Document, M, AStream);
+            finally
+              M.Free;
+            end;
+          end;
+        end;
+      end; { for i... }
+    end; { if FElement.Count... }
+    if (NumImg = -1) and (NumFnt = -1) then
+      WriteString('>>', AStream);
+end; { if/else }
+
+
+function TPDFDictionary.LastElement: TPDFDictionaryItem;
+begin
+  if (ElementCount=0) then
+    Result:=Nil
+  else
+    Result:=GetE(ElementCount-1);
+end;
+
+function TPDFDictionary.LastValue: TPDFObject;
+Var
+  DE : TPDFDictionaryItem;
+begin
+  DE:=LastElement;
+  If Assigned(DE) then
+    Result:=DE.Value
+  else
+    Result:=Nil;
+end;
+
+function TPDFDictionary.FindElement(const AKey: String): TPDFDictionaryItem;
+
+Var
+  I : integer;
+
+begin
+  I:=IndexOfKey(AKey);
+  if I=-1 then
+    Result:=Nil
+  else
+    Result:=GetE(I);
+end;
+
+function TPDFDictionary.FindValue(const AKey: String): TPDFObject;
+
+Var
+  DI : TPDFDictionaryItem;
+
+begin
+  DI:=FindElement(AKey);
+  if Assigned(DI) then
+    Result:=DI.Value
+  else
+    Result:=Nil;
+end;
+
+function TPDFDictionary.ElementByName(const AKey: String): TPDFDictionaryItem;
+begin
+  Result:=FindElement(AKey);
+  If (Result=Nil) then
+    Raise EPDF.CreateFmt(SErrDictElementNotFound,[AKey]);
+end;
+
+function TPDFDictionary.ValueByName(const AKey: String): TPDFObject;
+begin
+  Result:=ElementByName(AKey).Value;
+end;
+
+constructor TPDFDictionary.Create(const ADocument: TPDFDocument);
+begin
+  inherited Create(ADocument);
+  FElements:=TFPObjectList.Create;
+end;
+
+destructor TPDFDictionary.Destroy;
+
+begin
+  FreeAndNil(FElements);
+  inherited;
+end;
+
+procedure TPDFXRef.Write(const AStream: TStream);
+begin
+  TPDFObject.WriteString(FormatPDFInt(FOffset, 10)+' '+FormatPDFInt(0, 5)+' n'+CRLF, AStream);
+end;
+
+constructor TPDFXRef.Create(Const ADocument : TPDFDocument);
+begin
+  inherited Create;
+  FOffset:=0;
+  FDict:=ADocument.CreateDictionary;
+  FStream:=nil;
+end;
+
+destructor TPDFXRef.Destroy;
+begin
+  FreeAndNil(FDict);
+  FreeAndNil(FStream);
+  inherited;
+end;
+
+{ TPDFToUnicode }
+
+procedure TPDFToUnicode.Write(const AStream: TStream);
+var
+  i: integer;
+  lFontIndex: integer;
+  lFont: TPDFFont;
+begin
+  WriteString('/CIDInit/ProcSet findresource begin'+CRLF, AStream);
+  WriteString('12 dict begin'+CRLF, AStream);
+  WriteString('begincmap'+CRLF, AStream);
+  WriteString('/CIDSystemInfo <<'+CRLF, AStream);
+  WriteString('/Registry (Adobe)'+CRLF, AStream);
+  WriteString('/Ordering (UCS)'+CRLF, AStream);
+  WriteString('/Supplement 0'+CRLF, AStream);
+  WriteString('>> def'+CRLF, AStream);
+  WriteString('/CMapName/Adobe-Identity-UCS def'+CRLF, AStream);
+  WriteString('/CMapType 2 def'+CRLF, AStream);
+  WriteString('1 begincodespacerange'+CRLF, AStream);
+  WriteString('<00> <FF>'+CRLF, AStream);
+  WriteString('endcodespacerange'+CRLF, AStream);
+
+  lFont := Document.Fonts[EmbeddedFontNum];
+  WriteString(Format('%d beginbfchar'+CRLF, [lFont.Dictionary.Count]), AStream);
+  // write mapping for each character in dictionary
+  for i := 0 to lFont.Dictionary.Count-1 do
+    WriteString(Format('<%s> <%s>'+CRLF, [IntToStrZeros(i+1, 2), TTextDictionary(lFont.Dictionary[i]).CodePoint]), AStream);  // PDF expects 1-based numbering
+  WriteString('endbfchar'+CRLF, AStream);
+
+  WriteString('endcmap'+CRLF, AStream);
+  WriteString('CMapName currentdict /CMap defineresource pop'+CRLF, AStream);
+  WriteString('end'+CRLF, AStream);
+  WriteString('end'+CRLF, AStream);
+end;
+
+constructor TPDFToUnicode.Create(const ADocument: TPDFDocument; const AEmbeddedFontNum: integer; AFontDef: TFontDef);
+begin
+  inherited Create(ADocument);
+  FEmbeddedFontNum := AEmbeddedFontNum;
+  FFontDef := AFontDef;
+end;
+
+
+procedure TPDFDocument.SetInfos(AValue: TPDFInfos);
+begin
+  if FInfos=AValue then Exit;
+  FInfos.Assign(AValue);
+end;
+
+procedure TPDFDocument.SetLineStyles(AValue: TPDFLineStyleDefs);
+begin
+  if FLineStyleDefs=AValue then Exit;
+  FLineStyleDefs.Assign(AValue);
+end;
+
+procedure TPDFDocument.SetFonts(AValue: TPDFFontDefs);
+begin
+  if FFonts=AValue then Exit;
+  FFonts:=AValue;
+end;
+
+procedure TPDFDocument.SetFontFiles(AValue: TStrings);
+begin
+  if FFontFiles=AValue then Exit;
+  FFontFiles.Assign(AValue);
+end;
+
+function TPDFDocument.GetX(AIndex : Integer): TPDFXRef;
+begin
+  Result:=FGlobalXRefs[Aindex] as TPDFXRef;
+end;
+
+function TPDFDocument.GetXC: Integer;
+begin
+  Result:=FGlobalXRefs.Count;
+end;
+
+function TPDFDocument.IndexOfGlobalXRef(const AValue: string): integer;
+var
+  i: integer;
+begin
+  for i:=1 to Pred(FGlobalXRefs.Count) do
+    if TPDFName(GetX(i).Dict.Elements[0].Value).Name=AValue then
+      Result:=i;
+end;
+
+function TPDFDocument.FindGlobalXRef(const AName: String): TPDFXRef;
+
+Var
+  I : Integer;
+
+begin
+  I:=IndexOfGlobalXRef(AName);
+  if I=-1 then
+    Result:=Nil
+  else
+    Result:=GlobalXRefs[i];
+end;
+
+procedure TPDFDocument.WriteXRefTable(const AStream: TStream);
+var
+  i: integer;
+begin
+  if FGlobalXRefs.Count > 1 then
+    for i:=1 to FGlobalXRefs.Count-1 do
+      GetX(i).Write(AStream);
+end;
+
+procedure TPDFDocument.WriteObject(const AObject: integer; const AStream: TStream);
+var
+  M : TMemoryStream;
+  X : TPDFXRef;
+begin
+  TPDFObject.WriteString(IntToStr(AObject)+' 0 obj'+CRLF, AStream);
+  X:=GlobalXRefs[AObject];
+  if X.FStream = nil then
+    X.Dict.WriteDictionary(AObject, AStream)
+  else
+    begin
+    M:=TMemoryStream.Create;
+    try
+      CurrentColor:='';
+      CurrentWidth:='';
+      X.FStream.Write(M);
+      X.Dict.AddInteger('Length',M.Size);
+    finally
+      M.Free;
+    end;
+    X.Dict.Write(AStream);
+    // write stream in contents dictionary
+    CurrentColor:='';
+    CurrentWidth:='';
+    TPDFObject.WriteString(CRLF+'stream'+CRLF, AStream);
+    X.FStream.Write(AStream);
+    TPDFObject.WriteString('endstream', AStream);
+    end;
+  TPDFObject.WriteString(CRLF+'endobj'+CRLF+CRLF, AStream);
+end;
+
+procedure TPDFDocument.CreateRefTable;
+
+begin
+  FGlobalXRefs:=TFPObjectList.Create;
+  FGlobalXRefs.Add(CreateXRef);
+end;
+
+
+procedure TPDFDocument.CreateTrailer;
+
+begin
+  FTrailer:=CreateDictionary;
+  Trailer.AddInteger('Size',GlobalXRefCount);
+end;
+
+function TPDFDocument.CreateCatalogEntry: integer;
+var
+  CDict: TPDFDictionary;
+begin
+  CDict:=CreateGlobalXRef.Dict;
+  Trailer.AddReference('Root',GlobalXRefCount-1);
+  CDict.AddName('Type','Catalog');
+  CDict.AddName('PageLayout', PageLayoutNames[FPageLayout]);
+  CDict.AddElement('OpenAction', CreateArray);
+  Result:=GlobalXRefCount-1;
+end;
+
+procedure TPDFDocument.CreateInfoEntry;
+
+var
+  IDict: TPDFDictionary;
+
+begin
+  IDict:=CreateGlobalXRef.Dict;
+  Trailer.AddReference('Info', GLobalXRefCount-1);
+  (Trailer.ValueByName('Size') as TPDFInteger).Value:=GLobalXRefCount;
+  IDict.AddString('Title',Infos.Title);
+  IDict.AddString('Author',Infos.Author);
+  IDict.AddString('Creator',Infos.ApplicationName);
+  IDict.AddString('Producer',Infos.Producer);
+  IDict.AddString('CreationDate',DateToPdfDate(Infos.CreationDate));
+end;
+
+procedure TPDFDocument.CreatePreferencesEntry;
+
+var
+  VDict: TPDFDictionary;
+
+begin
+  VDict:=CreateGlobalXRef.Dict;
+  VDict.AddName('Type', 'ViewerPreferences');
+  VDict.AddElement('FitWindow', CreateBoolean(True));
+  VDict:=GlobalXRefByName('Catalog').Dict;
+  VDict.AddReference('ViewerPreferences',GLobalXRefCount-1);
+end;
+
+function TPDFDocument.CreatePagesEntry(Parent: integer): integer;
+
+var
+  EDict,ADict: TPDFDictionary;
+
+begin
+  EDict:=CreateGlobalXRef.Dict;
+  Result:=GLobalXRefCount-1;
+  EDict.AddName('Type','Pages');
+  EDict.AddElement('Kids',CreateArray);
+  EDict.AddInteger('Count',0);
+  if Parent=0 then
+    GlobalXRefByName('Catalog').Dict.AddReference('Pages',Result)
+  else
+    begin
+    EDict.AddReference('Parent',Parent);
+    ADict:=GlobalXRefs[Parent].Dict;
+    (ADict.ValueByName('Count') as TPDFInteger).Inc;
+    (ADict.ValueByName('Kids') as TPDFArray).AddItem(CreateReference(Result));
+    end;
+end;
+
+function TPDFDocument.CreatePageEntry(Parent, PageNum: integer): integer;
+var
+
+  PDict,ADict: TPDFDictionary;
+  Arr : TPDFArray;
+  PP : TPDFPage;
+
+begin
+  // add xref entry
+  PP:=Pages[PageNum];
+  PDict:=CreateGlobalXRef.Dict;
+  PDict.AddName('Type','Page');
+  PDict.AddReference('Parent',Parent);
+  ADict:=GlobalXRefs[Parent].Dict;
+  (ADict.ValueByName('Count') as TPDFInteger).Inc;
+  (ADict.ValueByName('Kids') as TPDFArray).AddItem(CreateReference(GLobalXRefCount-1));
+  Arr:=CreateArray;
+  Arr.AddItem(CreateInteger(0));
+  Arr.AddItem(CreateInteger(0));
+  Arr.AddItem(CreateInteger(PP.Paper.W));
+  Arr.AddItem(CreateInteger(PP.Paper.H));
+  PDict.AddElement('MediaBox',Arr);
+  ADict:=CreateDictionary;
+  PDict.AddElement('Resources',ADict);
+  Arr:=CreateArray; // procset
+  ADict.AddElement('ProcSet',Arr);
+  Arr.AddItem(CreateName('PDF'));
+  Arr.AddItem(CreateName('Text'));
+  Arr.AddItem(CreateName('ImageC'));
+  if (Fonts.Count>0) then
+    ADict.AddElement('Font',CreateDictionary);
+  if PP.HasImages then
+    ADict.AddElement('XObject', CreateDictionary);
+  Result:=GLobalXRefCount-1;
+end;
+
+function TPDFDocument.CreateOutlines: integer;
+var
+  ODict: TPDFDictionary;
+
+begin
+  ODict:=CreateGlobalXRef.Dict;
+  ODict.AddName('Type','Outlines');
+  ODict.AddInteger('Count',0);
+  Result:=GLobalXRefCount-1;
+end;
+
+function TPDFDocument.CreateOutlineEntry(Parent, SectNo, PageNo: integer; ATitle: string): integer;
+var
+  ODict: TPDFDictionary;
+  S: String;
+
+begin
+  ODict:=CreateGlobalXRef.Dict;
+  S:=ATitle;
+  if (S='') then
+    S:='Section '+IntToStr(SectNo);
+  if (PageNo>-1) then
+    S:=S+' Page '+IntToStr(PageNo);
+  ODict.AddString('Title',S);
+  ODict.AddReference('Parent',Parent);
+  ODict.AddInteger('Count',0);
+  ODict.AddElement('Dest', CreateArray);
+  Result:=GLobalXRefCount-1;
+end;
+
+procedure TPDFDocument.AddFontNameToPages(const AName: String; ANum: Integer);
+
+Var
+  i: integer;
+  ADict: TPDFDictionary;
+
+begin
+  for i:=1 to GLobalXRefCount-1 do
+    begin
+    ADict:=GlobalXRefs[i].Dict;
+    if (ADict.ElementCount>0) then
+      if (ADict.Values[0] is TPDFName) and ((ADict.Values[0] as TPDFName).Name= 'Page') then
+        begin
+        ADict:=ADict.ValueByName('Resources') as TPDFDictionary;
+        ADict:=ADict.ValueByName('Font') as TPDFDictionary;
+        ADict.AddReference(AName,ANum);
+        end;
+    end;
+end;
+
+procedure TPDFDocument.CreateStdFont(EmbeddedFontName: string; EmbeddedFontNum: integer);
+
+var
+  FDict: TPDFDictionary;
+  N: TPDFName;
+
+begin
+  if Pos('Italic', EmbeddedFontName) > 0 then
+    EmbeddedFontName:=Copy(EmbeddedFontName, 1, Pred(Pos('Italic', EmbeddedFontName)))+'Oblique';
+  //  AnsiReplaceText(EmbeddedFontName,'Italic','Oblique');
+  // add xref entry
+  FDict:=CreateGlobalXRef.Dict;
+  FDict.AddName('Type', 'Font');
+  FDict.AddName('Subtype', 'Type1');
+  FDict.AddName('Encoding', 'WinAnsiEncoding');
+  FDict.AddInteger('FirstChar', 32);
+  FDict.AddInteger('LastChar', 255);
+  FDict.AddName('BaseFont', EmbeddedFontName);
+  N:=CreateName('F'+IntToStr(EmbeddedFontNum));
+  FDict.AddElement('Name',N);
+  AddFontNameToPages(N.Name,GLobalXRefCount-1);
+  // add font reference to all page dictionary
+  FontFiles.Add('');
+end;
+
+function TPDFDocument.LoadFont(AFont: TPDFFont; out FontDef: TFontDef): string;
+var
+  lFontFile: TTFFileInfo;
+  lFontDef: TPDFFontDefinition;
+  lFName: string;
+  i: integer;
+  s: string;
+begin
+  if ExtractFilePath(AFont.FontFile) <> '' then
+    // assume AFont.FontFile is the full path to the TTF file
+    lFName := AFont.FontFile
+  else
+    // assume it's just a TTF filename
+    lFName := IncludeTrailingPathDelimiter(FontDirectory)+AFont.FontFile;
+
+  if FileExists(lFName) then
+  begin
+    lFontFile := TTFFileInfo.Create;
+    lFontFile.LoadFromFile(lFName);
+    lFontFile.PrepareFontDefinition('cp1252', True);
+    lFontFile.FillPDFFontDefinition(lFontDef, ExtractBaseFontName(AFont.Name), 'cp1252');
+    FontDef.FType := lFontDef.FontType;
+    FontDef.FName := lFontDef.FontName;
+    FontDef.FAscent := IntToStr(lFontDef.Ascender);
+    FontDef.FDescent := IntToStr(lFontDef.Descender);
+    FontDef.FCapHeight := IntToStr(lFontDef.CapHeight);
+    FontDef.FFlags := IntToStr(lFontDef.Flags);
+    s := '';
+    for i := 0 to 3 do
+    begin
+      if i > 0 then
+        s := s+' ';
+      s := s + IntToStr(lFontDef.BBox[i]);
+    end;
+    FontDef.FFontBBox := s;
+    FontDef.FItalicAngle := IntToStr(lFontDef.ItalicAngle);
+    FontDef.FStemV := IntToStr(lFontDef.StemV);
+   {$NOTE The 1000 value is a work-around until I can figure out the character spacing problem. }
+    FontDef.FMissingWidth := '1000'; //IntToStr(lFontDef.MissingWidth);
+    FontDef.FEncoding := lFontDef.Encoding;
+    FontDef.FFile := lFName;
+    FontDef.FOriginalSize := IntToStr(lFontDef.OriginalSize);
+    FontDef.FDiffs := lFontDef.Diffs;
+    FontDef.FCharWidth := lFontDef.CharWidths;
+    Result := lFontDef.FontType;
+    lFontFile.Free;
+  end
+  else
+    Raise EPDF.CreateFmt(rsErrReportFontFileMissing, [lFName]);
+end;
+
+procedure TPDFDocument.CreateTTFFont(const EmbeddedFontNum: integer; FontDef : TFontDef);
+var
+  FDict: TPDFDictionary;
+  N: TPDFName;
+
+begin
+  // add xref entry
+  FDict:=CreateGlobalXRef.Dict;
+  FDict.AddName('Type', 'Font');
+  FDict.AddName('Subtype', FontDef.FType);
+  FDict.AddName('Encoding', 'WinAnsiEncoding');
+  FDict.AddInteger('FirstChar', 32);
+  FDict.AddInteger('LastChar', 255);
+  FDict.AddName('BaseFont', FontDef.FName);
+  // add name element to font dictionary
+  N:=CreateName('F'+IntToStr(EmbeddedFontNum));
+  FDict.AddElement('Name',N);
+  Self.AddFontNameToPages(N.Name,GlobalXRefCount-1);
+  CreateFontDescriptor(EmbeddedFontNum,FontDef);
+  // add fontdescriptor reference to font dictionary
+  FDict.AddReference('FontDescriptor',GlobalXRefCount-2);
+  CreateFontWidth(FontDef);
+  // add fontwidth reference to font dictionary
+  FDict.AddReference('Widths',GlobalXRefCount-1);
+  CreateToUnicode(EmbeddedFontNum, FontDef);
+  FDict.AddReference('ToUnicode', GlobalXRefCount-1);
+  FontFiles.Add(FontDef.FFile);
+end;
+
+procedure TPDFDocument.CreateTp1Font(const EmbeddedFontNum: integer);
+begin
+  Assert(EmbeddedFontNum<>-1);
+end;
+
+procedure TPDFDocument.CreateFontDescriptor(const EmbeddedFontNum: integer; FontDef : TFontDef);
+
+var
+  Arr: TPDFArray;
+  FDict: TPDFDictionary;
+
+begin
+  FDict:=CreateGlobalXRef.Dict;
+  FDict.AddName('Type', 'FontDescriptor');
+  FDict.AddName('FontName', FontDef.FName);
+  FDict.AddInteger('Ascent', StrToInt(FontDef.FAscent));
+  FDict.AddInteger('Descent', StrToInt(FontDef.FDescent));
+  FDict.AddInteger('CapHeight', StrToInt(FontDef.FCapHeight));
+  FDict.AddInteger('Flags', StrToInt(FontDef.FFlags));
+  Arr:=CreateArray;
+  FDict.AddElement('FontBBox',Arr);
+  Arr.AddIntArray(FontDef.FFontBBox);
+  FDict.AddInteger('ItalicAngle',StrToInt(FontDef.FItalicAngle));
+  FDict.AddInteger('StemV',StrToInt(FontDef.FStemV));
+  FDict.AddInteger('MissingWidth', StrToInt(FontDef.FMissingWidth));
+  CreateFontFileEntry(EmbeddedFontNum,FontDef);
+  FDict.AddReference('FontFile2',GlobalXRefCount-1);
+end;
+
+procedure TPDFDocument.CreateToUnicode(const EmbeddedFontNum: integer; FontDef: TFontDef);
+var
+  lXRef: TPDFXRef;
+begin
+  lXRef := CreateGlobalXRef;
+  lXRef.FStream := CreateStream(True);
+  lXRef.FStream.AddItem(TPDFToUnicode.Create(self, EmbeddedFontNum, FontDef));
+end;
+
+
+procedure TPDFDocument.CreateFontWidth(FontDef : TFontDef);
+var
+  Arr: TPDFArray;
+  FDict: TPDFDictionary;
+
+begin
+  FDict:=CreateGlobalXRef.Dict;
+  Arr:=CreateArray;
+  FDict.AddElement('',Arr);
+  Arr.AddIntArray(FontDef.FCharWidth);
+end;
+
+procedure TPDFDocument.CreateFontFileEntry(const EmbeddedFontNum: integer;FontDef : TFontDef);
+
+var
+  FDict: TPDFDictionary;
+
+begin
+  FDict:=CreateGlobalXRef.Dict;
+  FDict.AddName('Filter','FlateDecode');
+  FDict.AddInteger('Length1 '+IntToStr(EmbeddedFontNum),StrToInt(FontDef.FOriginalSize));
+end;
+
+procedure TPDFDocument.CreateImageEntry(ImgWidth, ImgHeight, NumImg: integer);
+
+var
+  N: TPDFName;
+  IDict,ADict: TPDFDictionary;
+  i: integer;
+
+begin
+  IDict:=CreateGlobalXRef.Dict;
+  IDict.AddName('Type','XObject');
+  IDict.AddName('Subtype','Image');
+  IDict.AddInteger('Width',ImgWidth);
+  IDict.AddInteger('Height',ImgHeight);
+  IDict.AddName('ColorSpace','DeviceRGB');
+  IDict.AddInteger('BitsPerComponent',8);
+  N:=CreateName('I'+IntToStr(NumImg)); // Needed later
+  IDict.AddElement('Name',N);
+  for i:=1 to GLobalXRefCount-1 do
+    begin
+    ADict:=GlobalXRefs[i].Dict;
+    if ADict.ElementCount > 0 then
+      begin
+      if (ADict.Values[0] is TPDFName) and ((ADict.Values[0] as TPDFName).Name='Page') then
+        begin
+        ADict:=ADict.ValueByName('Resources') as TPDFDictionary;
+        ADict:=TPDFDictionary(ADict.FindValue('XObject'));
+        if Assigned(ADict) then
+          begin
+          ADict.AddReference(N.Name,GLobalXRefCount-1);
+          end;
+        end;
+      end;
+    end;
+end;
+
+function TPDFDocument.CreateContentsEntry: integer;
+var
+  Contents: TPDFXRef;
+
+begin
+  Contents:=CreateGlobalXRef;
+  Contents.FStream:=CreateStream(False);
+  Result:=GLobalXRefCount-1;
+  GLobalXrefs[GLobalXRefCount-2].Dict.AddReference('Contents',Result);
+end;
+
+procedure TPDFDocument.CreatePageStream(APage : TPDFPage; PageNum: integer);
+
+var
+  i: integer;
+  PageStream : TPDFStream;
+
+begin
+  PageStream:=GlobalXRefs[PageNum].FStream;
+  for i:=0 to APage.ObjectCount-1 do
+    begin
+    PageStream.AddItem(APage.Objects[i]);
+    end;
+end;
+
+function TPDFDocument.CreateGlobalXRef: TPDFXRef;
+begin
+  Result:=Self.CreateXRef;
+  AddGlobalXRef(Result);
+end;
+
+function TPDFDocument.AddGlobalXRef(AXRef: TPDFXRef): Integer;
+begin
+  Result:=FGlobalXRefs.Add(AXRef);
+end;
+
+
+function TPDFDocument.GlobalXRefByName(const AName: String): TPDFXRef;
+begin
+  Result:=FindGlobalXRef(AName);
+  if Result=Nil then
+    Raise EPDF.CreateFmt(SErrNoGlobalDict,[AName]);
+end;
+
+constructor TPDFDocument.Create(AOwner : TComponent);
+begin
+  inherited Create(AOwner);
+  FLineStyleDefs:=TPDFLineStyleDefs.Create(TPDFLineStyleDef);
+  FSections:=TPDFSectionList.Create(TPDFSection);
+  FFontFiles:=TStringList.Create;
+  FFonts:=TPDFFontDefs.Create(TPDFFont);
+  FInfos:=TPDFInfos.Create;
+  FImages:=TPDFImages.Create(TPDFImageItem);
+  FPages:=TPDFPages.Create(Self);
+  FPreferences:=True;
+  FPageLayout:=lSingle;
+  FDefaultPaperType:=ptA4;
+  FDefaultOrientation:=ppoPortrait;
+  FZoomValue:='100';
+  FOptions := [poCompressFonts];
+end;
+
+procedure TPDFDocument.StartDocument;
+
+begin
+  CreateRefTable;
+  CreateTrailer;
+  FCatalogue:=CreateCatalogEntry;
+  CreateInfoEntry;
+  CreatePreferencesEntry;
+  if (FontDirectory = '') then
+    FontDirectory:=ExtractFilePath(ParamStr(0));
+end;
+
+destructor TPDFDocument.Destroy;
+
+begin
+  FreeAndNil(FLineStyleDefs);
+  FreeAndNil(FInfos);
+  FreeAndNil(FFonts);
+  FreeAndNil(FImages);
+  FreeAndNil(FFontFiles);
+  FreeAndNil(FPages);
+  FreeAndNil(FSections);
+  Trailer.Free;
+  FGlobalXRefs.Free;
+  inherited;
+end;
+
+function TPDFDocument.CreateSectionPageOutLine(const S: TPDFSection;
+  const PageOutLine, PageIndex, NewPage, ParentOutline, NextOutline,
+  PrevOutLine: Integer): Integer; // Return pages ID
+
+Var
+  ADict: TPDFDictionary;
+  Arr : TPDFArray;
+
+begin
+  ADict:=GlobalXRefs[ParentOutline].Dict;
+  (ADict.ValueByName('Count') as TPDFInteger).Inc;
+  // add page reference to outline destination
+  ADict:=GlobalXRefs[PageOutLine].Dict;
+  Arr:=(ADict.ValueByName('Dest') as TPDFArray);
+  Arr.AddItem(CreateReference(NewPage));
+  Arr.AddItem(CreateName('Fit'));
+  Result:=PrevOutline;
+  if PageIndex=0 then
+    begin
+    GlobalXRefs[ParentOutline].Dict.AddReference('First',GLobalXRefCount-1);
+    Result:=GLobalXRefCount-1;
+    // add page reference to parent outline destination
+    ADict:=GlobalXRefs[ParentOutline].Dict;
+    Arr:=(ADict.ValueByName('Dest') as TPDFArray);
+    Arr.AddItem(CreateReference(NewPage));
+    Arr.AddItem(CreateName('Fit'));
+    end
+  else
+    begin
+    GlobalXRefs[NextOutline].Dict.AddReference('Next',GLobalXRefCount-1);
+    GlobalXRefs[PageOutLine].Dict.AddReference('Prev',PrevOutline);
+    if (PageIndex<S.PageCount) then
+      Result:=GLobalXRefCount-1;
+    end;
+  if PageIndex=S.PageCount-1 then
+    GlobalXRefs[ParentOutline].Dict.AddReference('Last',GLobalXRefCount-1);
+end;
+
+function TPDFDocument.CreateSectionOutLine(const SectionIndex, OutLineRoot,
+  ParentOutLine, NextSect, PrevSect: Integer): Integer; // Previous section
+
+Var
+  ADict: TPDFDictionary;
+
+begin
+  Result:=PrevSect;
+  ADict:=GlobalXRefs[OutlineRoot].Dict;
+  (ADict.ValueByName('Count') as TPDFInteger).Inc;
+  if (SectionIndex=0) then
+    begin
+    GlobalXRefs[OutlineRoot].Dict.AddReference('First',GLobalXRefCount-1);
+    Result:=GLobalXRefCount-1;
+    end
+  else
+    begin
+    GlobalXRefs[NextSect].Dict.AddReference('Next',GLobalXRefCount-1);
+    GlobalXRefs[ParentOutline].Dict.AddReference('Prev', PrevSect);
+    if (SectionIndex<Sections.Count-1) then
+      Result:=GLobalXRefCount-1;
+    end;
+  if SectionIndex=Sections.Count-1 then
+    GlobalXRefs[OutlineRoot].Dict.AddReference('Last',GLobalXRefCount-1);
+end;
+
+function TPDFDocument.CreateSectionsOutLine: Integer; // Parent page ID
+
+var
+  pc,j: integer;
+  ParentOutline,TreeRoot,OutlineRoot : Integer;
+  K,PageNum: integer;
+  PageOutline, NextOutline, NextSect, NewPage, PrevOutline, PrevSect: integer;
+  ADict: TPDFDictionary;
+  Arr : TPDFArray;
+  S : TPDFSection;
+
+begin
+  Result:=0;
+  TreeRoot:=0;
+  if (Sections.Count>1) then
+    begin
+    If (poOutline in Options) then
+      begin
+      OutlineRoot:=CreateOutlines;
+      // add outline reference to catalog dictionary
+      GlobalXRefs[Catalogue].Dict.AddReference('Outlines',GLobalXRefCount-1);
+      // add useoutline element to catalog dictionary
+      GlobalXRefs[Catalogue].Dict.AddName('PageMode','UseOutlines');
+      end;
+    TreeRoot:=CreatePagesEntry(Result);
+    end
+  else
+    begin
+    Result:=CreatePagesEntry(Result);
+    TreeRoot:=Result;
+    end;
+
+  NextSect:=0;
+  PrevSect:=0;
+  PrevOutLine:=0;
+  NextOutLine:=0;
+  for J:=0 to Sections.Count-1 do
+    begin
+    S:=Sections[J];
+    if (poOutline in options) then
+      begin
+      ParentOutline:=CreateOutlineEntry(OutlineRoot,j+1,-1,S.Title);
+      PrevSect:=CreateSectionOutline(J,OutlineRoot,ParentOutLine,NextSect,PrevSect);
+      NextSect:=ParentOutline;
+      Result:=CreatePagesEntry(TreeRoot);
+      end;
+    for k:=0 to S.PageCount-1 do
+      begin
+      with S do
+        NewPage:=CreatePageEntry(Result,K);
+      // add zoom factor to catalog dictionary
+      if (j=0) and (k=0) then
+        begin
+        ADict:=GlobalXRefByName('Catalog').Dict;
+        Arr:=ADict.ValueByName('OpenAction') as TPDFArray;
+        Arr.AddItem(CreateReference(GLobalXRefCount-1));
+        Arr.AddItem(CreateName('XYZ null null '+TPDFObject.FloatStr(StrToInt(FZoomValue) / 100)));
+        end;
+      PageNum:=CreateContentsEntry; // pagenum = object number in the pdf file
+      CreatePageStream(S.Pages[k],PageNum);
+      if (Sections.Count>1) and (poOutline in Options) then
+        begin
+        PageOutLine:=CreateOutlineEntry(ParentOutline,j+1,k+1,S.Title);
+        CreateSectionPageOutLine(S,PageOutLine,K,NewPage,ParentOutLine,NextOutLine,PrevOutLine);
+        NextOutline:=PageOutLine;
+        end;
+    end;
+  end;
+  // update count in root parent pages dictionary
+  ADict:=GlobalXRefs[TreeRoot].Dict;
+  Pc:=0;
+  For J:=0 to Sections.Count-1 do
+    Inc(Pc,Sections[J].PageCount);
+  (ADict.ValueByName('Count') as TPDFInteger).Value:=PC;
+end;
+
+procedure TPDFDocument.CreateFontEntries;
+
+var
+  i,p: integer;
+  NumFont: integer;
+  FontName, FtName: string;
+  FontDef : TFontDef;
+
+begin
+  // select the font type
+  NumFont:=0;
+  for i:=0 to Fonts.Count-1 do
+    begin
+    FontName:=ExtractBaseFontName(Fonts[i].Name);
+    P:=Pos('-', FontName);
+    if P>0 then
+      FtName:=LowerCase(Copy(FontName,1,P-1))
+    else
+      FtName:=LowerCase(FontName);
+    if (FtName='courier') or (FtName='helvetica') or (FtName='times') then
+      begin
+      FontName[1]:=UpCase(FontName[1]);
+      CreateStdFont(FontName,NumFont);
+      end
+    else if (LoadFont(Fonts[i], FontDef)='TrueType') then
+      CreateTtfFont(NumFont,FontDef)
+    else
+      CreateTp1Font(NumFont);  // not implemented yet
+    Inc(NumFont);
+    end;
+end;
+
+procedure TPDFDocument.CreateImageEntries;
+
+Var
+  I : Integer;
+
+begin
+  for i:=0 to Images.Count-1 do
+    CreateImageEntry(Images[i].Width,Images[i].Height,i);
+end;
+
+procedure TPDFDocument.SaveToStream(const AStream: TStream);
+
+var
+  i, XRefPos: integer;
+
+begin
+  CreateSectionsOutLine;
+  CreateFontEntries;
+  CreateImageEntries;
+  (Trailer.ValueByName('Size') as TPDFInteger).Value:=GlobalXRefCount;
+  AStream.Position:=0;
+  TPDFObject.WriteString(PDF_VERSION+CRLF, AStream);
+  // write numbered indirect objects
+  for i:=1 to GlobalXRefCount-1 do
+    begin
+    XRefPos:=AStream.Position;
+    WriteObject(i, AStream);
+    GlobalXRefs[i].Offset:=XRefPos;
+    end;
+  XRefPos:=AStream.Position;
+  // write xref table
+  TPDFObject.WriteString('xref'+CRLF+'0 '+IntToStr(GlobalXRefCount)+CRLF, AStream);
+  with GlobalXRefs[0] do
+    TPDFObject.WriteString(FormatPDFInt(Offset, 10)+' '+FormatPDFInt(PDF_MAX_GEN_NUM, 5)+' f'+CRLF, AStream);
+  WriteXRefTable(AStream);
+  // write trailer
+  TPDFObject.WriteString('trailer'+CRLF, AStream);
+  Trailer.Write(AStream);
+  // write offset of last xref table
+  TPDFObject.WriteString(CRLF+'startxref'+CRLF+IntToStr(XRefPos)+CRLF, AStream);
+  TPDFObject.WriteString(PDF_FILE_END, AStream);
+end;
+
+function TPDFDocument.CreateEmbeddedFont(AFontIndex, AFontSize : Integer): TPDFEmbeddedFont;
+begin
+  Result:=TPDFEmbeddedFont.Create(Self,AFontIndex,IntToStr(AFontSize))
+end;
+
+function TPDFDocument.CreateText(X, Y: TPDFFloat; AText: String): TPDFText;
+begin
+  Result:=TPDFText.Create(Self,X,Y,AText);
+end;
+
+function TPDFDocument.CreateUTF8Text(X, Y: TPDFFloat; AText: UTF8String; const AFontIndex: integer): TPDFUTF8Text;
+begin
+  Result := TPDFUTF8Text.Create(Self,X,Y,AText,AFontIndex);
+end;
+
+function TPDFDocument.CreateRectangle(const X,Y,W,H, ALineWidth: TPDFFloat; const AFill, AStroke: Boolean): TPDFRectangle;
+begin
+  Result:=TPDFRectangle.Create(Self,X,Y,W,H,ALineWidth,AFill, AStroke);
+end;
+
+function TPDFDocument.CreateColor(AColor: TARGBColor; AStroke: Boolean
+  ): TPDFColor;
+begin
+  Result:=TPDFColor.Create(Self,AStroke,AColor);
+end;
+
+function TPDFDocument.CreateBoolean(AValue: Boolean): TPDFBoolean;
+begin
+  Result:=TPDFBoolean.Create(Self,AValue);
+end;
+
+function TPDFDocument.CreateInteger(AValue: Integer): TPDFInteger;
+begin
+  Result:=TPDFInteger.Create(Self,AValue);
+end;
+
+function TPDFDocument.CreateReference(AValue: Integer): TPDFReference;
+begin
+  Result:=TPDFReference.Create(Self,AValue);
+end;
+
+function TPDFDocument.CreateString(const AValue: String): TPDFString;
+begin
+  Result:=TPDFString.Create(Self,AValue);
+end;
+
+function TPDFDocument.CreateUTF8String(const AValue: UTF8String; const AFontIndex: integer): TPDFUTF8String;
+begin
+  Result := TPDFUTF8String.Create(self, AValue, AFontIndex);
+end;
+
+function TPDFDocument.CreateLineStyle(APenStyle: TPDFPenStyle): TPDFLineStyle;
+begin
+  Result:=TPDFLineStyle.Create(Self,APenStyle,0)
+end;
+
+function TPDFDocument.CreateName(AValue: String): TPDFName;
+begin
+  Result:=TPDFName.Create(Self,AValue);
+end;
+
+function TPDFDocument.CreateStream(OwnsObjects : Boolean = True): TPDFStream;
+begin
+  Result:=TPDFStream.Create(Self,OwnsObjects);
+end;
+
+function TPDFDocument.CreateDictionary: TPDFDictionary;
+begin
+  Result:=TPDFDictionary.Create(Self);
+end;
+
+function TPDFDocument.CreateXRef: TPDFXRef;
+begin
+  Result:=TPDFXRef.Create(Self);
+end;
+
+function TPDFDocument.CreateArray: TPDFArray;
+begin
+  Result:=TPDFArray.Create(Self);
+end;
+
+function TPDFDocument.CreateImage(const ALeft, ABottom: TPDFFloat; AWidth,
+  AHeight, ANumber: integer): TPDFImage;
+begin
+  Result:=TPDFImage.Create(Self,ALeft,ABottom,AWidth,AHeight,ANumber);
+end;
+
+function TPDFDocument.AddFont(AName: String; AColor : TARGBColor = clBlack): Integer;
+Var
+  F : TPDFFont;
+
+begin
+  F:=Fonts.AddFontDef;
+  F.Name:=AName;
+  F.Color:=AColor;
+  Result:=Fonts.Count-1;
+end;
+
+function TPDFDocument.AddFont(AFontFile: String; AName: String; AColor: TARGBColor): Integer;
+Var
+  F : TPDFFont;
+begin
+  F:=Fonts.AddFontDef;
+  F.FontFile := AFontFile;
+  F.Name := AName;
+  F.Color := AColor;
+  Result := Fonts.Count-1;
+end;
+
+function TPDFDocument.AddLineStyleDef(ALineWidth: TPDFFloat; AColor: TARGBColor;
+  APenStyle: TPDFPenStyle): Integer;
+
+Var
+  F : TPDFLineStyleDef;
+
+begin
+  F:=FLineStyleDefs.AddLineStyleDef;
+  F.LineWidth:=ALineWidth;
+  F.Color:=AColor;
+  F.PenStyle:=APenStyle;
+  Result:=FLineStyleDefs.Count-1;
+end;
+
+end.
+

+ 480 - 0
packages/fcl-pdf/src/fpttf.pp

@@ -0,0 +1,480 @@
+{
+    Description:
+      This is a homegrown font cache. The fpReport reports can reference
+      a font by its name. The job of the font cache is to look through
+      its cached fonts to match the font name, and which *.ttf file it
+      relates too. The reporting code can then extract font details
+      correctly (eg: font width, height etc).
+}
+unit fpTTF;
+
+{$mode objfpc}{$H+}
+
+{.$define ttfdebug}
+
+interface
+
+uses
+  Classes,
+  SysUtils,
+  contnrs,
+  fpparsettf;
+
+const
+  { constants to query FontCacheItem.StyleFlags with. }
+  FP_FONT_STYLE_REGULAR = 1 shl 0;     { Regular, Plain, Book }
+  FP_FONT_STYLE_ITALIC = 1 shl 1;      { Italic }
+  FP_FONT_STYLE_BOLD = 1 shl 2;        { Bold }
+  FP_FONT_STYLE_CONDENSED = 1 shl 3;   { Condensed }
+  FP_FONT_STYLE_EXTRALIGHT = 1 shl 4;  { ExtraLight }
+  FP_FONT_STYLE_LIGHT = 1 shl 5;       { Light }
+  FP_FONT_STYLE_SEMIBOLD = 1 shl 6;    { Semibold }
+  FP_FONT_STYLE_MEDIUM = 1 shl 7;      { Medium }
+  FP_FONT_STYLE_BLACK = 1 shl 8;       { Black }
+  FP_FONT_STYLE_FIXEDWIDTH = 1 shl 9;  { Fixedwidth }
+
+type
+  { Forward declaration }
+  TFPFontCacheList = class;
+
+
+  TFPFontCacheItem = class(TObject)
+  private
+    FFamilyName: String;
+    FFileName: String;
+    FStyleFlags: LongWord;
+    FOwner: TFPFontCacheList; // reference to FontCacheList that owns this instance
+    function    GetIsBold: boolean;
+    function    GetIsFixedWidth: boolean;
+    function    GetIsItalic: boolean;
+    function    GetIsRegular: boolean;
+    procedure   SetIsBold(AValue: boolean);
+    procedure   SetIsFixedWidth(AValue: boolean);
+    procedure   SetIsItalic(AValue: boolean);
+    procedure   SetIsRegular(AValue: boolean);
+  public
+    constructor Create(const AFilename: String);
+    { Returns the actual TTF font file information. Caller needs to free the returned instance. }
+    function    GetFontData: TTFFileInfo;
+    { Result is in pixels }
+    function    TextWidth(AStr: string; APointSize: single): single;
+    property    FileName: String read FFileName write FFileName;
+    property    FamilyName: String read FFamilyName write FFamilyName;
+    { A bitmasked value describing the full font style }
+    property    StyleFlags: LongWord read FStyleFlags write FStyleFlags;
+    { IsXXX properties are convenience properties, internally querying StyleFlags. }
+    property    IsFixedWidth: boolean read GetIsFixedWidth write SetIsFixedWidth;
+    property    IsRegular: boolean read GetIsRegular write SetIsRegular;
+    property    IsItalic: boolean read GetIsItalic write SetIsItalic;
+    property    IsBold: boolean read GetIsBold write SetIsBold;
+  end;
+
+
+  TFPFontCacheList = class(TObject)
+  private
+    FList: TObjectList;
+    FSearchPath: TStringList;
+    FDPI: integer;
+    procedure   SearchForFont(const AFontPath: String);
+    function    BuildFontCacheItem(const AFontFile: String): TFPFontCacheItem;
+    procedure   SetStyleIfExists(var AText: string; var AStyleFlags: integer; const AStyleName: String; const AStyleBit: integer);
+    procedure   SetDPI(AValue: integer);
+  protected
+    function    GetCount: integer; virtual;
+    function    GetItem(AIndex: Integer): TFPFontCacheItem; virtual;
+    procedure   SetItem(AIndex: Integer; AValue: TFPFontCacheItem); virtual;
+  public
+    constructor Create;
+    destructor  Destroy; override;
+    procedure   BuildFontCache;
+    function    Add(const AObject: TFPFontCacheItem): integer;
+    procedure   Clear;
+    property    Count: integer read GetCount;
+    function    IndexOf(const AObject: TFPFontCacheItem): integer;
+    function    Find(const AFontCacheItem: TFPFontCacheItem): integer;
+    function    Find(const AFamilyName: string; ABold: boolean = False; AItalic: boolean = False): TFPFontCacheItem;
+    { not used: utility function doing a conversion for use. }
+    function    PointSizeInPixels(const APointSize: single): single;
+    property    Items[AIndex: Integer]: TFPFontCacheItem read GetItem write SetItem; default;
+    property    SearchPath: TStringList read FSearchPath;
+    property    DPI: integer read FDPI write SetDPI;
+  end;
+
+
+function gTTFontCache: TFPFontCacheList;
+
+implementation
+
+resourcestring
+  rsNoSearchPathDefined = 'No search path was defined';
+  rsNoFontFileName = 'The FileName property is empty, so we can''t load font data.';
+
+type
+  { so we can get access to protected methods }
+  TFriendTTFFileInfo = class(TTFFileInfo);
+
+var
+  uFontCacheList: TFPFontCacheList;
+
+function gTTFontCache: TFPFontCacheList;
+begin
+ if not Assigned(uFontCacheList) then
+ begin
+   uFontCacheList := TFPFontCacheList.Create;
+ end;
+ Result := uFontCacheList;
+end;
+
+{ TFPFontCacheItem }
+
+function TFPFontCacheItem.GetIsBold: boolean;
+begin
+  Result := (FStyleFlags and FP_FONT_STYLE_BOLD) <> 0;
+end;
+
+function TFPFontCacheItem.GetIsFixedWidth: boolean;
+begin
+  Result := (FStyleFlags and FP_FONT_STYLE_FIXEDWIDTH) <> 0;
+end;
+
+function TFPFontCacheItem.GetIsItalic: boolean;
+begin
+  Result := (FStyleFlags and FP_FONT_STYLE_ITALIC) <> 0;
+end;
+
+function TFPFontCacheItem.GetIsRegular: boolean;
+begin
+  Result := (FStyleFlags and FP_FONT_STYLE_REGULAR) <> 0;
+end;
+
+procedure TFPFontCacheItem.SetIsBold(AValue: boolean);
+begin
+  if AValue then
+    FStyleFlags := FStyleFlags or FP_FONT_STYLE_BOLD
+  else
+    FStyleFlags := FStyleFlags and (not FP_FONT_STYLE_BOLD);
+end;
+
+procedure TFPFontCacheItem.SetIsFixedWidth(AValue: boolean);
+begin
+  if AValue then
+    FStyleFlags := FStyleFlags or FP_FONT_STYLE_FIXEDWIDTH
+  else
+    FStyleFlags := FStyleFlags and (not FP_FONT_STYLE_FIXEDWIDTH);
+
+  // if we are FixedWidth, then Regular can't apply
+  FStyleFlags := FStyleFlags and (not FP_FONT_STYLE_REGULAR);
+end;
+
+procedure TFPFontCacheItem.SetIsItalic(AValue: boolean);
+begin
+  if AValue then
+    FStyleFlags := FStyleFlags or FP_FONT_STYLE_ITALIC
+  else
+    FStyleFlags := FStyleFlags and (not FP_FONT_STYLE_ITALIC);
+end;
+
+procedure TFPFontCacheItem.SetIsRegular(AValue: boolean);
+begin
+  if AValue then
+    FStyleFlags := FStyleFlags or FP_FONT_STYLE_REGULAR
+  else
+    FStyleFlags := FStyleFlags and (not FP_FONT_STYLE_REGULAR);
+
+  // if we are Regular, then FixedWidth can't apply
+  FStyleFlags := FStyleFlags and (not FP_FONT_STYLE_FIXEDWIDTH);
+end;
+
+constructor TFPFontCacheItem.Create(const AFilename: String);
+begin
+  inherited Create;
+  FFileName := AFilename;
+  FStyleFlags := FP_FONT_STYLE_REGULAR;
+end;
+
+function TFPFontCacheItem.GetFontData: TTFFileInfo;
+begin
+  if FileName = '' then
+    raise ETTF.Create(rsNoFontFileName);
+  if FileExists(FileName) then
+  begin
+    Result := TTFFileInfo.Create;
+    Result.LoadFromFile(FileName);
+  end
+  else
+    Result := nil;
+end;
+
+{ TextWidth returns with width of the text. If APointSize = 0.0, then it returns
+  the text width in Font Units. If APointSize > 0 then it returns the text width
+  in Pixels. }
+function TFPFontCacheItem.TextWidth(AStr: string; APointSize: single): single;
+{
+    From Microsoft's Typography website:
+    Converting FUnits (font units) to pixels
+
+    Values in the em square are converted to values in the pixel coordinate system
+    by multiplying them by a scale. This scale is:
+
+    pointSize * resolution / ( 72 points per inch * units_per_em )
+
+    where pointSize is the size at which the glyph is to be displayed, and resolution
+    is the resolution of the output device. The 72 in the denominator reflects the
+    number of points per inch.
+
+    For example, assume that a glyph feature is 550 FUnits in length on a 72 dpi
+    screen at 18 point. There are 2048 units per em. The following calculation
+    reveals that the feature is 4.83 pixels long.
+
+    550 * 18 * 72 / ( 72 * 2048 ) = 4.83
+}
+var
+  lFntInfo: TFriendTTFFileInfo;
+  i: integer;
+  lWidth: integer;
+  lGIndex: integer;
+  c: Char;
+  {$IFDEF ttfdebug}
+  sl: TStringList;
+  s: string;
+  {$ENDIF}
+begin
+  Result := 0;
+  if Length(AStr) = 0 then
+    Exit;
+
+  lFntInfo := TFriendTTFFileInfo(GetFontData);
+  if not Assigned(lFntInfo) then
+    Exit;
+
+  {$IFDEF ttfdebug}
+    sl := TStringList.Create;
+    s := '';
+    for i := 0 to 255 do
+    begin
+      lGIndex := lFntInfo.GetGlyphIndex(i);
+      lWidth := lFntInfo.GetAdvanceWidth(lGIndex);
+      s := s + ',' + IntToStr(lWidth);
+    end;
+    sl.Add(s);
+    sl.Add('UnitsPerEm = ' + IntToStr(lFntInfo.Head.UnitsPerEm));
+    sl.SaveToFile('/tmp/' + lFntInfo.PostScriptName + '.txt');
+    sl.Free;
+  {$ENDIF}
+
+  try
+    lWidth := 0;
+    for i := 1 to Length(AStr) do
+    begin
+      c := AStr[i];
+      lGIndex := lFntInfo.GetGlyphIndex(Ord(c));
+      lWidth := lWidth + lFntInfo.GetAdvanceWidth(lGIndex);
+    end;
+
+    if APointSize = 0.0 then
+      Result := lWidth
+    else
+    begin
+      { Converting Font Units to Pixels. The formula is:
+        pixels = glyph_units * pointSize * resolution / ( 72 points per inch * THead.UnitsPerEm )  }
+      Result := lWidth * APointSize * FOwner.DPI / (72 * lFntInfo.Head.UnitsPerEm);
+    end;
+  finally
+    lFntInfo.Free;
+  end;
+end;
+
+{ TFPFontCacheList }
+
+procedure TFPFontCacheList.SearchForFont(const AFontPath: String);
+var
+  sr: TSearchRec;
+  lFont: TFPFontCacheItem;
+  s: String;
+begin
+  if FindFirst(AFontPath + AllFilesMask, faAnyFile, sr) = 0 then
+  begin
+    repeat
+      // check if special files to skip
+      if (sr.Name = '.') or (sr.Name = '..') or (sr.Name = '') then
+        Continue;
+      // We got something, so lets continue
+      s := sr.Name;
+      if (sr.Attr and faDirectory) <> 0 then // found a directory
+        SearchForFont(IncludeTrailingPathDelimiter(AFontPath + s))
+      else
+      begin // we have a file
+        if (lowercase(ExtractFileExt(s)) = '.ttf') or
+           (lowercase(ExtractFileExt(s)) = '.otf') then
+        begin
+          lFont := BuildFontCacheItem(AFontPath + s);
+          Add(lFont);
+        end;
+      end;
+    until FindNext(sr) <> 0;
+  end;
+  FindClose(sr);
+end;
+
+function TFPFontCacheList.BuildFontCacheItem(const AFontFile: String): TFPFontCacheItem;
+var
+  lFontInfo: TTFFileInfo;
+  s: string;
+  flags: integer;
+begin
+  lFontInfo := TTFFileInfo.Create;
+  try
+    lFontInfo.LoadFromFile(AFontFile);
+
+    Result := TFPFontCacheItem.Create(AFontFile);
+    s := lFontInfo.PostScriptName;
+    Result.FamilyName := lFontInfo.FamilyName;
+
+    // extract simple styles first
+    if lFontInfo.PostScript.isFixedPitch > 0 then
+      Result.StyleFlags := FP_FONT_STYLE_FIXEDWIDTH; // this should overwrite Regular style
+
+    if lFontInfo.PostScript.ItalicAngle <> 0 then
+      Result.StyleFlags := Result.StyleFlags or FP_FONT_STYLE_ITALIC;
+
+    // Now to more complex styles stored in StyleName field. eg: 'Condensed Medium'
+    flags := Result.StyleFlags;
+    SetStyleIfExists(s, flags, 'Bold', FP_FONT_STYLE_BOLD);
+    SetStyleIfExists(s, flags, 'Condensed', FP_FONT_STYLE_CONDENSED);
+    SetStyleIfExists(s, flags, 'ExtraLight', FP_FONT_STYLE_EXTRALIGHT);
+    SetStyleIfExists(s, flags, 'Light', FP_FONT_STYLE_LIGHT);
+    SetStyleIfExists(s, flags, 'Semibold', FP_FONT_STYLE_SEMIBOLD);
+    SetStyleIfExists(s, flags, 'Medium', FP_FONT_STYLE_MEDIUM);
+    SetStyleIfExists(s, flags, 'Black', FP_FONT_STYLE_BLACK);
+    Result.StyleFlags := flags;
+  finally
+    lFontInfo.Free;
+  end;
+end;
+
+procedure TFPFontCacheList.SetStyleIfExists(var AText: string; var AStyleFlags: integer; const AStyleName: String;
+  const AStyleBit: integer);
+var
+  i: integer;
+begin
+  i := Pos(AStyleName, AText);
+  if i > 0 then
+  begin
+    AStyleFlags := AStyleFlags or AStyleBit;
+    Delete(AText, Length(AStyleName), i);
+  end;
+end;
+
+procedure TFPFontCacheList.SetDPI(AValue: integer);
+begin
+  if FDPI = AValue then Exit;
+  FDPI := AValue;
+end;
+
+function TFPFontCacheList.GetCount: integer;
+begin
+  Result := FList.Count;
+end;
+
+function TFPFontCacheList.GetItem(AIndex: Integer): TFPFontCacheItem;
+begin
+  Result := TFPFontCacheItem(FList.Items[AIndex]);
+end;
+
+procedure TFPFontCacheList.SetItem(AIndex: Integer; AValue: TFPFontCacheItem);
+begin
+  FList.Items[AIndex] := AValue;
+end;
+
+constructor TFPFontCacheList.Create;
+begin
+  inherited Create;
+  FList := TObjectList.Create;
+  FSearchPath := TStringList.Create;
+  FDPI := 96; // The default is the most common dpi used
+end;
+
+destructor TFPFontCacheList.Destroy;
+begin
+  FList.Free;
+  FSearchPath.Free;
+  inherited Destroy;
+end;
+
+procedure TFPFontCacheList.BuildFontCache;
+var
+  lPath: String;
+  i: integer;
+begin
+  if FSearchPath.Count < 1 then
+    raise ETTF.Create(rsNoSearchPathDefined);
+
+  for i := 0 to FSearchPath.Count-1 do
+  begin
+    lPath := FSearchPath[i];
+    SearchForFont(IncludeTrailingPathDelimiter(lPath));
+  end;
+end;
+
+function TFPFontCacheList.Add(const AObject: TFPFontCacheItem): integer;
+begin
+  Result := FList.Add(AObject);
+  AObject.FOwner := self;
+end;
+
+procedure TFPFontCacheList.Clear;
+begin
+  FList.Clear;
+end;
+
+function TFPFontCacheList.IndexOf(const AObject: TFPFontCacheItem): integer;
+begin
+  Result := FList.IndexOf(AObject);
+end;
+
+function TFPFontCacheList.Find(const AFontCacheItem: TFPFontCacheItem): integer;
+var
+  i: integer;
+begin
+  Result := -1; // nothing found
+  for i := 0 to Count-1 do
+  begin
+    if (Items[i].FamilyName = AFontCacheItem.FamilyName) and
+       (Items[i].StyleFlags = AFontCacheItem.StyleFlags) then
+    begin
+      Result := i;
+      exit;
+    end;
+  end;
+end;
+
+function TFPFontCacheList.Find(const AFamilyName: string; ABold: boolean; AItalic: boolean): TFPFontCacheItem;
+var
+  i: integer;
+begin
+  Result := nil;
+  for i := 0 to Count-1 do
+  begin
+    if (Items[i].FamilyName = AFamilyName) and (items[i].IsItalic = AItalic)
+        and (items[i].IsBold = ABold) then
+    begin
+      Result := Items[i];
+      exit;
+    end;
+  end;
+end;
+
+function TFPFontCacheList.PointSizeInPixels(const APointSize: single): single;
+begin
+  Result := APointSize * DPI / 72;
+end;
+
+
+initialization
+  uFontCacheList := nil;
+
+finalization
+  uFontCacheList.Free;
+
+end.
+

+ 2127 - 0
packages/fcl-pdf/src/fpttfencodings.pp

@@ -0,0 +1,2127 @@
+{
+    This file is part of the Free Component Library (FCL)
+    Copyright (c) 2014 by Michael Van Canneyt
+
+    This unit contains some common TTF encodings, needed to make differences with cp1525
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+unit fpttfencodings;
+
+{$mode objfpc}
+
+interface
+
+uses
+  SysUtils;
+
+Type
+  TTTFEncoding =
+    (teUnknown,tecp874,tecp1250,tecp1251,tecp1252,tecp1253,tecp1254,tecp1255,tecp1257,tecp1258,
+     teiso_8859_1,teiso_8859_2,teiso_8859_4,teiso_8859_5,teiso_8859_7,
+     teiso_8859_9, teiso_8859_11, teiso_8859_15, teiso_8859_16,
+     tekoi8_r,tekoi8_u);
+  TTTFEncodingNames = array[0..255] of string;
+  PTTFEncodingNames = ^TTTFEncodingNames;
+  TTTFEncodingValues = array[0..255] of Integer;
+  PTTFEncodingValues = ^TTTFEncodingValues;
+
+Procedure GetEncodingTables(E : TTTFEncoding; Out ANames: PTTFEncodingNames; Out AValues: PTTFEncodingValues);
+Function GetEncoding(AName : String) : TTTFEncoding;
+
+Implementation
+
+Function GetEncoding(AName : String) : TTTFEncoding;
+
+Var
+  Names : Array[TTTFEncoding] of string =
+  ('','cp874','cp1250','cp1251','cp1252','cp1253','cp1254','cp1255','cp1257','cp1258',
+   'iso_8859_1','iso_8859_2','iso_8859_4','iso_8859_5','iso_8859_7',
+   'iso_8859_9', 'iso_8859_11', 'iso_8859_15', 'iso_8859_16',
+   'koi8_r','koi8_u');
+
+begin
+  Result:=High(TTTFEncoding);
+  While (Result<>teUnknown) and (CompareText(Names[Result],Aname)<>0) do
+    Result:=Pred(Result);
+end;
+
+Const
+
+  cp874_n: TTTFEncodingNames =
+    ('.notdef',           '.notdef',          '.notdef',        '.notdef',            // 00 to 03
+     '.notdef',           '.notdef',          '.notdef',        '.notdef',            // 04 to 07
+     '.notdef',           '.notdef',          '.notdef',        '.notdef',            // 08 to 0B
+     '.notdef',           '.notdef',          '.notdef',        '.notdef',            // 0C to 0F
+     '.notdef',           '.notdef',          '.notdef',        '.notdef',            // 10 to 13
+     '.notdef',           '.notdef',          '.notdef',        '.notdef',            // 14 to 17
+     '.notdef',           '.notdef',          '.notdef',        '.notdef',            // 18 to 1B
+     '.notdef',           '.notdef',          '.notdef',        '.notdef',            // 1C to 1F
+     'space',             'exclam',           'quotedbl',       'numbersign',         // 20 to 23
+     'dollar',            'percent',          'ampersand',      'quotesingle',        // 24 to 27
+     'parenleft',         'parenright',       'asterisk',       'plus',               // 28 to 2B
+     'comma',             'hyphen',           'period',         'slash',              // 2C to 2F
+     'zero',              'one',              'two',            'three',              // 30 to 33
+     'four',              'five',             'six',            'seven',              // 34 to 37
+     'eight',             'nine',             'colon',          'semicolon',          // 38 to 3B
+     'less',              'equal',            'greater',        'question',           // 3C to 3F
+     'at',                'A',                'B',              'C',                  // 40 to 43
+     'D',                 'E',                'F',              'G',                  // 44 to 47
+     'H',                 'I',                'J',              'K',                  // 48 to 4B
+     'L',                 'M',                'N',              'O',                  // 4C to 4F
+     'P',                 'Q',                'R',              'S',                  // 50 to 53
+     'T',                 'U',                'V',              'W',                  // 54 to 57
+     'X',                 'Y',                'Z',              'bracketleft',        // 58 to 5B
+     'backslash',         'bracketright',     'asciicircum',    'underscore',         // 5C to 5F
+     'grave',             'a',                'b',              'c',                  // 60 to 63
+     'd',                 'e',                'f',              'g',                  // 64 to 67
+     'h',                 'i',                'j',              'k',                  // 68 to 6B
+     'l',                 'm',                'n',              'o',                  // 6C to 6F
+     'p',                 'q',                'r',              's',                  // 70 to 73
+     't',                 'u',                'v',              'w',                  // 74 to 77
+     'x',                 'y',                'z',              'braceleft',          // 78 to 7B
+     'bar',               'braceright',       'asciitilde',     '.notdef',            // 7C to 7F
+     'Euro',              '.notdef',          '.notdef',        '.notdef',            // 80 to 83
+     '.notdef',           'ellipsis',         '.notdef',        '.notdef',            // 84 to 87
+     '.notdef',           '.notdef',          '.notdef',        '.notdef',            // 88 to 8B
+     '.notdef',           '.notdef',          '.notdef',        '.notdef',            // 8C to 8F
+     '.notdef',           'quoteleft',        'quoteright',     'quotedblleft',       // 90 to 93
+     'quotedblright',     'bullet',           'endash',         'emdash',             // 94 to 97
+     '.notdef',           '.notdef',          '.notdef',        '.notdef',            // 98 to 9B
+     '.notdef',           '.notdef',          '.notdef',        '.notdef',            // 9C to 9F
+     'space',             'kokaithai',        'khokhaithai',    'khokhuatthai',       // A0 to A3
+     'khokhwaithai',      'khokhonthai',      'khorakhangthai', 'ngonguthai',         // A4 to A7
+     'chochanthai',       'chochingthai',     'chochangthai',   'sosothai',           // A8 to AB
+     'chochoethai',       'yoyingthai',       'dochadathai',    'topatakthai',        // AC to AF
+     'thothanthai',       'thonangmonthothai','thophuthaothai', 'nonenthai',          // B0 to B3
+     'dodekthai',         'totaothai',        'thothungthai',   'thothahanthai',      // B4 to B7
+     'thothongthai',      'nonuthai',         'bobaimaithai',   'poplathai',          // B8 to BB
+     'phophungthai',      'fofathai',         'phophanthai',    'fofanthai',          // BC to BF
+     'phosamphaothai',    'momathai',         'yoyakthai',      'roruathai',          // C0 to C3
+     'ruthai',            'lolingthai',       'luthai',         'wowaenthai',         // C4 to C7
+     'sosalathai',        'sorusithai',       'sosuathai',      'hohipthai',          // C8 to CB
+     'lochulathai',       'oangthai',         'honokhukthai',   'paiyannoithai',      // CC to CF
+     'saraathai',         'maihanakatthai',   'saraaathai',     'saraamthai',         // D0 to D3
+     'saraithai',         'saraiithai',       'sarauethai',     'saraueethai',        // D4 to D7
+     'sarauthai',         'sarauuthai',       'phinthuthai',    '.notdef',            // D8 to DB
+     '.notdef',           '.notdef',          '.notdef',        'bahtthai',           // DC to DF
+     'saraethai',         'saraaethai',       'saraothai',      'saraaimaimuanthai',  // E0 to E3
+     'saraaimaimalaithai','lakkhangyaothai',  'maiyamokthai',   'maitaikhuthai',      // E4 to E7
+     'maiekthai',         'maithothai',       'maitrithai',     'maichattawathai',    // E8 to EB
+     'thanthakhatthai',   'nikhahitthai',     'yamakkanthai',   'fongmanthai',        // EC to EF
+     'zerothai',          'onethai',          'twothai',        'threethai',          // F0 to F3
+     'fourthai',          'fivethai',         'sixthai',        'seventhai',          // F4 to F7
+     'eightthai',         'ninethai',         'angkhankhuthai', 'khomutthai',         // F8 to FB
+     '.notdef',           '.notdef',          '.notdef',        '.notdef');           // FC to FF
+
+const
+  cp874_v: TTTFEncodingValues =
+    (0,       1,       2,       3,       4,        5,       6,       7,         // 00 to 07
+     8,       9,       10,      11,      12,       13,      14,      15,        // 08 to 0F
+     16,      17,      18,      19,      20,       21,      22,      23,        // 10 to 17
+     24,      25,      26,      27,      28,       29,      30,      31,        // 18 to 1F
+     32,      33,      34,      35,      36,       37,      38,      39,        // 20 to 27
+     40,      41,      42,      43,      44,       45,      46,      47,        // 28 to 2F
+     48,      49,      50,      51,      52,       53,      54,      55,        // 30 to 37
+     56,      57,      58,      59,      60,       61,      62,      63,        // 38 to 3F
+     64,      65,      66,      67,      68,       69,      70,      71,        // 40 to 47
+     72,      73,      74,      75,      76,       77,      78,      79,        // 48 to 4F
+     80,      81,      82,      83,      84,       85,      86,      87,        // 50 to 57
+     88,      89,      90,      91,      92,       93,      94,      95,        // 58 to 5F
+     96,      97,      98,      99,      100,      101,     102,     103,       // 60 to 67
+     104,     105,     106,     107,     108,      109,     110,     111,       // 68 to 6F
+     112,     113,     114,     115,     116,      117,     118,     119,       // 70 to 77
+     120,     121,     122,     123,     124,      125,     126,     127,       // 78 to 7F
+     8364,    -1,      -1,      -1,      -1,       8230,    -1,      -1,        // 80 to 87
+     -1,      -1,      -1,      -1,      -1,       -1,      -1,      -1,        // 88 to 8F
+     -1,      8216,    8217,    8220,    8221,     8226,    8211,    8212,      // 90 to 97
+     -1,      -1,      -1,      -1,      -1,       -1,      -1,      -1,        // 98 to 9F
+     160,     3585,    3586,    3587,    3588,     3589,    3590,    3591,      // A0 to A7
+     3592,    3593,    3594,    3595,    3596,     3597,    3598,    3599,      // A8 to AF
+     3600,    3601,    3602,    3603,    3604,     3605,    3606,    3607,      // B0 to B7
+     3608,    3609,    3610,    3611,    3612,     3613,    3614,    3615,      // B8 to BF
+     3616,    3617,    3618,    3619,    3620,     3621,    3622,    3623,      // C0 to C7
+     3624,    3625,    3626,    3627,    3628,     3629,    3630,    3631,      // C8 to CF
+     3632,    3633,    3634,    3635,    3636,     3637,    3638,    3639,      // D0 to D7
+     3640,    3641,    3642,    -1,      -1,       -1,      -1,      3647,      // D8 to DF
+     3648,    3649,    3650,    3651,    3652,     3653,    3654,    3655,      // E0 to E7
+     3656,    3657,    3658,    3659,    3660,     3661,    3662,    3663,      // E8 to EF
+     3664,    3665,    3666,    3667,    3668,     3669,    3670,    3671,      // F0 to F7
+     3672,    3673,    3674,    3675,    -1,       -1,      -1,      -1);       // F8 to FF
+
+const
+  cp1250_n: TTTFEncodingNames =
+    ('.notdef',       '.notdef',      '.notdef',        '.notdef',            // 00 to 03
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 04 to 07
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 08 to 0B
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 0C to 0F
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 10 to 13
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 14 to 17
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 18 to 1B
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 1C to 1F
+     'space',         'exclam',       'quotedbl',       'numbersign',         // 20 to 23
+     'dollar',        'percent',      'ampersand',      'quotesingle',        // 24 to 27
+     'parenleft',     'parenright',   'asterisk',       'plus',               // 28 to 2B
+     'comma',         'hyphen',       'period',         'slash',              // 2C to 2F
+     'zero',          'one',          'two',            'three',              // 30 to 33
+     'four',          'five',         'six',            'seven',              // 34 to 37
+     'eight',         'nine',         'colon',          'semicolon',          // 38 to 3B
+     'less',          'equal',        'greater',        'question',           // 3C to 3F
+     'at',            'A',            'B',              'C',                  // 40 to 43
+     'D',             'E',            'F',              'G',                  // 44 to 47
+     'H',             'I',            'J',              'K',                  // 48 to 4B
+     'L',             'M',            'N',              'O',                  // 4C to 4F
+     'P',             'Q',            'R',              'S',                  // 50 to 53
+     'T',             'U',            'V',              'W',                  // 54 to 57
+     'X',             'Y',            'Z',              'bracketleft',        // 58 to 5B
+     'backslash',     'bracketright', 'asciicircum',    'underscore',         // 5C to 5F
+     'grave',         'a',            'b',              'c',                  // 60 to 63
+     'd',             'e',            'f',              'g',                  // 64 to 67
+     'h',             'i',            'j',              'k',                  // 68 to 6B
+     'l',             'm',            'n',              'o',                  // 6C to 6F
+     'p',             'q',            'r',              's',                  // 70 to 73
+     't',             'u',            'v',              'w',                  // 74 to 77
+     'x',             'y',            'z',              'braceleft',          // 78 to 7B
+     'bar',           'braceright',   'asciitilde',     '.notdef',            // 7C to 7F
+     'Euro',          '.notdef',      'quotesinglbase', '.notdef',            // 80 to 83
+     'quotedblbase',  'ellipsis',     'dagger',         'daggerdbl',          // 84 to 87
+     '.notdef',       'perthousand',  'Scaron',         'guilsinglleft',      // 88 to 8B
+     'Sacute',        'Tcaron',       'Zcaron',         'Zacute',             // 8C to 8F
+     '.notdef',       'quoteleft',    'quoteright',     'quotedblleft',       // 90 to 93
+     'quotedblright', 'bullet',       'endash',         'emdash',             // 94 to 97
+     '.notdef',       'trademark',    'scaron',         'guilsinglright',     // 98 to 9B
+     'sacute',        'tcaron',       'zcaron',         'zacute',             // 9C to 9F
+     'space',         'caron',        'breve',          'Lslash',             // A0 to A3
+     'currency',      'Aogonek',      'brokenbar',      'section',            // A4 to A7
+     'dieresis',      'copyright',    'Scedilla',       'guillemotleft',      // A8 to AB
+     'logicalnot',    'hyphen',       'registered',     'Zdotaccent',         // AC to AF
+     'degree',        'plusminus',    'ogonek',         'lslash',             // B0 to B3
+     'acute',         'mu',           'paragraph',      'periodcentered',     // B4 to B7
+     'cedilla',       'aogonek',      'scedilla',       'guillemotright',     // B8 to BB
+     'Lcaron',        'hungarumlaut', 'lcaron',         'zdotaccent',         // BC to BF
+     'Racute',        'Aacute',       'Acircumflex',    'Abreve',             // C0 to C3
+     'Adieresis',     'Lacute',       'Cacute',         'Ccedilla',           // C4 to C7
+     'Ccaron',        'Eacute',       'Eogonek',        'Edieresis',          // C8 to CB
+     'Ecaron',        'Iacute',       'Icircumflex',    'Dcaron',             // CC to CF
+     'Dcroat',        'Nacute',       'Ncaron',         'Oacute',             // D0 to D3
+     'Ocircumflex',   'Ohungarumlaut','Odieresis',      'multiply',           // D4 to D7
+     'Rcaron',        'Uring',        'Uacute',         'Uhungarumlaut',      // D8 to DB
+     'Udieresis',     'Yacute',       'Tcommaaccent',   'germandbls',         // DC to DF
+     'racute',        'aacute',       'acircumflex',    'abreve',             // E0 to E3
+     'adieresis',     'lacute',       'cacute',         'ccedilla',           // E4 to E7
+     'ccaron',        'eacute',       'eogonek',        'edieresis',          // E8 to EB
+     'ecaron',        'iacute',       'icircumflex',    'dcaron',             // EC to EF
+     'dcroat',        'nacute',       'ncaron',         'oacute',             // F0 to F3
+     'ocircumflex',   'ohungarumlaut','odieresis',      'divide',             // F4 to F7
+     'rcaron',        'uring',        'uacute',         'uhungarumlaut',      // F8 to FB
+     'udieresis',     'yacute',       'tcommaaccent',   'dotaccent');         // FC to FF
+
+const
+  cp1250_v: TTTFEncodingValues =
+    (0,       1,       2,       3,       4,        5,       6,       7,         // 00 to 07
+     8,       9,       10,      11,      12,       13,      14,      15,        // 08 to 0F
+     16,      17,      18,      19,      20,       21,      22,      23,        // 10 to 17
+     24,      25,      26,      27,      28,       29,      30,      31,        // 18 to 1F
+     32,      33,      34,      35,      36,       37,      38,      39,        // 20 to 27
+     40,      41,      42,      43,      44,       45,      46,      47,        // 28 to 2F
+     48,      49,      50,      51,      52,       53,      54,      55,        // 30 to 37
+     56,      57,      58,      59,      60,       61,      62,      63,        // 38 to 3F
+     64,      65,      66,      67,      68,       69,      70,      71,        // 40 to 47
+     72,      73,      74,      75,      76,       77,      78,      79,        // 48 to 4F
+     80,      81,      82,      83,      84,       85,      86,      87,        // 50 to 57
+     88,      89,      90,      91,      92,       93,      94,      95,        // 58 to 5F
+     96,      97,      98,      99,      100,      101,     102,     103,       // 60 to 67
+     104,     105,     106,     107,     108,      109,     110,     111,       // 68 to 6F
+     112,     113,     114,     115,     116,      117,     118,     119,       // 70 to 77
+     120,     121,     122,     123,     124,      125,     126,     127,       // 78 to 7F
+     8364,    -1,      8218,    -1,      8222,     8230,    8224,    8225,      // 80 to 87
+     -1,      8240,    352,     8249,    346,      356,     381,     377,       // 88 to 8F
+     -1,      8216,    8217,    8220,    8221,     8226,    8211,    8212,      // 90 to 97
+     -1,      8482,    353,     8250,    347,      357,     382,     378,       // 98 to 9F
+     160,     711,     728,     321,     164,      260,     166,     167,       // A0 to A7
+     168,     169,     350,     171,     172,      173,     174,     379,       // A8 to AF
+     176,     177,     731,     322,     180,      181,     182,     183,       // B0 to B7
+     184,     261,     351,     187,     317,      733,     318,     380,       // B8 to BF
+     340,     193,     194,     258,     196,      313,     262,     199,       // C0 to C7
+     268,     201,     280,     203,     282,      205,     206,     270,       // C8 to CF
+     272,     323,     327,     211,     212,      336,     214,     215,       // D0 to D7
+     344,     366,     218,     368,     220,      221,     354,     354,       // D8 to DF
+     341,     225,     226,     259,     228,      314,     263,     231,       // E0 to E7
+     269,     233,     281,     235,     283,      237,     238,     271,       // E8 to EF
+     273,     324,     328,     243,     244,      337,     246,     247,       // F0 to F7
+     345,     367,     250,     369,     252,      253,     355,     729);      // F8 to FF
+
+const
+  cp1251_n: TTTFEncodingNames =
+    ('.notdef',       '.notdef',      '.notdef',        '.notdef',            // 00 to 03
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 04 to 07
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 08 to 0B
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 0C to 0F
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 10 to 13
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 14 to 17
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 18 to 1B
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 1C to 1F
+     'space',         'exclam',       'quotedbl',       'numbersign',         // 20 to 23
+     'dollar',        'percent',      'ampersand',      'quotesingle',        // 24 to 27
+     'parenleft',     'parenright',   'asterisk',       'plus',               // 28 to 2B
+     'comma',         'hyphen',       'period',         'slash',              // 2C to 2F
+     'zero',          'one',          'two',            'three',              // 30 to 33
+     'four',          'five',         'six',            'seven',              // 34 to 37
+     'eight',         'nine',         'colon',          'semicolon',          // 38 to 3B
+     'less',          'equal',        'greater',        'question',           // 3C to 3F
+     'at',            'A',            'B',              'C',                  // 40 to 43
+     'D',             'E',            'F',              'G',                  // 44 to 47
+     'H',             'I',            'J',              'K',                  // 48 to 4B
+     'L',             'M',            'N',              'O',                  // 4C to 4F
+     'P',             'Q',            'R',              'S',                  // 50 to 53
+     'T',             'U',            'V',              'W',                  // 54 to 57
+     'X',             'Y',            'Z',              'bracketleft',        // 58 to 5B
+     'backslash',     'bracketright', 'asciicircum',    'underscore',         // 5C to 5F
+     'grave',         'a',            'b',              'c',                  // 60 to 63
+     'd',             'e',            'f',              'g',                  // 64 to 67
+     'h',             'i',            'j',              'k',                  // 68 to 6B
+     'l',             'm',            'n',              'o',                  // 6C to 6F
+     'p',             'q',            'r',              's',                  // 70 to 73
+     't',             'u',            'v',              'w',                  // 74 to 77
+     'x',             'y',            'z',              'braceleft',          // 78 to 7B
+     'bar',           'braceright',   'asciitilde',     '.notdef',            // 7C to 7F
+     'afii10051',     'afii10052',    'quotesinglbase', 'afii10100',          // 80 to 83
+     'quotedblbase',  'ellipsis',     'dagger',         'daggerdbl',          // 84 to 87
+     'Euro',          'perthousand',  'afii10058',      'guilsinglleft',      // 88 to 8B
+     'afii10059',     'afii10061',    'afii10060',      'afii10145',          // 8C to 8F
+     'afii10099',     'quoteleft',    'quoteright',     'quotedblleft',       // 90 to 93
+     'quotedblright', 'bullet',       'endash',         'emdash',             // 94 to 97
+     '.notdef',       'trademark',    'afii10106',      'guilsinglright',     // 98 to 9B
+     'afii10107',     'afii10109',    'afii10108',      'afii10193',          // 9C to 9F
+     'space',         'afii10062',    'afii10110',      'afii10057',          // A0 to A3
+     'currency',      'afii10050',    'brokenbar',      'section',            // A4 to A7
+     'afii10023',     'copyright',    'afii10053',      'guillemotleft',      // A8 to AB
+     'logicalnot',    'hyphen',       'registered',     'afii10056',          // AC to AF
+     'degree',        'plusminus',    'afii10055',      'afii10103',          // B0 to B3
+     'afii10098',     'mu',           'paragraph',      'periodcentered',     // B4 to B7
+     'afii10071',     'afii61352',    'afii10101',      'guillemotright',     // B8 to BB
+     'afii10105',     'afii10054',    'afii10102',      'afii10104',          // BC to BF
+     'afii10017',     'afii10018',    'afii10019',      'afii10020',          // C0 to C3
+     'afii10021',     'afii10022',    'afii10024',      'afii10025',          // C4 to C7
+     'afii10026',     'afii10027',    'afii10028',      'afii10029',          // C8 to CB
+     'afii10030',     'afii10031',    'afii10032',      'afii10033',          // CC to CF
+     'afii10034',     'afii10035',    'afii10036',      'afii10037',          // D0 to D3
+     'afii10038',     'afii10039',    'afii10040',      'afii10041',          // D4 to D7
+     'afii10042',     'afii10043',    'afii10044',      'afii10045',          // D8 to DB
+     'afii10046',     'afii10047',    'afii10048',      'afii10049',          // DC to DF
+     'afii10065',     'afii10066',    'afii10067',      'afii10068',          // E0 to E3
+     'afii10069',     'afii10070',    'afii10072',      'afii10073',          // E4 to E7
+     'afii10074',     'afii10075',    'afii10076',      'afii10077',          // E8 to EB
+     'afii10078',     'afii10079',    'afii10080',      'afii10081',          // EC to EF
+     'afii10082',     'afii10083',    'afii10084',      'afii10085',          // F0 to F3
+     'afii10086',     'afii10087',    'afii10088',      'afii10089',          // F4 to F7
+     'afii10090',     'afii10091',    'afii10092',      'afii10093',          // F8 to FB
+     'afii10094',     'afii10095',    'afii10095',      'afii10097');         // FC to FF
+
+const
+  cp1251_v: TTTFEncodingValues =
+    (0,       1,       2,       3,       4,        5,       6,       7,         // 00 to 07
+     8,       9,       10,      11,      12,       13,      14,      15,        // 08 to 0F
+     16,      17,      18,      19,      20,       21,      22,      23,        // 10 to 17
+     24,      25,      26,      27,      28,       29,      30,      31,        // 18 to 1F
+     32,      33,      34,      35,      36,       37,      38,      39,        // 20 to 27
+     40,      41,      42,      43,      44,       45,      46,      47,        // 28 to 2F
+     48,      49,      50,      51,      52,       53,      54,      55,        // 30 to 37
+     56,      57,      58,      59,      60,       61,      62,      63,        // 38 to 3F
+     64,      65,      66,      67,      68,       69,      70,      71,        // 40 to 47
+     72,      73,      74,      75,      76,       77,      78,      79,        // 48 to 4F
+     80,      81,      82,      83,      84,       85,      86,      87,        // 50 to 57
+     88,      89,      90,      91,      92,       93,      94,      95,        // 58 to 5F
+     96,      97,      98,      99,      100,      101,     102,     103,       // 60 to 67
+     104,     105,     106,     107,     108,      109,     110,     111,       // 68 to 6F
+     112,     113,     114,     115,     116,      117,     118,     119,       // 70 to 77
+     120,     121,     122,     123,     124,      125,     126,     127,       // 78 to 7F
+     1026,    1027,    8218,    1107,    8222,     8230,    8224,    8225,      // 80 to 87
+     8364,    8240,    1033,    8249,    1034,     1036,    1035,    1039,      // 88 to 8F
+     1106,    8216,    8217,    8220,    8221,     8226,    8211,    8212,      // 90 to 97
+     -1,      8482,    1113,    8250,    1114,     1116,    1115,    1119,      // 98 to 9F
+     160,     1038,    1118,    1032,    164,      1168,    166,     167,       // A0 to A7
+     1025,    169,     1028,    171,     172,      173,     174,     1031,      // A8 to AF
+     176,     177,     1030,    1110,    1169,     181,     182,     183,       // B0 to B7
+     1105,    8470,    1108,    187,     1112,     1029,    1109,    1111,      // B8 to BF
+     1040,    1041,    1042,    1043,    1044,     1045,    1046,    1047,      // C0 to C7
+     1048,    1049,    1050,    1051,    1052,     1053,    1054,    1055,      // C8 to CF
+     1056,    1057,    1058,    1059,    1060,     1061,    1062,    1063,      // D8 to D7
+     1064,    1065,    1066,    1067,    1068,     1069,    1070,    1071,      // D8 to DF
+     1072,    1073,    1074,    1075,    1076,     1077,    1078,    1079,      // E0 to E7
+     1080,    1081,    1082,    1083,    1084,     1085,    1086,    1087,      // E8 to EF
+     1088,    1089,    1090,    1091,    1092,     1093,    1094,    1095,      // F0 to F7
+     1096,    1097,    1098,    1099,    1100,     1101,    1102,    1103);     // F8 to FF
+
+const
+  cp1252_n: TTTFEncodingNames =
+    ('.notdef',       '.notdef',      '.notdef',        '.notdef',            // 00 to 03
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 04 to 07
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 08 to 0B
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 0C to 0F
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 10 to 13
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 14 to 17
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 18 to 1B
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 1C to 1F
+     'space',         'exclam',       'quotedbl',       'numbersign',         // 20 to 23
+     'dollar',        'percent',      'ampersand',      'quotesingle',        // 24 to 27
+     'parenleft',     'parenright',   'asterisk',       'plus',               // 28 to 2B
+     'comma',         'hyphen',       'period',         'slash',              // 2C to 2F
+     'zero',          'one',          'two',            'three',              // 30 to 33
+     'four',          'five',         'six',            'seven',              // 34 to 37
+     'eight',         'nine',         'colon',          'semicolon',          // 38 to 3B
+     'less',          'equal',        'greater',        'question',           // 3C to 3F
+     'at',            'A',            'B',              'C',                  // 40 to 43
+     'D',             'E',            'F',              'G',                  // 44 to 47
+     'H',             'I',            'J',              'K',                  // 48 to 4B
+     'L',             'M',            'N',              'O',                  // 4C to 4F
+     'P',             'Q',            'R',              'S',                  // 50 to 53
+     'T',             'U',            'V',              'W',                  // 54 to 57
+     'X',             'Y',            'Z',              'bracketleft',        // 58 to 5B
+     'backslash',     'bracketright', 'asciicircum',    'underscore',         // 5C to 5F
+     'grave',         'a',            'b',              'c',                  // 60 to 63
+     'd',             'e',            'f',              'g',                  // 64 to 67
+     'h',             'i',            'j',              'k',                  // 68 to 6B
+     'l',             'm',            'n',              'o',                  // 6C to 6F
+     'p',             'q',            'r',              's',                  // 70 to 73
+     't',             'u',            'v',              'w',                  // 74 to 77
+     'x',             'y',            'z',              'braceleft',          // 78 to 7B
+     'bar',           'braceright',   'asciitilde',     '.notdef',            // 7C to 7F
+     'Euro',          '.notdef',      'quotesinglbase', 'florin',             // 80 to 83
+     'quotedblbase',  'ellipsis',     'dagger',         'daggerdbl',          // 84 to 87
+     'circumflex',    'perthousand',  'Scaron',         'guilsinglleft',      // 88 to 8B
+     'OE',            '.notdef',      'Zcaron',         '.notdef',            // 8C to 8F
+     '.notdef',       'quoteleft',    'quoteright',     'quotedblleft',       // 90 to 93
+     'quotedblright', 'bullet',       'endash',         'emdash',             // 94 to 97
+     'tilde',         'trademark',    'scaron',         'guilsinglright',     // 98 to 9B
+     'oe',            '.notdef',      'zcaron',         'Ydieresis',          // 9C to 9F
+     'space',         'exclamdown',   'cent',           'sterling',           // A0 to A3
+     'currency',      'yen',          'brokenbar',      'section',            // A4 to A7
+     'dieresis',      'copyright',    'ordfeminine',    'guillemotleft',      // A8 to AB
+     'logicalnot',    'hyphen',       'registered',     'macron',             // AC to AF
+     'degree',        'plusminus',    'twosuperior',    'threesuperior',      // B0 to B3
+     'acute',         'mu',           'paragraph',      'periodcentered',     // B4 to B7
+     'cedilla',       'onesuperior',  'ordmasculine',   'guillemotright',     // B8 to BB
+     'onequarter',    'onehalf',      'threequarters',  'questiondown',       // BC to BF
+     'Agrave',        'Aacute',       'Acircumflex',    'Atilde',             // C0 to C3
+     'Adieresis',     'Aring',        'AE',             'Ccedilla',           // C4 to C7
+     'Egrave',        'Eacute',       'Ecircumflex',    'Edieresis',          // C8 to CB
+     'Igrave',        'Iacute',       'Icircumflex',    'Idieresis',          // CC to CF
+     'Eth',           'Ntilde',       'Ograve',         'Oacute',             // D0 to D3
+     'Ocircumflex',   'Otilde',       'Odieresis',      'multiply',           // D4 to D7
+     'Oslash',        'Ugrave',       'Uacute',         'Ucircumflex',        // D8 to DB
+     'Udieresis',     'Yacute',       'Thorn',          'germandbls',         // DC to DF
+     'agrave',        'aacute',       'acircumflex',    'atilde',             // E0 to E3
+     'adieresis',     'aring',        'ae',             'ccedilla',           // E4 to E7
+     'egrave',        'eacute',       'ecircumflex',    'edieresis',          // E8 to EB
+     'igrave',        'iacute',       'icircumflex',    'idieresis',          // EC to EF
+     'eth',           'ntilde',       'ograve',         'oacute',             // F0 to F3
+     'ocircumflex',   'otilde',       'odieresis',      'divide',             // F4 to F7
+     'oslash',        'ugrave',       'uacute',         'ucircumflex',        // F8 to FB
+     'udieresis',     'yacute',       'thorn',          'ydieresis');         // FC to FF
+
+const
+  cp1252_v: TTTFEncodingValues =
+    (0,       1,       2,       3,       4,        5,       6,       7,         // 00 to 07
+     8,       9,       10,      11,      12,       13,      14,      15,        // 08 to 0F
+     16,      17,      18,      19,      20,       21,      22,      23,        // 10 to 17
+     24,      25,      26,      27,      28,       29,      30,      31,        // 18 to 1F
+     32,      33,      34,      35,      36,       37,      38,      39,        // 20 to 27
+     40,      41,      42,      43,      44,       45,      46,      47,        // 28 to 2F
+     48,      49,      50,      51,      52,       53,      54,      55,        // 30 to 37
+     56,      57,      58,      59,      60,       61,      62,      63,        // 38 to 3F
+     64,      65,      66,      67,      68,       69,      70,      71,        // 40 to 47
+     72,      73,      74,      75,      76,       77,      78,      79,        // 48 to 4F
+     80,      81,      82,      83,      84,       85,      86,      87,        // 50 to 57
+     88,      89,      90,      91,      92,       93,      94,      95,        // 58 to 5F
+     96,      97,      98,      99,      100,      101,     102,     103,       // 60 to 67
+     104,     105,     106,     107,     108,      109,     110,     111,       // 68 to 6F
+     112,     113,     114,     115,     116,      117,     118,     119,       // 70 to 77
+     120,     121,     122,     123,     124,      125,     126,     127,       // 78 to 7F
+     8364,    -1,     8218,    402,     8222,     8230,    8224,    8225,      // 80 to 87
+     710,     8240,    352,     8249,    338,      -1,      381,     -1,        // 88 to 8F
+     -1,      8216,    8217,    8220,    8221,     8226,    8211,    8212,      // 90 to 97
+     732,     8482,    353,     8250,    339,      -1,      382,     376,       // 98 to 9F
+     160,     161,     162,     163,     164,      165,     166,     167,       // A0 to A7
+     168,     169,     170,     171,     172,      173,     174,     175,       // A8 to AF
+     176,     177,     178,     179,     180,      181,     182,     183,       // B0 to B7
+     184,     185,     186,     187,     188,      189,     190,     191,       // B8 to BF
+     192,     193,     194,     195,     196,      197,     198,     199,       // C0 to C7
+     200,     201,     202,     203,     204,      205,     206,     207,       // C8 to CF
+     208,     209,     210,     211,     212,      213,     214,     215,       // D0 to D7
+     216,     217,     218,     219,     220,      221,     222,     223,       // D8 to DF
+     224,     225,     226,     227,     228,      229,     230,     231,       // E0 to E7
+     232,     233,     234,     235,     236,      237,     238,     239,       // E8 to EF
+     240,     241,     242,     243,     244,      245,     246,     247,       // F0 to F7
+     248,     249,     250,     251,     252,      253,     254,     255);      // F8 to FF
+
+const
+  cp1253_n: TTTFEncodingNames =
+    ('.notdef',             '.notdef',      '.notdef',        '.notdef',            // 00 to 03
+     '.notdef',             '.notdef',      '.notdef',        '.notdef',            // 04 to 07
+     '.notdef',             '.notdef',      '.notdef',        '.notdef',            // 08 to 0B
+     '.notdef',             '.notdef',      '.notdef',        '.notdef',            // 0C to 0F
+     '.notdef',             '.notdef',      '.notdef',        '.notdef',            // 10 to 13
+     '.notdef',             '.notdef',      '.notdef',        '.notdef',            // 14 to 17
+     '.notdef',             '.notdef',      '.notdef',        '.notdef',            // 18 to 1B
+     '.notdef',             '.notdef',      '.notdef',        '.notdef',            // 1C to 1F
+     'space',               'exclam',       'quotedbl',       'numbersign',         // 20 to 23
+     'dollar',              'percent',      'ampersand',      'quotesingle',        // 24 to 27
+     'parenleft',           'parenright',   'asterisk',       'plus',               // 28 to 2B
+     'comma',               'hyphen',       'period',         'slash',              // 2C to 2F
+     'zero',                'one',          'two',            'three',              // 30 to 33
+     'four',                'five',         'six',            'seven',              // 34 to 37
+     'eight',               'nine',         'colon',          'semicolon',          // 38 to 3B
+     'less',                'equal',        'greater',        'question',           // 3C to 3F
+     'at',                  'A',            'B',              'C',                  // 40 to 43
+     'D',                   'E',            'F',              'G',                  // 44 to 47
+     'H',                   'I',            'J',              'K',                  // 48 to 4B
+     'L',                   'M',            'N',              'O',                  // 4C to 4F
+     'P',                   'Q',            'R',              'S',                  // 50 to 53
+     'T',                   'U',            'V',              'W',                  // 54 to 57
+     'X',                   'Y',            'Z',              'bracketleft',        // 58 to 5B
+     'backslash',           'bracketright', 'asciicircum',    'underscore',         // 5C to 5F
+     'grave',               'a',            'b',              'c',                  // 60 to 63
+     'd',                   'e',            'f',              'g',                  // 64 to 67
+     'h',                   'i',            'j',              'k',                  // 68 to 6B
+     'l',                   'm',            'n',              'o',                  // 6C to 6F
+     'p',                   'q',            'r',              's',                  // 70 to 73
+     't',                   'u',            'v',              'w',                  // 74 to 77
+     'x',                   'y',            'z',              'braceleft',          // 78 to 7B
+     'bar',                 'braceright',   'asciitilde',     '.notdef',            // 7C to 7F
+     'Euro',                '.notdef',      'quotesinglbase', 'florin',             // 80 to 83
+     'quotedblbase',        'ellipsis',     'dagger',         'daggerdbl',          // 84 to 87
+     '.notdef',             'perthousand',  '.notdef',        'guilsinglleft',      // 88 to 8B
+     '.notdef',             '.notdef',      '.notdef',        '.notdef',            // 8C to 8F
+     '.notdef',             'quoteleft',    'quoteright',     'quotedblleft',       // 90 to 93
+     'quotedblright',       'bullet',       'endash',         'emdash',             // 94 to 97
+     '.notdef',             'trademark',    '.notdef',        'guilsinglright',     // 98 to 9B
+     '.notdef',             '.notdef',      '.notdef',        '.notdef',            // 9C to 9F
+     'space',               'dieresistonos','Alphatonos',     'sterling',           // A0 to A3
+     'currency',            'yen',          'brokenbar',      'section',            // A4 to A7
+     'dieresis',            'copyright',    '.notdef',        'guillemotleft',      // A8 to AB
+     'logicalnot',          'hyphen',       'registered',     'afii00208',          // AC to AF
+     'degree',              'plusminus',    'twosuperior',    'threesuperior',      // B0 to B3
+     'tonos',               'mu',           'paragraph',      'periodcentered',     // B4 to B7
+     'Epsilontonos',        'Etatonos',     'Iotatonos',      'guillemotright',     // B8 to BB
+     'Omicrontonos',        'onehalf',      'Upsilontonos',   'Omegatonos',         // BC to BF
+     'iotadieresistonos',   'Alpha',        'Beta',           'Gamma',              // C0 to C3
+     'Delta',               'Epsilon',      'Zeta',           'Eta',                // C4 to C7
+     'Theta',               'Iota',         'Kappa',          'Lambda',             // C8 to CB
+     'Mu',                  'Nu',           'Xi',             'Omicron',            // CC to CF
+     'Pi',                  'Rho',          '.notdef',        'Sigma',              // D0 to D3
+     'Tau',                 'Upsilon',      'Phi',            'Chi',                // D4 to D7
+     'Psi',                 'Omega',        'Iotadieresis',   'Upsilondieresis',    // D8 to DB
+     'alphatonos',          'epsilontonos', 'etatonos',       'iotatonos',          // DC to DF
+     'upsilondieresistonos','alpha',        'beta',           'gamma',              // E0 to E3
+     'delta',               'epsilon',      'zeta',           'eta',                // E4 to E7
+     'theta',               'iota',         'kappa',          'lambda',             // E8 to EB
+     'mu',                  'nu',           'xi',             'omicron',            // EC to EF
+     'pi',                  'rho',          'sigma1',         'sigma',              // F0 to F3
+     'tau',                 'upsilon',      'phi',            'chi',                // F4 to F7
+     'psi',                 'omega',        'iotadieresis',   'upsilondieresis',    // F8 to FB
+     'omicrontonos',        'upsilontonos', 'omegatonos',     '.notdef');           // FC to FF
+
+const
+  cp1253_v: TTTFEncodingValues =
+    (0,       1,       2,       3,       4,        5,       6,       7,         // 00 to 07
+     8,       9,       10,      11,      12,       13,      14,      15,        // 08 to 0F
+     16,      17,      18,      19,      20,       21,      22,      23,        // 10 to 17
+     24,      25,      26,      27,      28,       29,      30,      31,        // 18 to 1F
+     32,      33,      34,      35,      36,       37,      38,      39,        // 20 to 27
+     40,      41,      42,      43,      44,       45,      46,      47,        // 28 to 2F
+     48,      49,      50,      51,      52,       53,      54,      55,        // 30 to 37
+     56,      57,      58,      59,      60,       61,      62,      63,        // 38 to 3F
+     64,      65,      66,      67,      68,       69,      70,      71,        // 40 to 47
+     72,      73,      74,      75,      76,       77,      78,      79,        // 48 to 4F
+     80,      81,      82,      83,      84,       85,      86,      87,        // 50 to 57
+     88,      89,      90,      91,      92,       93,      94,      95,        // 58 to 5F
+     96,      97,      98,      99,      100,      101,     102,     103,       // 60 to 67
+     104,     105,     106,     107,     108,      109,     110,     111,       // 68 to 6F
+     112,     113,     114,     115,     116,      117,     118,     119,       // 70 to 77
+     120,     121,     122,     123,     124,      125,     126,     127,       // 78 to 7F
+     8364,    -1,      8218,    402,     8222,     8230,    8224,    8225,      // 80 to 87
+     -1,      8240,    -1,      8249,    -1,       -1,      -1,      -1,        // 88 to 8F
+     -1,      8216,    8217,    8220,    8221,     8226,    8211,    8212,      // 90 to 97
+     -1,      8482,    -1,      8250,    -1,       -1,      -1,      -1,        // 98 to 9F
+     160,     901,     902,     163,     164,      165,     166,     167,       // A0 to A7
+     168,     169,     -1,      171,     172,      173,     174,     8213,      // A8 to AF
+     176,     177,     178,     179,     900,      181,     182,     183,       // B0 to B7
+     904,     905,     906,     187,     908,      189,     910,     911,       // B8 to BF
+     912,     913,     914,     915,     916,      917,     918,     919,       // C0 to C7
+     920,     921,     922,     923,     924,      925,     926,     927,       // C8 to CF
+     928,     929,     -1,      931,     932,      933,     934,     935,       // D0 to D7
+     936,     937,     938,     939,     940,      941,     942,     943,       // D8 to DF
+     944,     945,     946,     947,     948,      949,     950,     951,       // E0 to E7
+     952,     953,     954,     955,     956,      957,     958,     959,       // E8 to EF
+     960,     961,     962,     963,     964,      965,     966,     967,       // F0 to F7
+     968,     969,     970,     971,     972,      973,     974,     -1);           // F8 to FF
+
+const
+  cp1254_n: TTTFEncodingNames =
+    ('.notdef',       '.notdef',      '.notdef',        '.notdef',            // 00 to 03
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 04 to 07
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 08 to 0B
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 0C to 0F
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 10 to 13
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 14 to 17
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 18 to 1B
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 1C to 1F
+     'space',         'exclam',       'quotedbl',       'numbersign',         // 20 to 23
+     'dollar',        'percent',      'ampersand',      'quotesingle',        // 24 to 27
+     'parenleft',     'parenright',   'asterisk',       'plus',               // 28 to 2B
+     'comma',         'hyphen',       'period',         'slash',              // 2C to 2F
+     'zero',          'one',          'two',            'three',              // 30 to 33
+     'four',          'five',         'six',            'seven',              // 34 to 37
+     'eight',         'nine',         'colon',          'semicolon',          // 38 to 3B
+     'less',          'equal',        'greater',        'question',           // 3C to 3F
+     'at',            'A',            'B',              'C',                  // 40 to 43
+     'D',             'E',            'F',              'G',                  // 44 to 47
+     'H',             'I',            'J',              'K',                  // 48 to 4B
+     'L',             'M',            'N',              'O',                  // 4C to 4F
+     'P',             'Q',            'R',              'S',                  // 50 to 53
+     'T',             'U',            'V',              'W',                  // 54 to 57
+     'X',             'Y',            'Z',              'bracketleft',        // 58 to 5B
+     'backslash',     'bracketright', 'asciicircum',    'underscore',         // 5C to 5F
+     'grave',         'a',            'b',              'c',                  // 60 to 63
+     'd',             'e',            'f',              'g',                  // 64 to 67
+     'h',             'i',            'j',              'k',                  // 68 to 6B
+     'l',             'm',            'n',              'o',                  // 6C to 6F
+     'p',             'q',            'r',              's',                  // 70 to 73
+     't',             'u',            'v',              'w',                  // 74 to 77
+     'x',             'y',            'z',              'braceleft',          // 78 to 7B
+     'bar',           'braceright',   'asciitilde',     '.notdef',            // 7C to 7F
+     'Euro',          '.notdef',      'quotesinglbase', 'florin',             // 80 to 83
+     'quotedblbase',  'ellipsis',     'dagger',         'daggerdbl',          // 84 to 87
+     'circumflex',    'perthousand',  'Scaron',         'guilsinglleft',      // 88 to 8B
+     'OE',            '.notdef',      '.notdef',        '.notdef',            // 8C to 8F
+     '.notdef',       'quoteleft',    'quoteright',     'quotedblleft',       // 90 to 93
+     'quotedblright', 'bullet',       'endash',         'emdash',             // 94 to 97
+     'tilde',         'trademark',    'scaron',         'guilsinglright',     // 98 to 9B
+     'oe',            '.notdef',      '.notdef',        'Ydieresis',          // 9C to 9F
+     'space',         'exclamdown',   'cent',           'sterling',           // A0 to A3
+     'currency',      'yen',          'brokenbar',      'section',            // A4 to A7
+     'dieresis',      'copyright',    'ordfeminine',    'guillemotleft',      // A8 to AB
+     'logicalnot',    'hyphen',       'registered',     'macron',             // AC to AF
+     'degree',        'plusminus',    'twosuperior',    'threesuperior',      // B0 to B3
+     'acute',         'mu',           'paragraph',      'periodcentered',     // B4 to B7
+       'cedilla',       'onesuperior','ordmasculine',   'guillemotright',     // B8 to BB
+     'onequarter',    'onehalf',      'threequarters',  'questiondown',       // BC to BF
+     'Agrave',        'Aacute',       'Acircumflex',    'Atilde',             // C0 to C3
+     'Adieresis',     'Aring',        'AE',             'Ccedilla',           // C4 to C7
+     'Egrave',        'Eacute',       'Ecircumflex',    'Edieresis',          // C8 to CB
+     'Igrave',        'Iacute',       'Icircumflex',    'Idieresis',          // CC to CF
+     'Gbreve',        'Ntilde',       'Ograve',         'Oacute',             // D0 to D3
+     'Ocircumflex',   'Otilde',       'Odieresis',      'multiply',           // D4 to D7
+     'Oslash',        'Ugrave',       'Uacute',         'Ucircumflex',        // D8 to DB
+     'Udieresis',     'Idotaccent',   'Scedilla',       'germandbls',         // DC to DF
+     'agrave',        'aacute',       'acircumflex',    'atilde',             // E0 to E3
+     'adieresis',     'aring',        'ae',             'ccedilla',           // E4 to E7
+     'egrave',        'eacute',       'ecircumflex',    'edieresis',          // E8 to EB
+     'igrave',        'iacute',       'icircumflex',    'idieresis',          // EC to EF
+     'gbreve',        'ntilde',       'ograve',         'oacute',             // F0 to F3
+     'ocircumflex',   'otilde',       'odieresis',      'divide',             // F4 to F7
+     'oslash',        'ugrave',       'uacute',         'ucircumflex',        // F8 to FB
+     'udieresis',     'dotlessi',     'scedilla',       'ydieresis');         // FC to FF
+
+const
+  cp1254_v: TTTFEncodingValues =
+    (0,       1,       2,       3,       4,        5,       6,       7,         // 00 to 07
+     8,       9,       10,      11,      12,       13,      14,      15,        // 08 to 0F
+     16,      17,      18,      19,      20,       21,      22,      23,        // 10 to 17
+     24,      25,      26,      27,      28,       29,      30,      31,        // 18 to 1F
+     32,      33,      34,      35,      36,       37,      38,      39,        // 20 to 27
+     40,      41,      42,      43,      44,       45,      46,      47,        // 28 to 2F
+     48,      49,      50,      51,      52,       53,      54,      55,        // 30 to 37
+     56,      57,      58,      59,      60,       61,      62,      63,        // 38 to 3F
+     64,      65,      66,      67,      68,       69,      70,      71,        // 40 to 47
+     72,      73,      74,      75,      76,       77,      78,      79,        // 48 to 4F
+     80,      81,      82,      83,      84,       85,      86,      87,        // 50 to 57
+     88,      89,      90,      91,      92,       93,      94,      95,        // 58 to 5F
+     96,      97,      98,      99,      100,      101,     102,     103,       // 60 to 67
+     104,     105,     106,     107,     108,      109,     110,     111,       // 68 to 6F
+     112,     113,     114,     115,     116,      117,     118,     119,       // 70 to 77
+     120,     121,     122,     123,     124,      125,     126,     127,       // 78 to 7F
+     8364,    -1,      8218,    402,     8222,     8230,    8224,    8225,      // 80 to 87
+     710,     8240,    352,     8249,    338,      -1,      -1,      -1,        // 88 to 8F
+     -1,      8216,    8217,    8220,    8221,     8226,    8211,    8212,      // 90 to 97
+     732,     8482,    353,     8250,    339,      -1,      -1,      376,       // 98 to 9F
+     160,     161,     162,     163,     164,      165,     166,     167,       // A0 to A7
+     168,     169,     170,     171,     172,      173,     174,     175,       // A8 to AF
+     176,     177,     178,     179,     180,      181,     182,     183,       // B0 to B7
+     184,     185,     186,     187,     188,      189,     190,     191,       // B8 to BF
+     192,     193,     194,     195,     196,      197,     198,     199,       // C0 to C7
+     200,     201,     202,     203,     204,      205,     206,     207,       // C8 to CF
+     286,     209,     210,     211,     212,      213,     214,     215,       // D0 to D7
+     216,     217,     218,     219,     220,      304,     350,     223,       // D8 to DF
+     224,     225,     226,     227,     228,      229,     230,     231,       // E0 to E7
+     232,     233,     234,     235,     236,      237,     238,     239,       // E8 to EF
+     287,     241,     242,     243,     244,      245,     246,     247,       // F0 to F7
+     248,     249,     250,     251,     252,      305,     351,     255);      // F8 to FF
+
+const
+  cp1255_n: TTTFEncodingNames =
+    ('.notdef',         '.notdef',      '.notdef',        '.notdef',            // 00 to 03
+     '.notdef',         '.notdef',      '.notdef',        '.notdef',            // 04 to 07
+     '.notdef',         '.notdef',      '.notdef',        '.notdef',            // 08 to 0B
+     '.notdef',         '.notdef',      '.notdef',        '.notdef',            // 0C to 0F
+     '.notdef',         '.notdef',      '.notdef',        '.notdef',            // 10 to 13
+     '.notdef',         '.notdef',      '.notdef',        '.notdef',            // 14 to 17
+     '.notdef',         '.notdef',      '.notdef',        '.notdef',            // 18 to 1B
+     '.notdef',         '.notdef',      '.notdef',        '.notdef',            // 1C to 1F
+     'space',           'exclam',       'quotedbl',       'numbersign',         // 20 to 23
+     'dollar',          'percent',      'ampersand',      'quotesingle',        // 24 to 27
+     'parenleft',       'parenright',   'asterisk',       'plus',               // 28 to 2B
+     'comma',           'hyphen',       'period',         'slash',              // 2C to 2F
+     'zero',            'one',          'two',            'three',              // 30 to 33
+     'four',            'five',         'six',            'seven',              // 34 to 37
+     'eight',           'nine',         'colon',          'semicolon',          // 38 to 3B
+     'less',            'equal',        'greater',        'question',           // 3C to 3F
+     'at',              'A',            'B',              'C',                  // 40 to 43
+     'D',               'E',            'F',              'G',                  // 44 to 47
+     'H',               'I',            'J',              'K',                  // 48 to 4B
+     'L',               'M',            'N',              'O',                  // 4C to 4F
+     'P',               'Q',            'R',              'S',                  // 50 to 53
+     'T',               'U',            'V',              'W',                  // 54 to 57
+     'X',               'Y',            'Z',              'bracketleft',        // 58 to 5B
+     'backslash',       'bracketright', 'asciicircum',    'underscore',         // 5C to 5F
+     'grave',           'a',            'b',              'c',                  // 60 to 63
+     'd',               'e',            'f',              'g',                  // 64 to 67
+     'h',               'i',            'j',              'k',                  // 68 to 6B
+     'l',               'm',            'n',              'o',                  // 6C to 6F
+     'p',               'q',            'r',              's',                  // 70 to 73
+     't',               'u',            'v',              'w',                  // 74 to 77
+     'x',               'y',            'z',              'braceleft',          // 78 to 7B
+     'bar',             'braceright',   'asciitilde',     '.notdef',            // 7C to 7F
+     'Euro',            '.notdef',      'quotesinglbase', 'florin',             // 80 to 83
+     'quotedblbase',    'ellipsis',     'dagger',         'daggerdbl',          // 84 to 87
+     'circumflex',      'perthousand',  '.notdef',        'guilsinglleft',      // 88 to 8B
+     '.notdef',         '.notdef',      '.notdef',        '.notdef',            // 8C to 8F
+     '.notdef',         'quoteleft',    'quoteright',     'quotedblleft',       // 90 to 93
+     'quotedblright',   'bullet',       'endash',         'emdash',             // 94 to 97
+     'tilde',           'trademark',    '.notdef',        'guilsinglright',     // 98 to 9B
+     '.notdef',         '.notdef',      '.notdef',        '.notdef',            // 9C to 9F
+     'space',           'exclamdown',   'cent',           'sterling',           // A0 to A3
+     'afii57636',       'yen',          'brokenbar',      'section',            // A4 to A7
+     'dieresis',        'copyright',    'multiply',       'guillemotleft',      // A8 to AB
+     'logicalnot',      'sfthyphen',    'registered',     'macron',             // AC to AF
+     'degree',          'plusminus',    'twosuperior',    'threesuperior',      // B0 to B3
+     'acute',           'mu',           'paragraph',      'middot',             // B4 to B7
+     'cedilla',         'onesuperior',  'divide',         'guillemotright',     // B8 to BB
+     'onequarter',      'onehalf',      'threequarters',  'questiondown',       // BC to BF
+     'afii57799',       'afii57801',    'afii57800',      'afii57802',          // C0 to C3
+     'afii57793',       'afii57794',    'afii57795',      'afii57798',          // C4 to C7
+     'afii57797',       'afii57806',    '.notdef',        'afii57796',          // C8 to CB
+     'afii57807',       'afii57839',    'afii57645',      'afii57841',          // CC to CF
+     'afii57842',       'afii57804',    'afii57803',      'afii57658',          // D0 to D3
+     'afii57716',       'afii57717',    'afii57718',      'gereshhebrew',       // D4 to D7
+     'gershayimhebrew', '.notdef',      '.notdef',        '.notdef',            // D8 to DB
+     '.notdef',         '.notdef',      '.notdef',        '.notdef',            // DC to DF
+     'afii57664',       'afii57665',    'afii57666',      'afii57667',          // E0 to E3
+     'afii57668',       'afii57669',    'afii57670',      'afii57671',          // E4 to E7
+     'afii57672',       'afii57673',    'afii57674',      'afii57675',          // E8 to EB
+     'afii57676',       'afii57677',    'afii57678',      'afii57679',          // EC to EF
+     'afii57680',       'afii57681',    'afii57682',      'afii57683',          // F0 to F3
+     'afii57684',       'afii57685',    'afii57686',      'afii57687',          // F4 to F7
+     'afii57688',       'afii57689',    'afii57690',      '.notdef',            // F8 to FB
+     '.notdef',         'afii299',      'afii300',        '.notdef');           // FC to FF
+
+const
+  cp1255_v: TTTFEncodingValues =
+    (0,       1,       2,       3,       4,        5,       6,       7,         // 00 to 07
+     8,       9,       10,      11,      12,       13,      14,      15,        // 08 to 0F
+     16,      17,      18,      19,      20,       21,      22,      23,        // 10 to 17
+     24,      25,      26,      27,      28,       29,      30,      31,        // 18 to 1F
+     32,      33,      34,      35,      36,       37,      38,      39,        // 20 to 27
+     40,      41,      42,      43,      44,       45,      46,      47,        // 28 to 2F
+     48,      49,      50,      51,      52,       53,      54,      55,        // 30 to 37
+     56,      57,      58,      59,      60,       61,      62,      63,        // 38 to 3F
+     64,      65,      66,      67,      68,       69,      70,      71,        // 40 to 47
+     72,      73,      74,      75,      76,       77,      78,      79,        // 48 to 4F
+     80,      81,      82,      83,      84,       85,      86,      87,        // 50 to 57
+     88,      89,      90,      91,      92,       93,      94,      95,        // 58 to 5F
+     96,      97,      98,      99,      100,      101,     102,     103,       // 60 to 67
+     104,     105,     106,     107,     108,      109,     110,     111,       // 68 to 6F
+     112,     113,     114,     115,     116,      117,     118,     119,       // 70 to 77
+     120,     121,     122,     123,     124,      125,     126,     127,       // 78 to 7F
+     8364,    -1,      8218,    402,     8222,     8230,    8224,    8225,      // 80 to 87
+     710,     8240,    -1,      8249,    -1,       -1,      -1,      -1,        // 88 to 8F
+     -1,      8216,    8217,    8220,    8221,     8226,    8211,    8212,      // 90 to 97
+     732,     8482,    -1,      8250,    -1,       -1,      -1,      -1,        // 98 to 9F
+     160,     161,     162,     163,     8362,     165,     166,     167,       // A0 to A7
+     168,     169,     215,     171,     172,      173,     174,     175,       // A8 to AF
+     176,     177,     178,     179,     180,      181,     182,     183,       // B0 to B7
+     184,     185,     247,     187,     188,      189,     190,     191,       // B8 to BF
+     1456,    1457,    1458,    1459,    1460,     1461,    1462,    1463,      // C0 to C7
+     1464,    1465,    -1,      1467,    1468,     1469,    1470,    1471,      // C8 to CF
+     1472,    1473,    1474,    1475,    1520,     1521,    1522,    1523,      // D0 to D7
+     1524,    -1,      -1,      -1,      -1,       -1,      -1,      -1,        // D8 to DF
+     1488,    1489,    1490,    1491,    1492,     1493,    1494,    1495,      // E0 to E7
+     1496,    1497,    1498,    1499,    1500,     1501,    1502,    1503,      // E8 to EF
+     1504,    1505,    1506,    1507,    1508,     1509,    1510,    1511,      // F0 to F7
+     1512,    1513,    1514,    -1,      -1,       8206,    8207,    -1);       // F8 to FF
+
+const
+  cp1257_n: TTTFEncodingNames =
+    ('.notdef',       '.notdef',      '.notdef',        '.notdef',            // 00 to 03
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 04 to 07
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 08 to 0B
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 0C to 0F
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 10 to 13
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 14 to 17
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 18 to 1B
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 1C to 1F
+     'space',         'exclam',       'quotedbl',       'numbersign',         // 20 to 23
+     'dollar',        'percent',      'ampersand',      'quotesingle',        // 24 to 27
+     'parenleft',     'parenright',   'asterisk',       'plus',               // 28 to 2B
+     'comma',         'hyphen',       'period',         'slash',              // 2C to 2F
+     'zero',          'one',          'two',            'three',              // 30 to 33
+     'four',          'five',         'six',            'seven',              // 34 to 37
+     'eight',         'nine',         'colon',          'semicolon',          // 38 to 3B
+     'less',          'equal',        'greater',        'question',           // 3C to 3F
+     'at',            'A',            'B',              'C',                  // 40 to 43
+     'D',             'E',            'F',              'G',                  // 44 to 47
+     'H',             'I',            'J',              'K',                  // 48 to 4B
+     'L',             'M',            'N',              'O',                  // 4C to 4F
+     'P',             'Q',            'R',              'S',                  // 50 to 53
+     'T',             'U',            'V',              'W',                  // 54 to 57
+     'X',             'Y',            'Z',              'bracketleft',        // 58 to 5B
+     'backslash',     'bracketright', 'asciicircum',    'underscore',         // 5C to 5F
+     'grave',         'a',            'b',              'c',                  // 60 to 63
+     'd',             'e',            'f',              'g',                  // 64 to 67
+     'h',             'i',            'j',              'k',                  // 68 to 6B
+     'l',             'm',            'n',              'o',                  // 6C to 6F
+     'p',             'q',            'r',              's',                  // 70 to 73
+     't',             'u',            'v',              'w',                  // 74 to 77
+     'x',             'y',            'z',              'braceleft',          // 78 to 7B
+     'bar',           'braceright',   'asciitilde',     '.notdef',            // 7C to 7F
+     'Euro',          '.notdef',      'quotesinglbase', '.notdef',            // 80 to 83
+     'quotedblbase',  'ellipsis',     'dagger',         'daggerdbl',          // 84 to 87
+     '.notdef',       'perthousand',  '.notdef',        'guilsinglleft',      // 88 to 8B
+     '.notdef',       'dieresis',     'caron',          'cedilla',            // 8C to 8F
+     '.notdef',       'quoteleft',    'quoteright',     'quotedblleft',       // 90 to 93
+     'quotedblright', 'bullet',       'endash',         'emdash',             // 94 to 97
+     '.notdef',       'trademark',    '.notdef',        'guilsinglright',     // 98 to 9B
+     '.notdef',       'macron',       'ogonek',         '.notdef',            // 9C to 9F
+     'space',         '.notdef',      'cent',           'sterling',           // A0 to A3
+     'currency',      '.notdef',      'brokenbar',      'section',            // A4 to A7
+     'Oslash',        'copyright',    'Rcommaaccent',   'guillemotleft',      // A8 to AB
+     'logicalnot',    'hyphen',       'registered',     'AE',                 // AC to AF
+     'degree',        'plusminus',    'twosuperior',    'threesuperior',      // B0 to B3
+     'acute',         'mu',           'paragraph',      'periodcentered',     // B4 to B7
+     'oslash',        'onesuperior',  'rcommaaccent',   'guillemotright',     // B8 to BB
+     'onequarter',    'onehalf',      'threequarters',  'ae',                 // BC to BF
+     'Aogonek',       'Iogonek',      'Amacron',        'Cacute',             // C0 to C3
+     'Adieresis',     'Aring',        'Eogonek',        'Emacron',            // C4 to C7
+     'Ccaron',        'Eacute',       'Zacute',         'Edotaccent',         // C8 to CB
+     'Gcommaaccent',  'Kcommaaccent', 'Imacron',        'Lcommaaccent',       // CC to CF
+     'Scaron',        'Nacute',       'Ncommaaccent',   'Oacute',             // D0 to D3
+     'Omacron',       'Otilde',       'Odieresis',      'multiply',           // D4 to D7
+     'Uogonek',       'Lslash',       'Sacute',         'Umacron',            // D8 to DB
+     'Udieresis',     'Zdotaccent',   'Zcaron',         'germandbls',         // DC to DF
+     'aogonek',       'iogonek',      'amacron',        'cacute',             // E0 to E3
+     'adieresis',     'aring',        'eogonek',        'emacron',            // E4 to E7
+     'ccaron',        'eacute',       'zacute',         'edotaccent',         // E8 to EB
+     'gcommaaccent',  'kcommaaccent', 'imacron',        'lcommaaccent',       // EC to EF
+     'scaron',        'nacute',       'ncommaaccent',   'oacute',             // F0 to F3
+     'omacron',       'otilde',       'odieresis',      'divide',             // F4 to F7
+     'uogonek',       'lslash',       'sacute',         'umacron',            // F8 to FB
+     'udieresis',     'zdotaccent',   'zcaron',         'dotaccent');         // FC to FF
+
+const
+  cp1257_v: TTTFEncodingValues =
+    (0,       1,       2,       3,       4,        5,       6,       7,         // 00 to 07
+     8,       9,       10,      11,      12,       13,      14,      15,        // 08 to 0F
+     16,      17,      18,      19,      20,       21,      22,      23,        // 10 to 17
+     24,      25,      26,      27,      28,       29,      30,      31,        // 18 to 1F
+     32,      33,      34,      35,      36,       37,      38,      39,        // 20 to 27
+     40,      41,      42,      43,      44,       45,      46,      47,        // 28 to 2F
+     48,      49,      50,      51,      52,       53,      54,      55,        // 30 to 37
+     56,      57,      58,      59,      60,       61,      62,      63,        // 38 to 3F
+     64,      65,      66,      67,      68,       69,      70,      71,        // 40 to 47
+     72,      73,      74,      75,      76,       77,      78,      79,        // 48 to 4F
+     80,      81,      82,      83,      84,       85,      86,      87,        // 50 to 57
+     88,      89,      90,      91,      92,       93,      94,      95,        // 58 to 5F
+     96,      97,      98,      99,      100,      101,     102,     103,       // 60 to 67
+     104,     105,     106,     107,     108,      109,     110,     111,       // 68 to 6F
+     112,     113,     114,     115,     116,      117,     118,     119,       // 70 to 77
+     120,     121,     122,     123,     124,      125,     126,     127,       // 78 to 7F
+     8364,    -1,      8218,    -1,      8222,     8230,    8224,    8225,      // 80 to 87
+     -1,      8240,    -1,      8249,    -1,       168,     711,     184,       // 88 to 8F
+     -1,      8216,    8217,    8220,    8221,     8226,    8211,    8212,      // 90 to 97
+     -1,      8482,    -1,      8250,    -1,       175,     731,     -1,        // 98 to 9F
+     160,     -1,      162,     163,     164,      -1,      166,     167,       // A0 to A7
+     216,     169,     342,     171,     172,      173,     174,     198,       // A0 to AF
+     176,     177,     178,     179,     180,      181,     182,     183,       // B0 to B7
+     248,     185,     343,     187,     188,      189,     190,     230,       // B8 to BF
+     260,     302,     256,     262,     196,      197,     280,     274,       // C0 to C7
+     268,     201,     377,     278,     290,      310,     298,     315,       // C8 to CF
+     352,     323,     325,     211,     332,      213,     214,     215,       // D0 to D7
+     370,     321,     346,     362,     220,      379,     381,     223,       // D8 to DF
+     261,     303,     257,     263,     228,      229,     281,     275,       // E0 to E7
+     269,     233,     378,     279,     291,      311,     299,     316,       // E8 to EF
+     353,     324,     326,     243,     333,      245,     246,     247,       // F0 to F7
+     371,     322,     347,     363,     252,      380,     382,     729);      // F8 to FF
+
+const
+  cp1258_n: TTTFEncodingNames =
+    ('.notdef',       '.notdef',      '.notdef',        '.notdef',            // 00 to 03
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 04 to 07
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 08 to 0B
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 0C to 0F
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 10 to 13
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 14 to 17
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 18 to 1B
+     '.notdef',       '.notdef',      '.notdef',        '.notdef',            // 1C to 1F
+     'space',         'exclam',       'quotedbl',       'numbersign',         // 20 to 23
+     'dollar',        'percent',      'ampersand',      'quotesingle',        // 24 to 27
+     'parenleft',     'parenright',   'asterisk',       'plus',               // 28 to 2B
+     'comma',         'hyphen',       'period',         'slash',              // 2C to 2F
+     'zero',          'one',          'two',            'three',              // 30 to 33
+     'four',          'five',         'six',            'seven',              // 34 to 37
+     'eight',         'nine',         'colon',          'semicolon',          // 38 to 3B
+     'less',          'equal',        'greater',        'question',           // 3C to 3F
+     'at',            'A',            'B',              'C',                  // 40 to 43
+     'D',             'E',            'F',              'G',                  // 44 to 47
+     'H',             'I',            'J',              'K',                  // 48 to 4B
+     'L',             'M',            'N',              'O',                  // 4C to 4F
+     'P',             'Q',            'R',              'S',                  // 50 to 53
+     'T',             'U',            'V',              'W',                  // 54 to 57
+     'X',             'Y',            'Z',              'bracketleft',        // 58 to 5B
+     'backslash',     'bracketright', 'asciicircum',    'underscore',         // 5C to 5F
+     'grave',         'a',            'b',              'c',                  // 60 to 63
+     'd',             'e',            'f',              'g',                  // 64 to 67
+     'h',             'i',            'j',              'k',                  // 68 to 6B
+     'l',             'm',            'n',              'o',                  // 6C to 6F
+     'p',             'q',            'r',              's',                  // 70 to 73
+     't',             'u',            'v',              'w',                  // 74 to 77
+     'x',             'y',            'z',              'braceleft',          // 78 to 7B
+     'bar',           'braceright',   'asciitilde',     '.notdef',            // 7C to 7F
+     'Euro',          '.notdef',      'quotesinglbase', 'florin',             // 80 to 83
+     'quotedblbase',  'ellipsis',     'dagger',         'daggerdbl',          // 84 to 87
+     'circumflex',    'perthousand',  '.notdef',        'guilsinglleft',      // 88 to 8B
+     'OE',            '.notdef',      '.notdef',        '.notdef',            // 8C to 8F
+     '.notdef',       'quoteleft',    'quoteright',     'quotedblleft',       // 90 to 93
+     'quotedblright', 'bullet',       'endash',         'emdash',             // 94 to 97
+     'tilde',         'trademark',    '.notdef',        'guilsinglright',     // 98 to 9B
+     'oe',            '.notdef',      '.notdef',        'Ydieresis',          // 9C to 9F
+     'space',         'exclamdown',   'cent',           'sterling',           // A0 to A3
+     'currency',      'yen',          'brokenbar',      'section',            // A4 to A7
+     'dieresis',      'copyright',    'ordfeminine',    'guillemotleft',      // A8 to AB
+     'logicalnot',    'hyphen',       'registered',     'macron',             // AC to AF
+     'degree',        'plusminus',    'twosuperior',    'threesuperior',      // B0 to B3
+     'acute',         'mu',           'paragraph',             'periodcentered',     // B4 to B7
+     'cedilla',       'onesuperior',  'ordmasculine',   'guillemotright',     // B8 to BB
+     'onequarter',    'onehalf',      'threequarters',  'questiondown',       // BC to BF
+     'Agrave',        'Aacute',       'Acircumflex',    'Abreve',             // C0 to C3
+     'Adieresis',     'Aring',        'AE',             'Ccedilla',           // C4 to C7
+     'Egrave',        'Eacute',       'Ecircumflex',    'Edieresis',          // C8 to CB
+     'gravecomb',     'Iacute',       'Icircumflex',    'Idieresis',          // CC to CF
+     'Dcroat',        'Ntilde',       'hookabovecomb',  'Oacute',             // D0 to D3
+     'Ocircumflex',   'Ohorn',        'Odieresis',      'multiply',           // D4 to D7
+     'Oslash',        'Ugrave',       'Uacute',         'Ucircumflex',        // D8 to DB
+     'Udieresis',     'Uhorn',        'tildecomb',      'germandbls',         // DC to DF
+     'agrave',        'aacute',       'acircumflex',    'abreve',             // E0 to E3
+     'adieresis',     'aring',        'ae',             'ccedilla',           // E4 to E7
+     'egrave',        'eacute',       'ecircumflex',    'edieresis',          // E8 to EB
+     'acutecomb',     'iacute',       'icircumflex',    'idieresis',          // EC to EF
+     'dcroat',        'ntilde',       'dotbelowcomb',   'oacute',             // F0 to F3
+     'ocircumflex',   'ohorn',        'odieresis',      'divide',             // F4 to F7
+     'oslash',        'ugrave',       'uacute',         'ucircumflex',        // F8 to FB
+     'udieresis',     'uhorn',        'dong',           'ydieresis');         // FC to FF
+
+const
+  cp1258_v: TTTFEncodingValues =
+    (0,       1,       2,       3,       4,        5,       6,       7,         // 00 to 07
+     8,       9,       10,      11,      12,       13,      14,      15,        // 08 to 0F
+     16,      17,      18,      19,      20,       21,      22,      23,        // 10 to 17
+     24,      25,      26,      27,      28,       29,      30,      31,        // 18 to 1F
+     32,      33,      34,      35,      36,       37,      38,      39,        // 20 to 27
+     40,      41,      42,      43,      44,       45,      46,      47,        // 28 to 2F
+     48,      49,      50,      51,      52,       53,      54,      55,        // 30 to 37
+     56,      57,      58,      59,      60,       61,      62,      63,        // 38 to 3F
+     64,      65,      66,      67,      68,       69,      70,      71,        // 40 to 47
+     72,      73,      74,      75,      76,       77,      78,      79,        // 48 to 4F
+     80,      81,      82,      83,      84,       85,      86,      87,        // 50 to 57
+     88,      89,      90,      91,      92,       93,      94,      95,        // 58 to 5F
+     96,      97,      98,      99,      100,      101,     102,     103,       // 60 to 67
+     104,     105,     106,     107,     108,      109,     110,     111,       // 68 to 6F
+     112,     113,     114,     115,     116,      117,     118,     119,       // 70 to 77
+     120,     121,     122,     123,     124,      125,     126,     127,       // 78 to 7F
+     8264,    -1,      8218,    402,     8222,     8230,    8224,    8225,      // 80 to 87
+     710,     8240,    -1,      8249,    338,      -1,      -1,      -1,        // 88 to 8F
+     -1,      8216,    8217,    8220,    8221,     8226,    8211,    8212,      // 90 to 97
+     732,     8482,    -1,      8250,    339,      -1,      -1,      376,       // 98 to 9F
+     160,     161,     162,     163,     164,      165,     166,     167,       // A0 to A7
+     168,     169,     170,     171,     172,      173,     174,     175,       // A8 to AF
+     176,     177,     178,     179,     180,      181,     182,     183,       // B0 to B7
+     184,     185,     186,     187,     188,      189,     190,     191,       // B8 to BF
+     192,     193,     194,     258,     196,      197,     198,     199,       // C0 to C7
+     200,     201,     202,     203,     768,      205,     206,     207,       // C8 to CF
+     272,     209,     777,     211,     212,      416,     214,     215,       // D0 to D7
+     216,     217,     218,     219,     220,      431,     771,     223,       // D8 to DF
+     224,     225,     226,     259,     228,      229,     230,     231,       // E0 to E7
+     232,     233,     234,     235,     769,      237,     238,     239,       // E8 to EF
+     273,     241,     803,     243,     244,      417,     246,     247,       // F0 to F7
+     248,     249,     250,     251,     252,      432,     8363,    255);      // F8 to FF
+
+const
+  iso_8859_1_n: TTTFEncodingNames =
+    ('.notdef',     '.notdef',      '.notdef',      '.notdef',            // 00 to 03
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 04 to 07
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 08 to 0B
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 0C to 0F
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 10 to 13
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 14 to 17
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 18 to 1B
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 1C to 1F
+     'space',       'exclam',       'quotedbl',     'numbersign',         // 20 to 23
+     'dollar',      'percent',      'ampersand',    'quotesingle',        // 24 to 27
+     'parenleft',   'parenright',   'asterisk',     'plus',               // 28 to 2B
+     'comma',       'hyphen',       'period',       'slash',              // 2C to 2F
+     'zero',        'one',          'two',          'three',              // 30 to 33
+     'four',        'five',         'six',          'seven',              // 34 to 37
+     'eight',       'nine',         'colon',        'semicolon',          // 38 to 3B
+     'less',        'equal',        'greater',      'question',           // 3C to 3F
+     'at',          'A',            'B',            'C',                  // 40 to 43
+     'D',           'E',            'F',            'G',                  // 44 to 47
+     'H',           'I',            'J',            'K',                  // 48 to 4B
+     'L',           'M',            'N',            'O',                  // 4C to 4F
+     'P',           'Q',            'R',            'S',                  // 50 to 53
+     'T',           'U',            'V',            'W',                  // 54 to 57
+     'X',           'Y',            'Z',            'bracketleft',        // 58 to 5B
+     'backslash',   'bracketright', 'asciicircum',  'underscore',         // 5C to 5F
+     'grave',       'a',            'b',            'c',                  // 60 to 63
+     'd',           'e',            'f',            'g',                  // 64 to 67
+     'h',           'i',            'j',            'k',                  // 68 to 6B
+     'l',           'm',            'n',            'o',                  // 6C to 6F
+     'p',           'q',            'r',            's',                  // 70 to 73
+     't',           'u',            'v',            'w',                  // 74 to 77
+     'x',           'y',            'z',            'braceleft',          // 78 to 7B
+     'bar',         'braceright',   'asciitilde',   '.notdef',            // 7C to 7F
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 80 to 83
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 84 to 87
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 88 to 8B
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 8C to 8F
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 90 to 93
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 94 to 97
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 98 to 9B
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 9C to 9F
+     'space',       'exclamdown',   'cent',         'sterling',           // A0 to A3
+     'currency',    'yen',          'brokenbar',    'section',            // A4 to A7
+     'dieresis',    'copyright',    'ordfeminine',  'guillemotleft',      // A8 to AB
+     'logicalnot',  'hyphen',       'registered',   'macron',             // AC to AF
+     'degree',      'plusminus',    'twosuperior',  'threesuperior',      // B0 to B3
+     'acute',       'mu',           'paragraph',    'periodcentered',     // B4 to B7
+     'cedilla',     'onesuperior',  'ordmasculine', 'guillemotright',     // B8 to BB
+     'onequarter',  'onehalf',      'threequarters','questiondown',       // BC to BF
+     'Agrave',      'Aacute',       'Acircumflex',  'Atilde',             // C0 to C3
+     'Adieresis',   'Aring',        'AE',           'Ccedilla',           // C4 to C7
+     'Egrave',      'Eacute',       'Ecircumflex',  'Edieresis',          // C8 to CB
+     'Igrave',      'Iacute',       'Icircumflex',  'Idieresis',          // CC to CF
+     'Eth',         'Ntilde',       'Ograve',       'Oacute',             // D0 to D3
+     'Ocircumflex', 'Otilde',       'Odieresis',    'multiply',           // D4 to D7
+     'Oslash',      'Ugrave',       'Uacute',       'Ucircumflex',        // D8 to DB
+     'Udieresis',   'Yacute',       'Thorn',        'germandbls',         // DC to DF
+     'agrave',      'aacute',       'acircumflex',  'atilde',             // E0 to E3
+     'adieresis',   'aring',        'ae',           'ccedilla',           // E4 to E7
+     'egrave',      'eacute',       'ecircumflex',  'edieresis',          // E8 to EB
+     'igrave',      'iacute',       'icircumflex',  'idieresis',          // EC to EF
+     'eth',         'ntilde',       'ograve',       'oacute',             // F0 to F3
+     'ocircumflex', 'otilde',       'odieresis',    'divide',             // F4 to F7
+     'oslash',      'ugrave',       'uacute',       'ucircumflex',        // F8 to FB
+     'udieresis',   'yacute',       'thorn',        'ydieresis');         // FC to FF
+
+const
+  iso_8859_1_v: TTTFEncodingValues =
+    (0,       1,       2,       3,       4,        5,       6,       7,         // 00 to 07
+     8,       9,       10,      11,      12,       13,      14,      15,        // 08 to 0F
+     16,      17,      18,      19,      20,       21,      22,      23,        // 10 to 17
+     24,      25,      26,      27,      28,       29,      30,      31,        // 18 to 1F
+     32,      33,      34,      35,      36,       37,      38,      39,        // 20 to 27
+     40,      41,      42,      43,      44,       45,      46,      47,        // 28 to 2F
+     48,      49,      50,      51,      52,       53,      54,      55,        // 30 to 37
+     56,      57,      58,      59,      60,       61,      62,      63,        // 38 to 3F
+     64,      65,      66,      67,      68,       69,      70,      71,        // 40 to 47
+     72,      73,      74,      75,      76,       77,      78,      79,        // 48 to 4F
+     80,      81,      82,      83,      84,       85,      86,      87,        // 50 to 57
+     88,      89,      90,      91,      92,       93,      94,      95,        // 58 to 5F
+     96,      97,      98,      99,      100,      101,     102,     103,       // 60 to 67
+     104,     105,     106,     107,     108,      109,     110,     111,       // 68 to 6F
+     112,     113,     114,     115,     116,      117,     118,     119,       // 70 to 77
+     120,     121,     122,     123,     124,      125,     126,     127,       // 78 to 7F
+     -1,      -1,      -1,      -1,      -1,       -1,      -1,      -1,        // 80 to 87
+     -1,      -1,      -1,      -1,      -1,       -1,      -1,      -1,        // 88 to 8F
+     -1,      -1,      -1,      -1,      -1,       -1,      -1,      -1,        // 90 to 97
+     -1,      -1,      -1,      -1,      -1,       -1,      -1,      -1,        // 98 to 9F
+     160,     161,     162,     163,     164,      165,     166,     167,       // A0 to A7
+     168,     169,     170,     171,     172,      173,     174,     175,       // A8 to AF
+     176,     177,     178,     179,     180,      181,     182,     183,       // B0 to B7
+     184,     185,     186,     187,     188,      189,     190,     191,       // B8 to BF
+     192,     193,     194,     195,     196,      197,     198,     199,       // C0 to C7
+     200,     201,     202,     203,     204,      205,     206,     207,       // C8 to CF
+     208,     209,     210,     211,     212,      213,     214,     215,       // D0 to D7
+     216,     217,     218,     219,     220,      221,     222,     223,       // D8 to DF
+     224,     225,     226,     227,     228,      229,     230,     231,       // E0 to E7
+     232,     233,     234,     235,     236,      237,     238,     239,       // E8 to EF
+     240,     241,     242,     243,     244,      245,     246,     247,       // F0 to F7
+     248,     249,     250,     251,     252,      253,     254,     255);      // F8 to FF
+
+const
+  iso_8859_2_n: TTTFEncodingNames =
+    ('.notdef',     '.notdef',      '.notdef',      '.notdef',            // 00 to 03
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 04 to 07
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 08 to 0B
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 0C to 0F
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 10 to 13
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 14 to 17
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 18 to 1B
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 1C to 1F
+     'space',       'exclam',       'quotedbl',     'numbersign',         // 20 to 23
+     'dollar',      'percent',      'ampersand',    'quotesingle',        // 24 to 27
+     'parenleft',   'parenright',   'asterisk',     'plus',               // 28 to 2B
+     'comma',       'hyphen',       'period',       'slash',              // 2C to 2F
+     'zero',        'one',          'two',          'three',              // 30 to 33
+     'four',        'five',         'six',          'seven',              // 34 to 37
+     'eight',       'nine',         'colon',        'semicolon',          // 38 to 3B
+     'less',        'equal',        'greater',      'question',           // 3C to 3F
+     'at',          'A',            'B',            'C',                  // 40 to 43
+     'D',           'E',            'F',            'G',                  // 44 to 47
+     'H',           'I',            'J',            'K',                  // 48 to 4B
+     'L',           'M',            'N',            'O',                  // 4C to 4F
+     'P',           'Q',            'R',            'S',                  // 50 to 53
+     'T',           'U',            'V',            'W',                  // 54 to 57
+     'X',           'Y',            'Z',            'bracketleft',        // 58 to 5B
+     'backslash',   'bracketright', 'asciicircum',  'underscore',         // 5C to 5F
+     'grave',       'a',            'b',            'c',                  // 60 to 63
+     'd',           'e',            'f',            'g',                  // 64 to 67
+     'h',           'i',            'j',            'k',                  // 68 to 6B
+     'l',           'm',            'n',            'o',                  // 6C to 6F
+     'p',           'q',            'r',            's',                  // 70 to 73
+     't',           'u',            'v',            'w',                  // 74 to 77
+     'x',           'y',            'z',            'braceleft',          // 78 to 7B
+     'bar',         'braceright',   'asciitilde',   '.notdef',            // 7C to 7F
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 80 to 83
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 84 to 87
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 88 to 8B
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 8C to 8F
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 90 to 93
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 94 to 97
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 98 to 9B
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 9C to 9F
+     'space',       'Aogonek',      'breve',        'Lslash',             // A0 to A3
+     'currency',    'Lcaron',       'Sacute',       'section',            // A4 to A7
+     'dieresis',    'Scaron',       'Scedilla',     'Tcaron',             // A8 to AB
+     'Zacute',      'hyphen',       'Zcaron',       'Zdotaccent',         // AC to AF
+     'degree',      'aogonek',      'ogonek',       'lslash',             // B0 to B3
+     'acute',       'lcaron',       'sacute',       'caron',              // B4 to B7
+     'cedilla',     'scaron',       'scedilla',     'tcaron',             // B8 to BB
+     'zacute',      'hungarumlaut', 'zcaron',       'zdotaccent',         // BC to BF
+     'Racute',      'Aacute',       'Acircumflex',  'Abreve',             // C0 to C3
+     'Adieresis',   'Lacute',       'Cacute',       'Ccedilla',           // C4 to C7
+     'Ccaron',      'Eacute',       'Eogonek',      'Edieresis',          // C8 to CB
+     'Ecaron',      'Iacute',       'Icircumflex',  'Dcaron',             // CC to CF
+     'Dcroat',      'Nacute',       'Ncaron',       'Oacute',             // D0 to D3
+     'Ocircumflex', 'Ohungarumlaut','Odieresis',    'multiply',           // D4 to D7
+     'Rcaron',      'Uring',        'Uacute',       'Uhungarumlaut',      // D8 to DB
+     'Udieresis',   'Yacute',       'Tcommaaccent', 'germandbls',         // DC to DF
+     'racute',      'aacute',       'acircumflex',  'abreve',             // E0 to E3
+     'adieresis',   'lacute',       'cacute',       'ccedilla',           // E4 to E7
+     'ccaron',      'eacute',       'eogonek',      'edieresis',          // E8 to EB
+     'ecaron',      'iacute',       'icircumflex',  'dcaron',             // EC to EF
+     'dcroat',      'nacute',       'ncaron',       'oacute',             // F0 to F3
+     'ocircumflex', 'ohungarumlaut','odieresis',    'divide',             // F4 to F7
+     'rcaron',      'uring',        'uacute',       'uhungarumlaut',      // F8 to FB
+     'udieresis',   'yacute',       'tcommaaccent', 'dotaccent');         // FC to FF
+
+const
+  iso_8859_2_v: TTTFEncodingValues =
+    (0,       1,       2,       3,       4,        5,       6,       7,         // 00 to 07
+     8,       9,       10,      11,      12,       13,      14,      15,        // 08 to 0F
+     16,      17,      18,      19,      20,       21,      22,      23,        // 10 to 17
+     24,      25,      26,      27,      28,       29,      30,      31,        // 18 to 1F
+     32,      33,      34,      35,      36,       37,      38,      39,        // 20 to 27
+     40,      41,      42,      43,      44,       45,      46,      47,        // 28 to 2F
+     48,      49,      50,      51,      52,       53,      54,      55,        // 30 to 37
+     56,      57,      58,      59,      60,       61,      62,      63,        // 38 to 3F
+     64,      65,      66,      67,      68,       69,      70,      71,        // 40 to 47
+     72,      73,      74,      75,      76,       77,      78,      79,        // 48 to 4F
+     80,      81,      82,      83,      84,       85,      86,      87,        // 50 to 57
+     88,      89,      90,      91,      92,       93,      94,      95,        // 58 to 5F
+     96,      97,      98,      99,      100,      101,     102,     103,       // 60 to 67
+     104,     105,     106,     107,     108,      109,     110,     111,       // 68 to 6F
+     112,     113,     114,     115,     116,      117,     118,     119,       // 70 to 77
+     120,     121,     122,     123,     124,      125,     126,     127,       // 78 to 7F
+     -1,      -1,      -1,      -1,      -1,       -1,      -1,      -1,        // 80 to 87
+     -1,      -1,      -1,      -1,      -1,       -1,      -1,      -1,        // 88 to 8F
+     -1,      -1,      -1,      -1,      -1,       -1,      -1,      -1,        // 90 to 97
+     -1,      -1,      -1,      -1,      -1,       -1,      -1,      -1,        // 98 to 9F
+     160,     260,     728,     321,     164,      317,     346,     167,       // A0 to A7
+     168,     352,     350,     356,     377,      173,     381,     379,       // A8 to AF
+     176,     261,     731,     322,     180,      318,     347,     711,       // B0 to B7
+     184,     353,     351,     357,     378,      733,     382,     380,       // B8 to BF
+     340,     193,     194,     258,     196,      313,     262,     199,       // C0 to C7
+     268,     201,     280,     203,     282,      205,     206,     270,       // C8 to CF
+     272,     323,     327,     211,     212,      336,     214,     215,       // D0 to D7
+     344,     366,     218,     368,     220,      221,     354,     223,       // D8 to DF
+     341,     225,     226,     259,     228,      314,     263,     231,       // E0 to E7
+     269,     233,     281,     235,     283,      237,     238,     271,       // E8 to EF
+     273,     324,     328,     243,     244,      337,     246,     247,       // F0 to F7
+     345,     367,     250,     369,     252,      253,     355,     729);      // F8 to FF
+
+const
+  iso_8859_4_n: TTTFEncodingNames =
+    ('.notdef',     '.notdef',      '.notdef',      '.notdef',            // 00 to 03
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 04 to 07
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 08 to 0B
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 0C to 0F
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 10 to 13
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 14 to 17
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 18 to 1B
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 1C to 1F
+     'space',       'exclam',       'quotedbl',     'numbersign',         // 20 to 23
+     'dollar',      'percent',      'ampersand',    'quotesingle',        // 24 to 27
+     'parenleft',   'parenright',   'asterisk',     'plus',               // 28 to 2B
+     'comma',       'hyphen',       'period',       'slash',              // 2C to 2F
+     'zero',        'one',          'two',          'three',              // 30 to 33
+     'four',        'five',         'six',          'seven',              // 34 to 37
+     'eight',       'nine',         'colon',        'semicolon',          // 38 to 3B
+     'less',        'equal',        'greater',      'question',           // 3C to 3F
+     'at',          'A',            'B',            'C',                  // 40 to 43
+     'D',           'E',            'F',            'G',                  // 44 to 47
+     'H',           'I',            'J',            'K',                  // 48 to 4B
+     'L',           'M',            'N',            'O',                  // 4C to 4F
+     'P',           'Q',            'R',            'S',                  // 50 to 53
+     'T',           'U',            'V',            'W',                  // 54 to 57
+     'X',           'Y',            'Z',            'bracketleft',        // 58 to 5B
+     'backslash',   'bracketright', 'asciicircum',  'underscore',         // 5C to 5F
+     'grave',       'a',            'b',            'c',                  // 60 to 63
+     'd',           'e',            'f',            'g',                  // 64 to 67
+     'h',           'i',            'j',            'k',                  // 68 to 6B
+     'l',           'm',            'n',            'o',                  // 6C to 6F
+     'p',           'q',            'r',            's',                  // 70 to 73
+     't',           'u',            'v',            'w',                  // 74 to 77
+     'x',           'y',            'z',            'braceleft',          // 78 to 7B
+     'bar',         'braceright',   'asciitilde',   '.notdef',            // 7C to 7F
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 80 to 83
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 84 to 87
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 88 to 8B
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 8C to 8F
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 90 to 93
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 94 to 97
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 98 to 9B
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 9C to 9F
+     'space',       'Aogonek',      'kgreenlandic', 'Rcommaaccent',       // A0 to A3
+     'currency',    'Itilde',       'Lcommaaccent', 'section',            // A4 to A7
+     'dieresis',    'Scaron',       'Emacron',      'Gcommaaccent',       // A8 to AB
+     'Tbar',        'hyphen',       'Zcaron',       'macron',             // AC to AF
+     'degree',      'aogonek',      'ogonek',       'rcommaaccent',       // B0 to B3
+     'acute',       'itilde',       'lcommaaccent', 'caron',              // B4 to B7
+     'cedilla',     'scaron',       'emacron',      'gcommaaccent',       // B8 to BB
+     'tbar',        'Eng',          'zcaron',       'eng',                // BC to BF
+     'Amacron',     'Aacute',       'Acircumflex',  'Atilde',             // C0 to C3
+     'Adieresis',   'Aring',        'AE',           'Iogonek',            // C4 to C7
+     'Ccaron',      'Eacute',       'Eogonek',      'Edieresis',          // C8 to CB
+     'Edotaccent',  'Iacute',       'Icircumflex',  'Imacron',            // CC to CF
+     'Dcroat',      'Ncommaaccent', 'Omacron',      'Kcommaaccent',       // D0 to D3
+     'Ocircumflex', 'Otilde',       'Odieresis',    'multiply',           // D4 to D7
+     'Oslash',      'Uogonek',      'Uacute',       'Ucircumflex',        // D8 to DB
+     'Udieresis',   'Utilde',       'Umacron',      'germandbls',         // DC to DF
+     'amacron',     'aacute',       'acircumflex',  'atilde',             // E0 to E3
+     'adieresis',   'aring',        'ae',           'iogonek',            // E4 to E7
+     'ccaron',      'eacute',       'eogonek',      'edieresis',          // E8 to EB
+     'edotaccent',  'iacute',       'icircumflex',  'imacron',            // EC to EF
+     'dcroat',      'ncommaaccent', 'omacron',      'kcommaaccent',       // F0 to F3
+     'ocircumflex', 'otilde',       'odieresis',    'divide',             // F4 to F7
+     'oslash',      'uogonek',      'uacute',       'ucircumflex',        // F8 to FB
+     'udieresis',   'utilde',       'umacron',      'dotaccent');         // FC to FF
+
+const
+  iso_8859_4_v: TTTFEncodingValues =
+    (0,       1,       2,       3,       4,        5,       6,       7,         // 00 to 07
+     8,       9,       10,      11,      12,       13,      14,      15,        // 08 to 0F
+     16,      17,      18,      19,      20,       21,      22,      23,        // 10 to 17
+     24,      25,      26,      27,      28,       29,      30,      31,        // 18 to 1F
+     32,      33,      34,      35,      36,       37,      38,      39,        // 20 to 27
+     40,      41,      42,      43,      44,       45,      46,      47,        // 28 to 2F
+     48,      49,      50,      51,      52,       53,      54,      55,        // 30 to 37
+     56,      57,      58,      59,      60,       61,      62,      63,        // 38 to 3F
+     64,      65,      66,      67,      68,       69,      70,      71,        // 40 to 47
+     72,      73,      74,      75,      76,       77,      78,      79,        // 48 to 4F
+     80,      81,      82,      83,      84,       85,      86,      87,        // 50 to 57
+     88,      89,      90,      91,      92,       93,      94,      95,        // 58 to 5F
+     96,      97,      98,      99,      100,      101,     102,     103,       // 60 to 67
+     104,     105,     106,     107,     108,      109,     110,     111,       // 68 to 6F
+     112,     113,     114,     115,     116,      117,     118,     119,       // 70 to 77
+     120,     121,     122,     123,     124,      125,     126,     127,       // 78 to 7F
+     -1,      -1,      -1,      -1,      -1,       -1,      -1,      -1,        // 80 to 87
+     -1,      -1,      -1,      -1,      -1,       -1,      -1,      -1,        // 88 to 8F
+     -1,      -1,      -1,      -1,      -1,       -1,      -1,      -1,        // 90 to 97
+     -1,      -1,      -1,      -1,      -1,       -1,      -1,      -1,        // 98 to 9F
+     160,     260,     312,     342,     164,      296,     315,     167,       // A4 to A7
+     168,     352,     274,     290,     358,      173,     381,     175,       // AC to AF
+     176,     261,     731,     343,     180,      297,     316,     711,       // B4 to B7
+     184,     353,     275,     291,     359,      330,     382,     331,       // BC to BF
+     256,     193,     194,     195,     196,      197,     198,     302,       // C4 to C7
+     268,     201,     280,     203,     278,      205,     206,     298,       // CC to CF
+     272,     325,     332,     310,     212,      213,     214,     215,       // D4 to D7
+     216,     370,     218,     219,     220,      360,     362,     223,       // DC to DF
+     257,     225,     226,     227,     228,      229,     230,     303,       // E4 to E7
+     269,     233,     281,     235,     279,      237,     238,     299,       // EC to EF
+     273,     326,     333,     311,     244,      245,     246,     247,       // F4 to F7
+     248,     371,     250,     251,     252,      361,     363,     729);      // FC to FF
+
+const
+  iso_8859_5_n: TTTFEncodingNames =
+    ('.notdef',   '.notdef',      '.notdef',    '.notdef',            // 00 to 03
+     '.notdef',   '.notdef',      '.notdef',    '.notdef',            // 04 to 07
+     '.notdef',   '.notdef',      '.notdef',    '.notdef',            // 08 to 0B
+     '.notdef',   '.notdef',      '.notdef',    '.notdef',            // 0C to 0F
+     '.notdef',   '.notdef',      '.notdef',    '.notdef',            // 10 to 13
+     '.notdef',   '.notdef',      '.notdef',    '.notdef',            // 14 to 17
+     '.notdef',   '.notdef',      '.notdef',    '.notdef',            // 18 to 1B
+     '.notdef',   '.notdef',      '.notdef',    '.notdef',            // 1C to 1F
+     'space',     'exclam',       'quotedbl',   'numbersign',         // 20 to 23
+     'dollar',    'percent',      'ampersand',  'quotesingle',        // 24 to 27
+     'parenleft', 'parenright',   'asterisk',   'plus',               // 28 to 2B
+     'comma',     'hyphen',       'period',     'slash',              // 2C to 2F
+     'zero',      'one',          'two',        'three',              // 30 to 33
+     'four',      'five',         'six',        'seven',              // 34 to 37
+     'eight',     'nine',         'colon',      'semicolon',          // 38 to 3B
+     'less',      'equal',        'greater',    'question',           // 3C to 3F
+     'at',        'A',            'B',          'C',                  // 40 to 43
+     'D',         'E',            'F',          'G',                  // 44 to 47
+     'H',         'I',            'J',          'K',                  // 48 to 4B
+     'L',         'M',            'N',          'O',                  // 4C to 4F
+     'P',         'Q',            'R',          'S',                  // 50 to 53
+     'T',         'U',            'V',          'W',                  // 54 to 57
+     'X',         'Y',            'Z',          'bracketleft',        // 58 to 5B
+     'backslash', 'bracketright', 'asciicircum','underscore',         // 5C to 5F
+     'grave',     'a',            'b',          'c',                  // 60 to 63
+     'd',         'e',            'f',          'g',                  // 64 to 67
+     'h',         'i',            'j',          'k',                  // 68 to 6B
+     'l',         'm',            'n',          'o',                  // 6C to 6F
+     'p',         'q',            'r',          's',                  // 70 to 73
+     't',         'u',            'v',          'w',                  // 74 to 77
+     'x',         'y',            'z',          'braceleft',          // 78 to 7B
+     'bar',       'braceright',   'asciitilde', '.notdef',            // 7C to 7F
+     '.notdef',   '.notdef',      '.notdef',    '.notdef',     // 80 to 83
+     '.notdef',   '.notdef',      '.notdef',    '.notdef',     // 84 to 87
+     '.notdef',   '.notdef',      '.notdef',    '.notdef',     // 88 to 8B
+     '.notdef',   '.notdef',      '.notdef',    '.notdef',     // 8C to 8F
+     '.notdef',   '.notdef',      '.notdef',    '.notdef',     // 90 to 93
+     '.notdef',   '.notdef',      '.notdef',    '.notdef',     // 94 to 97
+     '.notdef',   '.notdef',      '.notdef',    '.notdef',     // 98 to 9B
+     '.notdef',   '.notdef',      '.notdef',    '.notdef',     // 9C to 9F
+     'space',     'afii10023',    'afii10051',  'afii10052',     // A0 to A3
+     'afii10053', 'afii10054',    'afii10055',  'afii10056',     // A4 to A7
+     'afii10057', 'afii10058',    'afii10059',  'afii10060',     // A8 to AB
+     'afii10061', 'hyphen',       'afii10062',  'afii10145',     // AC to AF
+     'afii10017', 'afii10018',    'afii10019',  'afii10020',     // B0 to B3
+     'afii10021', 'afii10022',    'afii10024',  'afii10025',     // B4 to B7
+     'afii10026', 'afii10027',    'afii10028',  'afii10029',     // B8 to BB
+     'afii10030', 'afii10031',    'afii10032',  'afii10033',     // BC to BF
+     'afii10034', 'afii10035',    'afii10036',  'afii10037',     // C0 to C3
+     'afii10038', 'afii10039',    'afii10040',  'afii10041',     // C4 to C7
+     'afii10042', 'afii10043',    'afii10044',  'afii10045',     // C8 to CB
+     'afii10046', 'afii10047',    'afii10048',  'afii10049',     // CC to CF
+     'afii10065', 'afii10065',    'afii10067',  'afii10068',     // D0 to D3
+     'afii10069', 'afii10070',    'afii10072',  'afii10073',     // D4 to D7
+     'afii10074', 'afii10075',    'afii10076',  'afii10077',     // D8 to DB
+     'afii10078', 'afii10079',    'afii10080',  'afii10081',     // DC to DF
+     'afii10082', 'afii10083',    'afii10084',  'afii10085',     // E0 to E3
+     'afii10086', 'afii10087',    'afii10088',  'afii10089',     // E4 to E7
+     'afii10090', 'afii10091',    'afii10092',  'afii10093',     // E8 to EB
+     'afii10094', 'afii10095',    'afii10096',  'afii10097',     // EC to EF
+     'afii61352', 'afii10071',    'afii10099',  'afii10100',     // F0 to F3
+     'afii10101', 'afii10102',    'afii10103',  'afii10104',     // F4 to F7
+     'afii10105', 'afii10106',    'afii10107',  'afii10108',     // F8 to FB
+     'afii10109', 'section',      'afii10110',  'afii10193');    // FC to FF
+
+const
+  iso_8859_5_v: TTTFEncodingValues =
+    (0,       1,       2,       3,       4,        5,       6,       7,         // 00 to 07
+     8,       9,       10,      11,      12,       13,      14,      15,        // 08 to 0F
+     16,      17,      18,      19,      20,       21,      22,      23,        // 10 to 17
+     24,      25,      26,      27,      28,       29,      30,      31,        // 18 to 1F
+     32,      33,      34,      35,      36,       37,      38,      39,        // 20 to 27
+     40,      41,      42,      43,      44,       45,      46,      47,        // 28 to 2F
+     48,      49,      50,      51,      52,       53,      54,      55,        // 30 to 37
+     56,      57,      58,      59,      60,       61,      62,      63,        // 38 to 3F
+     64,      65,      66,      67,      68,       69,      70,      71,        // 40 to 47
+     72,      73,      74,      75,      76,       77,      78,      79,        // 48 to 4F
+     80,      81,      82,      83,      84,       85,      86,      87,        // 50 to 57
+     88,      89,      90,      91,      92,       93,      94,      95,        // 58 to 5F
+     96,      97,      98,      99,      100,      101,     102,     103,       // 60 to 67
+     104,     105,     106,     107,     108,      109,     110,     111,       // 68 to 6F
+     112,     113,     114,     115,     116,      117,     118,     119,       // 70 to 77
+     120,     121,     122,     123,     124,      125,     126,     127,       // 78 to 7F
+     -1,      -1,      -1,      -1,      -1,       -1,      -1,      -1,        // 80 to 87
+     -1,      -1,      -1,      -1,      -1,       -1,      -1,      -1,        // 88 to 8F
+     -1,      -1,      -1,      -1,      -1,       -1,      -1,      -1,        // 90 to 97
+     -1,      -1,      -1,      -1,      -1,       -1,      -1,      -1,        // 98 to 9F
+     160,     1025,    1026,    1027,    1028,     1029,    1030,    1031,      // A0 to A7
+     1032,    1033,    1034,    1035,    1036,     173,     1038,    1039,      // A8 to AF
+     1040,    1041,    1042,    1043,    1044,     1045,    1046,    1047,      // B0 to B7
+     1048,    1049,    1050,    1051,    1052,     1053,    1054,    1055,      // B8 to BF
+     1056,    1057,    1058,    1059,    1060,     1061,    1062,    1063,      // C0 to C7
+     1064,    1065,    1066,    1067,    1068,     1069,    1070,    1071,      // C8 to CF
+     1072,    1073,    1074,    1075,    1076,     1077,    1078,    1079,      // D0 to D7
+     1080,    1081,    1082,    1083,    1084,     1085,    1086,    1087,      // D8 to DF
+     1088,    1089,    1090,    1091,    1092,     1093,    1094,    1095,      // E0 to E7
+     1096,    1097,    1098,    1099,    1100,     1101,    1102,    1103,      // E8 to EF
+     8470,    1105,    1106,    1107,    1108,     1109,    1110,    1111,      // F0 to F7
+     1112,    1113,    1114,    1115,    1116,     167,     1118,    1119);     // F8 to FF
+
+const
+  iso_8859_7_n: TTTFEncodingNames =
+    ('.notdef',           '.notdef',      '.notdef',        '.notdef',                // 00 to 03
+     '.notdef',           '.notdef',      '.notdef',        '.notdef',                // 04 to 07
+     '.notdef',           '.notdef',      '.notdef',        '.notdef',                // 08 to 0B
+     '.notdef',           '.notdef',      '.notdef',        '.notdef',                // 0C to 0F
+     '.notdef',           '.notdef',      '.notdef',        '.notdef',                // 10 to 13
+     '.notdef',           '.notdef',      '.notdef',        '.notdef',                // 14 to 17
+     '.notdef',           '.notdef',      '.notdef',        '.notdef',                // 18 to 1B
+     '.notdef',           '.notdef',      '.notdef',        '.notdef',                // 1C to 1F
+     'space',             'exclam',       'quotedbl',       'numbersign',             // 20 to 23
+     'dollar',            'percent',      'ampersand',      'quotesingle',            // 24 to 27
+     'parenleft',         'parenright',   'asterisk',       'plus',                   // 28 to 2B
+     'comma',             'hyphen',       'period',         'slash',                  // 2C to 2F
+     'zero',              'one',          'two',            'three',                  // 30 to 33
+     'four',              'five',         'six',            'seven',                  // 34 to 37
+     'eight',             'nine',         'colon',          'semicolon',              // 38 to 3B
+     'less',              'equal',        'greater',        'question',               // 3C to 3F
+     'at',                'A',            'B',              'C',                      // 40 to 43
+     'D',                 'E',            'F',              'G',                      // 44 to 47
+     'H',                 'I',            'J',              'K',                      // 48 to 4B
+     'L',                 'M',            'N',              'O',                      // 4C to 4F
+     'P',                 'Q',            'R',              'S',                      // 50 to 53
+     'T',                 'U',            'V',              'W',                      // 54 to 57
+     'X',                 'Y',            'Z',              'bracketleft',            // 58 to 5B
+     'backslash',         'bracketright', 'asciicircum',    'underscore',             // 5C to 5F
+     'grave',             'a',            'b',              'c',                      // 60 to 63
+     'd',                 'e',            'f',              'g',                      // 64 to 67
+     'h',                 'i',            'j',              'k',                      // 68 to 6B
+     'l',                 'm',            'n',              'o',                      // 6C to 6F
+     'p',                 'q',            'r',              's',                      // 70 to 73
+     't',                 'u',            'v',              'w',                      // 74 to 77
+     'x',                 'y',            'z',              'braceleft',              // 78 to 7B
+     'bar',               'braceright',   'asciitilde',     '.notdef',                // 7C to 7F
+     '.notdef',           '.notdef',      '.notdef',        '.notdef',                // 80 to 83
+     '.notdef',           '.notdef',      '.notdef',        '.notdef',                // 84 to 87
+     '.notdef',           '.notdef',      '.notdef',        '.notdef',                // 88 to 8B
+     '.notdef',           '.notdef',      '.notdef',        '.notdef',                // 8C to 8F
+     '.notdef',           '.notdef',      '.notdef',        '.notdef',                // 90 to 93
+     '.notdef',           '.notdef',      '.notdef',        '.notdef',                // 94 to 97
+     '.notdef',           '.notdef',      '.notdef',        '.notdef',                // 98 to 9B
+     '.notdef',           '.notdef',      '.notdef',        '.notdef',                // 9C to 9F
+     'space',             'quoteleft',    'quoteright',     'sterling',               // A0 to A3
+     'brokenbar',         'section',      'dieresis',       'copyright',              // A4 to A7
+     'guillemotleft',     'logicalnot',   'hyphen',         'afii00208',              // A8 to AB
+     'degree',            'plusminus',    'twosuperior',    'threesuperior',          // AC to AF
+     'tonos',             'dieresistonos','Alphatonos',     'periodcentered',         // B0 to B3
+     'Epsilontonos',      'Etatonos',     'Iotatonos',      'guillemotright',         // B4 to B7
+     'Omicrontonos',      'onehalf',      'Upsilontonos',   'Omegatonos',             // B8 to BB
+     'iotadieresistonos', 'Alpha',        'Beta',           'Gamma',                  // BC to BF
+     'Delta',             'Epsilon',      'Zeta',           'Eta',                    // C0 to C3
+     'Theta',             'Iota',         'Kappa',          'Lambda',                 // C4 to C7
+     'Mu',                'Nu',           'Xi',             'Omicron',                // C8 to CB
+     'Pi',                'Rho',          'Sigma',          'Tau',                    // CC to CF
+     'Upsilon',           'Phi',          'Chi',            'Psi',                    // D0 to D3
+     'Omega',             'Iotadieresis', 'Upsilondieresis','alphatonos',             // D4 to D7
+     'epsilontonos',      'etatonos',     'iotatonos',      'upsilondieresistonos',   // D8 to DB
+     'alpha',             'beta',         'gamma',          'delta',                  // DC to DF
+     'epsilon',           'zeta',         'eta',            'theta',                  // E0 to E3
+     'iota',              'kappa',        'lambda',         'mu',                     // E4 to E7
+     'nu',                'xi',           'omicron',        'pi',                     // E8 to EB
+     'rho',               'sigma1',       'sigma',          'tau',                    // EC to EF
+     'upsilon',           'phi',          'chi',            'psi',                    // F0 to F3
+     'omega',             'iotadieresis', 'upsilondieresis','omicrontonos',           // F4 to F7
+     'upsilontonos',      'omegatonos',   '.notdef',        '.notdef',                // F8 to FB
+     '.notdef',           '.notdef',      '.notdef',        '.notdef');               // FC to FF
+
+const
+  iso_8859_7_v: TTTFEncodingValues =
+    (0,       1,       2,       3,       4,        5,       6,       7,         // 00 to 07
+     8,       9,       10,      11,      12,       13,      14,      15,        // 08 to 0F
+     16,      17,      18,      19,      20,       21,      22,      23,        // 10 to 17
+     24,      25,      26,      27,      28,       29,      30,      31,        // 18 to 1F
+     32,      33,      34,      35,      36,       37,      38,      39,        // 20 to 27
+     40,      41,      42,      43,      44,       45,      46,      47,        // 28 to 2F
+     48,      49,      50,      51,      52,       53,      54,      55,        // 30 to 37
+     56,      57,      58,      59,      60,       61,      62,      63,        // 38 to 3F
+     64,      65,      66,      67,      68,       69,      70,      71,        // 40 to 47
+     72,      73,      74,      75,      76,       77,      78,      79,        // 48 to 4F
+     80,      81,      82,      83,      84,       85,      86,      87,        // 50 to 57
+     88,      89,      90,      91,      92,       93,      94,      95,        // 58 to 5F
+     96,      97,      98,      99,      100,      101,     102,     103,       // 60 to 67
+     104,     105,     106,     107,     108,      109,     110,     111,       // 68 to 6F
+     112,     113,     114,     115,     116,      117,     118,     119,       // 70 to 77
+     120,     121,     122,     123,     124,      125,     126,     127,       // 78 to 7F
+     -1,      -1,      -1,      -1,      -1,       -1,      -1,      -1,        // 80 to 87
+     -1,      -1,      -1,      -1,      -1,       -1,      -1,      -1,        // 88 to 8F
+     -1,      -1,      -1,      -1,      -1,       -1,      -1,      -1,        // 90 to 97
+     -1,      -1,      -1,      -1,      -1,       -1,      -1,      -1,        // 98 to 9F
+     160,     8216,    8217,    163,     166,      167,     168,     169,       // A0 to A7
+     171,     172,     173,     8213,    176,      177,     178,     179,       // A8 to AF
+     900,     901,     902,     183,     904,      905,     906,     187,       // B0 to B7
+     908,     189,     910,     911,     912,      913,     914,     915,       // B8 to BF
+     916,     917,     918,     919,     920,      921,     922,     923,       // C0 to C7
+     924,     925,     926,     927,     928,      929,     931,     932,       // C8 to CF
+     933,     934,     935,     936,     937,      938,     939,     940,       // D0 to D7
+     941,     942,     943,     944,     945,      946,     947,     948,       // D8 to DF
+     949,     950,     951,     952,     953,      954,     955,     956,       // E0 to E7
+     957,     958,     959,     960,     961,      962,     963,     964,       // E8 to EF
+     965,     966,     967,     968,     969,      970,     971,     972,       // F0 to F7
+     973,     974,     -1,      -1,      -1,       -1,      -1,      -1);       // F8 to FF
+
+const
+  iso_8859_9_n: TTTFEncodingNames =
+    ('.notdef',     '.notdef',      '.notdef',      '.notdef',            // 00 to 03
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 04 to 07
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 08 to 0B
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 0C to 0F
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 10 to 13
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 14 to 17
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 18 to 1B
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 1C to 1F
+     'space',       'exclam',       'quotedbl',     'numbersign',         // 20 to 23
+     'dollar',      'percent',      'ampersand',    'quotesingle',        // 24 to 27
+     'parenleft',   'parenright',   'asterisk',     'plus',               // 28 to 2B
+     'comma',       'hyphen',       'period',       'slash',              // 2C to 2F
+     'zero',        'one',          'two',          'three',              // 30 to 33
+     'four',        'five',         'six',          'seven',              // 34 to 37
+     'eight',       'nine',         'colon',        'semicolon',          // 38 to 3B
+     'less',        'equal',        'greater',      'question',           // 3C to 3F
+     'at',          'A',            'B',            'C',                  // 40 to 43
+     'D',           'E',            'F',            'G',                  // 44 to 47
+     'H',           'I',            'J',            'K',                  // 48 to 4B
+     'L',           'M',            'N',            'O',                  // 4C to 4F
+     'P',           'Q',            'R',            'S',                  // 50 to 53
+     'T',           'U',            'V',            'W',                  // 54 to 57
+     'X',           'Y',            'Z',            'bracketleft',        // 58 to 5B
+     'backslash',   'bracketright', 'asciicircum',  'underscore',         // 5C to 5F
+     'grave',       'a',            'b',            'c',                  // 60 to 63
+     'd',           'e',            'f',            'g',                  // 64 to 67
+     'h',           'i',            'j',            'k',                  // 68 to 6B
+     'l',           'm',            'n',            'o',                  // 6C to 6F
+     'p',           'q',            'r',            's',                  // 70 to 73
+     't',           'u',            'v',            'w',                  // 74 to 77
+     'x',           'y',            'z',            'braceleft',          // 78 to 7B
+     'bar',         'braceright',   'asciitilde',   '.notdef',            // 7C to 7F
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 80 to 83
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 84 to 87
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 88 to 8B
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 8C to 8F
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 90 to 93
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 94 to 97
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 98 to 9B
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 9C to 9F
+     'space',       'exclamdown',   'cent',         'sterling',           // A0 to A3
+     'currency',    'yen',          'brokenbar',    'section',            // A4 to A7
+     'dieresis',    'copyright',    'ordfeminine',  'guillemotleft',      // A8 to AB
+     'logicalnot',  'hyphen',       'registered',   'macron',             // AC to AF
+     'degree',      'plusminus',    'twosuperior',  'threesuperior',      // B0 to B3
+     'acute',       'mu',           'paragraph',    'periodcentered',     // B4 to B7
+     'cedilla',     'onesuperior',  'ordmasculine', 'guillemotright',     // B8 to BB
+     'onequarter',  'onehalf',      'threequarters','questiondown',       // BC to BF
+     'Agrave',      'Aacute',       'Acircumflex',  'Atilde',             // C0 to C3
+     'Adieresis',   'Aring',        'AE',           'Ccedilla',           // C4 to C7
+     'Egrave',      'Eacute',       'Ecircumflex',  'Edieresis',          // C8 to CB
+     'Igrave',      'Iacute',       'Icircumflex',  'Idieresis',          // CC to CF
+     'Gbreve',      'Ntilde',       'Ograve',       'Oacute',             // D0 to D3
+     'Ocircumflex', 'Otilde',       'Odieresis',    'multiply',           // D4 to D7
+     'Oslash',      'Ugrave',       'Uacute',       'Ucircumflex',        // D8 to DB
+     'Udieresis',   'Idotaccent',   'Scedilla',     'germandbls',         // DC to DF
+     'agrave',      'aacute',       'acircumflex',  'atilde',             // E0 to E3
+     'adieresis',   'aring',        'ae',           'ccedilla',           // E4 to E7
+     'egrave',      'eacute',       'ecircumflex',  'edieresis',          // E8 to EB
+     'igrave',      'iacute',       'icircumflex',  'idieresis',          // EC to EF
+     'gbreve',      'ntilde',       'ograve',       'oacute',             // F0 to F3
+     'ocircumflex', 'otilde',       'odieresis',    'divide',             // F4 to F7
+     'oslash',      'ugrave',       'uacute',       'ucircumflex',        // F8 to FB
+     'udieresis',   'dotlessi',     'scedilla',     'ydieresis');         // FC to FF
+
+const
+  iso_8859_9_v: TTTFEncodingValues =
+    (0,       1,       2,       3,       4,        5,       6,       7,         // 00 to 07
+     8,       9,       10,      11,      12,       13,      14,      15,        // 08 to 0F
+     16,      17,      18,      19,      20,       21,      22,      23,        // 10 to 17
+     24,      25,      26,      27,      28,       29,      30,      31,        // 18 to 1F
+     32,      33,      34,      35,      36,       37,      38,      39,        // 20 to 27
+     40,      41,      42,      43,      44,       45,      46,      47,        // 28 to 2F
+     48,      49,      50,      51,      52,       53,      54,      55,        // 30 to 37
+     56,      57,      58,      59,      60,       61,      62,      63,        // 38 to 3F
+     64,      65,      66,      67,      68,       69,      70,      71,        // 40 to 47
+     72,      73,      74,      75,      76,       77,      78,      79,        // 48 to 4F
+     80,      81,      82,      83,      84,       85,      86,      87,        // 50 to 57
+     88,      89,      90,      91,      92,       93,      94,      95,        // 58 to 5F
+     96,      97,      98,      99,      100,      101,     102,     103,       // 60 to 67
+     104,     105,     106,     107,     108,      109,     110,     111,       // 68 to 6F
+     112,     113,     114,     115,     116,      117,     118,     119,       // 70 to 77
+     120,     121,     122,     123,     124,      125,     126,     127,       // 78 to 7F
+     -1,      -1,      -1,      -1,      -1,       -1,      -1,      -1,        // 80 to 87
+     -1,      -1,      -1,      -1,      -1,       -1,      -1,      -1,        // 88 to 8F
+     -1,      -1,      -1,      -1,      -1,       -1,      -1,      -1,        // 90 to 97
+     -1,      -1,      -1,      -1,      -1,       -1,      -1,      -1,        // 98 to 9F
+     160,     161,     162,     163,     164,      165,     166,     167,       // A0 to A7
+     168,     169,     170,     171,     172,      173,     174,     175,       // A8 to AF
+     176,     177,     178,     179,     180,      181,     182,     183,       // B0 to B7
+     184,     185,     186,     187,     188,      189,     190,     191,       // B8 to BF
+     192,     193,     194,     195,     196,      197,     198,     199,       // C0 to C7
+     200,     201,     202,     203,     204,      205,     206,     207,       // C8 to CF
+     286,     209,     210,     211,     212,      213,     214,     215,       // D0 to D7
+     216,     217,     218,     219,     220,      304,     350,     223,       // D8 to DF
+     224,     225,     226,     227,     228,      229,     230,     231,       // E0 to E7
+     232,     233,     234,     235,     236,      237,     238,     239,       // E8 to EF
+     287,     241,     242,     243,     244,      245,     246,     247,       // F0 to F7
+     248,     249,     250,     251,     252,      305,     351,     255);      // F8 to FF
+
+const
+  iso_8859_11_n: TTTFEncodingNames =
+    ('.notdef',           '.notdef',          '.notdef',        '.notdef',            // 00 to 03
+     '.notdef',           '.notdef',          '.notdef',        '.notdef',            // 04 to 07
+     '.notdef',           '.notdef',          '.notdef',        '.notdef',            // 08 to 0B
+     '.notdef',           '.notdef',          '.notdef',        '.notdef',            // 0C to 0F
+     '.notdef',           '.notdef',          '.notdef',        '.notdef',            // 10 to 13
+     '.notdef',           '.notdef',          '.notdef',        '.notdef',            // 14 to 17
+     '.notdef',           '.notdef',          '.notdef',        '.notdef',            // 18 to 1B
+     '.notdef',           '.notdef',          '.notdef',        '.notdef',            // 1C to 1F
+     'space',             'exclam',           'quotedbl',       'numbersign',         // 20 to 23
+     'dollar',            'percent',          'ampersand',      'quotesingle',        // 24 to 27
+     'parenleft',         'parenright',       'asterisk',       'plus',               // 28 to 2B
+     'comma',             'hyphen',           'period',         'slash',              // 2C to 2F
+     'zero',              'one',              'two',            'three',              // 30 to 33
+     'four',              'five',             'six',            'seven',              // 34 to 37
+     'eight',             'nine',             'colon',          'semicolon',          // 38 to 3B
+     'less',              'equal',            'greater',        'question',           // 3C to 3F
+     'at',                'A',                'B',              'C',                  // 40 to 43
+     'D',                 'E',                'F',              'G',                  // 44 to 47
+     'H',                 'I',                'J',              'K',                  // 48 to 4B
+     'L',                 'M',                'N',              'O',                  // 4C to 4F
+     'P',                 'Q',                'R',              'S',                  // 50 to 53
+     'T',                 'U',                'V',              'W',                  // 54 to 57
+     'X',                 'Y',                'Z',              'bracketleft',        // 58 to 5B
+     'backslash',         'bracketright',     'asciicircum',    'underscore',         // 5C to 5F
+     'grave',             'a',                'b',              'c',                  // 60 to 63
+     'd',                 'e',                'f',              'g',                  // 64 to 67
+     'h',                 'i',                'j',              'k',                  // 68 to 6B
+     'l',                 'm',                'n',              'o',                  // 6C to 6F
+     'p',                 'q',                'r',              's',                  // 70 to 73
+     't',                 'u',                'v',              'w',                  // 74 to 77
+     'x',                 'y',                'z',              'braceleft',          // 78 to 7B
+     'bar',               'braceright',       'asciitilde',     '.notdef',            // 7C to 7F
+     '.notdef',           '.notdef',          '.notdef',        '.notdef',            // 80 to 83
+     '.notdef',           '.notdef',          '.notdef',        '.notdef',            // 84 to 87
+     '.notdef',           '.notdef',          '.notdef',        '.notdef',            // 88 to 8B
+     '.notdef',           '.notdef',          '.notdef',        '.notdef',            // 8C to 8F
+     '.notdef',           '.notdef',          '.notdef',        '.notdef',            // 90 to 93
+     '.notdef',           '.notdef',          '.notdef',        '.notdef',            // 94 to 97
+     '.notdef',           '.notdef',          '.notdef',        '.notdef',            // 98 to 9B
+     '.notdef',           '.notdef',          '.notdef',        '.notdef',            // 9C to 9F
+     'space',             'kokaithai',        'khokhaithai',    'khokhuatthai',       // A0 to A3
+     'khokhwaithai',      'khokhonthai',      'khorakhangthai', 'ngonguthai',         // A4 to A7
+     'chochanthai',       'chochingthai',     'chochangthai',   'sosothai',           // A8 to AB
+     'chochoethai',       'yoyingthai',       'dochadathai',    'topatakthai',        // AC to AF
+     'thothanthai',       'thonangmonthothai','thophuthaothai', 'nonenthai',          // B0 to B3
+     'dodekthai',         'totaothai',        'thothungthai',   'thothahanthai',      // B4 to B7
+     'thothongthai',      'nonuthai',         'bobaimaithai',   'poplathai',          // B8 to BB
+     'phophungthai',      'fofathai',         'phophanthai',    'fofanthai',          // BC to BF
+     'phosamphaothai',    'momathai',         'yoyakthai',      'roruathai',          // C0 to C3
+     'ruthai',            'lolingthai',       'luthai',         'wowaenthai',         // C4 to C7
+     'sosalathai',        'sorusithai',       'sosuathai',      'hohipthai',          // C8 to CB
+     'lochulathai',       'oangthai',         'honokhukthai',   'paiyannoithai',      // CC to CF
+     'saraathai',         'maihanakatthai',   'saraaathai',     'saraamthai',         // D0 to D3
+     'saraithai',         'saraiithai',       'sarauethai',     'saraueethai',        // D4 to D7
+     'sarauthai',         'sarauuthai',       'phinthuthai',    '.notdef',            // D8 to DB
+     '.notdef',           '.notdef',          '.notdef',        'bahtthai',           // DC to DF
+     'saraethai',         'saraaethai',       'saraothai',      'saraaimaimuanthai',  // E0 to E3
+     'saraaimaimalaithai','lakkhangyaothai',  'maiyamokthai',   'maitaikhuthai',      // E4 to E7
+     'maiekthai',         'maithothai',       'maitrithai',     'maichattawathai',    // E8 to EB
+     'thanthakhatthai',   'nikhahitthai',     'yamakkanthai',   'fongmanthai',        // EC to EF
+     'zerothai',          'onethai',          'twothai',        'threethai',          // F0 to F3
+     'fourthai',          'fivethai',         'sixthai',        'seventhai',          // F4 to F7
+     'eightthai',         'ninethai',         'angkhankhuthai', 'khomutthai',         // F8 to FB
+     '.notdef',           '.notdef',          '.notdef',        '.notdef');           // FC to FF
+
+const
+  iso_8859_11_v: TTTFEncodingValues =
+    (0,       1,       2,       3,       4,        5,       6,       7,         // 00 to 07
+     8,       9,       10,      11,      12,       13,      14,      15,        // 08 to 0F
+     16,      17,      18,      19,      20,       21,      22,      23,        // 10 to 17
+     24,      25,      26,      27,      28,       29,      30,      31,        // 18 to 1F
+     32,      33,      34,      35,      36,       37,      38,      39,        // 20 to 27
+     40,      41,      42,      43,      44,       45,      46,      47,        // 28 to 2F
+     48,      49,      50,      51,      52,       53,      54,      55,        // 30 to 37
+     56,      57,      58,      59,      60,       61,      62,      63,        // 38 to 3F
+     64,      65,      66,      67,      68,       69,      70,      71,        // 40 to 47
+     72,      73,      74,      75,      76,       77,      78,      79,        // 48 to 4F
+     80,      81,      82,      83,      84,       85,      86,      87,        // 50 to 57
+     88,      89,      90,      91,      92,       93,      94,      95,        // 58 to 5F
+     96,      97,      98,      99,      100,      101,     102,     103,       // 60 to 67
+     104,     105,     106,     107,     108,      109,     110,     111,       // 68 to 6F
+     112,     113,     114,     115,     116,      117,     118,     119,       // 70 to 77
+     120,     121,     122,     123,     124,      125,     126,     127,       // 78 to 7F
+     -1,      -1,      -1,      -1,      -1,       -1,      -1,      -1,        // 80 to 87
+     -1,      -1,      -1,      -1,      -1,       -1,      -1,      -1,        // 88 to 8F
+     -1,      -1,      -1,      -1,      -1,       -1,      -1,      -1,        // 90 to 97
+     -1,      -1,      -1,      -1,      -1,       -1,      -1,      -1,        // 98 to 9F
+     160,     3585,    3586,    3587,    3588,     3589,    3590,    3591,      // A0 to A7
+     3592,    3593,    3594,    3595,    3596,     3597,    3598,    3599,      // A8 to AF
+     3600,    3601,    3602,    3603,    3604,     3605,    3606,    3607,      // B0 to B7
+     3608,    3609,    3610,    3611,    3612,     3613,    3614,    3615,      // B8 to BF
+     3616,    3617,    3618,    3619,    3620,     3621,    3622,    3623,      // C0 to C7
+     3624,    3625,    3626,    3627,    3628,     3629,    3630,    3631,      // C8 to CF
+     3632,    3633,    3634,    3635,    3636,     3637,    3638,    3639,      // D0 to D7
+     3640,    3641,    3642,    -1,      -1,       -1,      -1,      3647,      // D8 to DF
+     3648,    3649,    3650,    3651,    3652,     3653,    3654,    3655,      // E0 to E7
+     3656,    3657,    3658,    3659,    3660,     3661,    3662,    3663,      // E8 to EF
+     3664,    3665,    3666,    3667,    3668,     3669,    3670,    3671,      // F0 to F7
+     3672,    3673,    3674,    3675,    -1,       -1,      -1,      -1);       // F8 to FF
+
+const
+  iso_8859_15_n: TTTFEncodingNames =
+    ('.notdef',     '.notdef',      '.notdef',      '.notdef',            // 00 to 03
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 04 to 07
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 08 to 0B
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 0C to 0F
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 10 to 13
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 14 to 17
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 18 to 1B
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 1C to 1F
+     'space',       'exclam',       'quotedbl',     'numbersign',         // 20 to 23
+     'dollar',      'percent',      'ampersand',    'quotesingle',        // 24 to 27
+     'parenleft',   'parenright',   'asterisk',     'plus',               // 28 to 2B
+     'comma',       'hyphen',       'period',       'slash',              // 2C to 2F
+     'zero',        'one',          'two',          'three',              // 30 to 33
+     'four',        'five',         'six',          'seven',              // 34 to 37
+     'eight',       'nine',         'colon',        'semicolon',          // 38 to 3B
+     'less',        'equal',        'greater',      'question',           // 3C to 3F
+     'at',          'A',            'B',            'C',                  // 40 to 43
+     'D',           'E',            'F',            'G',                  // 44 to 47
+     'H',           'I',            'J',            'K',                  // 48 to 4B
+     'L',           'M',            'N',            'O',                  // 4C to 4F
+     'P',           'Q',            'R',            'S',                  // 50 to 53
+     'T',           'U',            'V',            'W',                  // 54 to 57
+     'X',           'Y',            'Z',            'bracketleft',        // 58 to 5B
+     'backslash',   'bracketright', 'asciicircum',  'underscore',         // 5C to 5F
+     'grave',       'a',            'b',            'c',                  // 60 to 63
+     'd',           'e',            'f',            'g',                  // 64 to 67
+     'h',           'i',            'j',            'k',                  // 68 to 6B
+     'l',           'm',            'n',            'o',                  // 6C to 6F
+     'p',           'q',            'r',            's',                  // 70 to 73
+     't',           'u',            'v',            'w',                  // 74 to 77
+     'x',           'y',            'z',            'braceleft',          // 78 to 7B
+     'bar',         'braceright',   'asciitilde',   '.notdef',            // 7C to 7F
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 80 to 83
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 84 to 87
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 88 to 8B
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 8C to 8F
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 90 to 93
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 94 to 97
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 98 to 9B
+     '.notdef',     '.notdef',      '.notdef',      '.notdef',            // 9C to 9F
+     'space',       'exclamdown',   'cent',         'sterling',           // A0 to A3
+     'Euro',        'yen',          'Scaron',       'section',            // A4 to A7
+     'scaron',      'copyright',    'ordfeminine',  'guillemotleft',      // A8 to AB
+     'logicalnot',  'hyphen',       'registered',   'macron',             // AC to AF
+     'degree',      'plusminus',    'twosuperior',  'threesuperior',      // B0 to B3
+     'Zcaron',      'mu',           'paragraph',    'periodcentered',     // B4 to B7
+     'zcaron',      'onesuperior',  'ordmasculine', 'guillemotright',     // B8 to BB
+     'OE',          'oe',           'Ydieresis',    'questiondown',       // BC to BF
+     'Agrave',      'Aacute',       'Acircumflex',  'Atilde',             // C0 to C3
+     'Adieresis',   'Aring',        'AE',           'Ccedilla',           // C4 to C7
+     'Egrave',      'Eacute',       'Ecircumflex',  'Edieresis',          // C8 to CB
+     'Igrave',      'Iacute',       'Icircumflex',  'Idieresis',          // CC to CF
+     'Eth',         'Ntilde',       'Ograve',       'Oacute',             // D0 to D3
+     'Ocircumflex', 'Otilde',       'Odieresis',    'multiply',           // D4 to D7
+     'Oslash',      'Ugrave',       'Uacute',       'Ucircumflex',        // D8 to DB
+     'Udieresis',   'Yacute',       'Thorn',        'germandbls',         // DC to DF
+     'agrave',      'aacute',       'acircumflex',  'atilde',             // E0 to E3
+     'adieresis',   'aring',        'ae',           'ccedilla',           // E4 to E7
+     'egrave',      'eacute',       'ecircumflex',  'edieresis',          // E8 to EB
+     'igrave',      'iacute',       'icircumflex',  'idieresis',          // EC to EF
+     'eth',         'ntilde',       'ograve',       'oacute',             // F0 to F3
+     'ocircumflex', 'otilde',       'odieresis',    'divide',             // F4 to F7
+     'oslash',      'ugrave',       'uacute',       'ucircumflex',        // F8 to FB
+     'udieresis',   'yacute',       'thorn',        'ydieresis');         // FC to FF
+
+const
+  iso_8859_15_v: TTTFEncodingValues =
+    (0,       1,       2,       3,       4,        5,       6,       7,         // 00 to 07
+     8,       9,       10,      11,      12,       13,      14,      15,        // 08 to 0F
+     16,      17,      18,      19,      20,       21,      22,      23,        // 10 to 17
+     24,      25,      26,      27,      28,       29,      30,      31,        // 18 to 1F
+     32,      33,      34,      35,      36,       37,      38,      39,        // 20 to 27
+     40,      41,      42,      43,      44,       45,      46,      47,        // 28 to 2F
+     48,      49,      50,      51,      52,       53,      54,      55,        // 30 to 37
+     56,      57,      58,      59,      60,       61,      62,      63,        // 38 to 3F
+     64,      65,      66,      67,      68,       69,      70,      71,        // 40 to 47
+     72,      73,      74,      75,      76,       77,      78,      79,        // 48 to 4F
+     80,      81,      82,      83,      84,       85,      86,      87,        // 50 to 57
+     88,      89,      90,      91,      92,       93,      94,      95,        // 58 to 5F
+     96,      97,      98,      99,      100,      101,     102,     103,       // 60 to 67
+     104,     105,     106,     107,     108,      109,     110,     111,       // 68 to 6F
+     112,     113,     114,     115,     116,      117,     118,     119,       // 70 to 77
+     120,     121,     122,     123,     124,      125,     126,     127,       // 78 to 7F
+     -1,      -1,      -1,      -1,      -1,       -1,      -1,      -1,        // 80 to 87
+     -1,      -1,      -1,      -1,      -1,       -1,      -1,      -1,        // 88 to 8F
+     -1,      -1,      -1,      -1,      -1,       -1,      -1,      -1,        // 90 to 97
+     -1,      -1,      -1,      -1,      -1,       -1,      -1,      -1,        // 98 to 9F
+     160,     161,     162,     163,     8364,     165,     352,     167,       // A0 to A7
+     353,     169,     170,     171,     172,      173,     174,     175,       // A8 to AF
+     176,     177,     178,     179,     381,      181,     182,     183,       // B0 to B7
+     382,     185,     186,     187,     338,      339,     376,     191,       // B8 to BF
+     192,     193,     194,     195,     196,      197,     198,     199,       // C0 to C7
+     200,     201,     202,     203,     204,      205,     206,     207,       // C8 to CF
+     208,     209,     210,     211,     212,      213,     214,     215,       // D0 to D7
+     216,     217,     218,     219,     220,      221,     222,     223,       // D8 to DF
+     224,     225,     226,     227,     228,      229,     230,     231,       // E0 to E7
+     232,     233,     234,     235,     236,      237,     238,     239,       // E8 to EF
+     240,     241,     242,     243,     244,      245,     246,     247,       // F0 to F7
+     248,     249,     250,     251,     252,      253,     254,     255);      // F8 to FF
+
+const
+  iso_8859_16_n: TTTFEncodingNames =
+    ('.notdef',       '.notdef',      '.notdef',      '.notdef',            // 00 to 03
+     '.notdef',       '.notdef',      '.notdef',      '.notdef',            // 04 to 07
+     '.notdef',       '.notdef',      '.notdef',      '.notdef',            // 08 to 0B
+     '.notdef',       '.notdef',      '.notdef',      '.notdef',            // 0C to 0F
+     '.notdef',       '.notdef',      '.notdef',      '.notdef',            // 10 to 13
+     '.notdef',       '.notdef',      '.notdef',      '.notdef',            // 14 to 17
+     '.notdef',       '.notdef',      '.notdef',      '.notdef',            // 18 to 1B
+     '.notdef',       '.notdef',      '.notdef',      '.notdef',            // 1C to 1F
+     'space',         'exclam',       'quotedbl',     'numbersign',         // 20 to 23
+     'dollar',        'percent',      'ampersand',    'quotesingle',        // 24 to 27
+     'parenleft',     'parenright',   'asterisk',     'plus',               // 28 to 2B
+     'comma',         'hyphen',       'period',       'slash',              // 2C to 2F
+     'zero',          'one',          'two',          'three',              // 30 to 33
+     'four',          'five',         'six',          'seven',              // 34 to 37
+     'eight',         'nine',         'colon',        'semicolon',          // 38 to 3B
+     'less',          'equal',        'greater',      'question',           // 3C to 3F
+     'at',            'A',            'B',            'C',                  // 40 to 43
+     'D',             'E',            'F',            'G',                  // 44 to 47
+     'H',             'I',            'J',            'K',                  // 48 to 4B
+     'L',             'M',            'N',            'O',                  // 4C to 4F
+     'P',             'Q',            'R',            'S',                  // 50 to 53
+     'T',             'U',            'V',            'W',                  // 54 to 57
+     'X',             'Y',            'Z',            'bracketleft',        // 58 to 5B
+     'backslash',     'bracketright', 'asciicircum',  'underscore',         // 5C to 5F
+     'grave',         'a',            'b',            'c',                  // 60 to 63
+     'd',             'e',            'f',            'g',                  // 64 to 67
+     'h',             'i',            'j',            'k',                  // 68 to 6B
+     'l',             'm',            'n',            'o',                  // 6C to 6F
+     'p',             'q',            'r',            's',                  // 70 to 73
+     't',             'u',            'v',            'w',                  // 74 to 77
+     'x',             'y',            'z',            'braceleft',          // 78 to 7B
+     'bar',           'braceright',   'asciitilde',   '.notdef',            // 7C to 7F
+     '.notdef',       '.notdef',      '.notdef',      '.notdef',            // 80 to 83
+     '.notdef',       '.notdef',      '.notdef',      '.notdef',            // 84 to 87
+     '.notdef',       '.notdef',      '.notdef',      '.notdef',            // 88 to 8B
+     '.notdef',       '.notdef',      '.notdef',      '.notdef',            // 8C to 8F
+     '.notdef',       '.notdef',      '.notdef',      '.notdef',            // 90 to 93
+     '.notdef',       '.notdef',      '.notdef',      '.notdef',            // 94 to 97
+     '.notdef',       '.notdef',      '.notdef',      '.notdef',            // 98 to 9B
+     '.notdef',       '.notdef',      '.notdef',      '.notdef',            // 9C to 9F
+     'space',         'Aogonek',      'aogonek',      'Lslash',             // A0 to A3
+     'Euro',          'quotedblbase', 'Scaron',       'section',            // A4 to A7
+     'scaron',        'copyright',    'Scommaaccent', 'guillemotleft',      // A8 to AB
+     'Zacute',        'hyphen',       'zacute',       'Zdotaccent',         // AC to AF
+     'degree',        'plusminus',    'Ccaron',       'lslash',             // B0 to B3
+     'Zcaron',        'quotedblright','paragraph',    'periodcentered',     // B4 to B7
+     'zcaron',        'ccaron',       'scommaaccent', 'guillemotright',     // B8 to BB
+     'OE',            'oe',           'Ydieresis',    'zdotaccent',         // BC to BF
+     'Agrave',        'Aacute',       'Acircumflex',  'Abreve',             // C0 to C3
+     'Adieresis',     'Cacute',       'AE',           'Ccedilla',           // C4 to C7
+     'Egrave',        'Eacute',       'Ecircumflex',  'Edieresis',          // C8 to CB
+     'Igrave',        'Iacute',       'Icircumflex',  'Idieresis',          // CC to CF
+     'Dcroat',        'Nacute',       'Ograve',       'Oacute',             // D0 to D3
+     'Ocircumflex',   'Ohungarumlaut','Odieresis',    'Sacute',             // D4 to D7
+     'Uhungarumlaut', 'Ugrave',       'Uacute',       'Ucircumflex',        // D8 to DB
+     'Udieresis',     'Eogonek',      'Tcommaaccent', 'germandbls',         // DC to DF
+     'agrave',        'aacute',       'acircumflex',  'abreve',             // E0 to E3
+     'adieresis',     'cacute',       'ae',           'ccedilla',           // E4 to E7
+     'egrave',        'eacute',       'ecircumflex',  'edieresis',          // E8 to EB
+     'igrave',        'iacute',       'icircumflex',  'idieresis',          // EC to EF
+     'dcroat',        'nacute',       'ograve',       'oacute',             // F0 to F3
+     'ocircumflex',   'ohungarumlaut','odieresis',    'sacute',             // F4 to F7
+     'uhungarumlaut', 'ugrave',       'uacute',       'ucircumflex',        // F8 to FB
+     'udieresis',     'eogonek',      'tcommaaccent', 'ydieresis');         // FC to FF
+
+const
+  iso_8859_16_v: TTTFEncodingValues =
+    (0,       1,       2,       3,       4,        5,       6,       7,         // 00 to 07
+     8,       9,       10,      11,      12,       13,      14,      15,        // 08 to 0F
+     16,      17,      18,      19,      20,       21,      22,      23,        // 10 to 17
+     24,      25,      26,      27,      28,       29,      30,      31,        // 18 to 1F
+     32,      33,      34,      35,      36,       37,      38,      39,        // 20 to 27
+     40,      41,      42,      43,      44,       45,      46,      47,        // 28 to 2F
+     48,      49,      50,      51,      52,       53,      54,      55,        // 30 to 37
+     56,      57,      58,      59,      60,       61,      62,      63,        // 38 to 3F
+     64,      65,      66,      67,      68,       69,      70,      71,        // 40 to 47
+     72,      73,      74,      75,      76,       77,      78,      79,        // 48 to 4F
+     80,      81,      82,      83,      84,       85,      86,      87,        // 50 to 57
+     88,      89,      90,      91,      92,       93,      94,      95,        // 58 to 5F
+     96,      97,      98,      99,      100,      101,     102,     103,       // 60 to 67
+     104,     105,     106,     107,     108,      109,     110,     111,       // 68 to 6F
+     112,     113,     114,     115,     116,      117,     118,     119,       // 70 to 77
+     120,     121,     122,     123,     124,      125,     126,     127,       // 78 to 7F
+     -1,      -1,      -1,      -1,      -1,       -1,      -1,      -1,        // 80 to 87
+     -1,      -1,      -1,      -1,      -1,       -1,      -1,      -1,        // 88 to 8F
+     -1,      -1,      -1,      -1,      -1,       -1,      -1,      -1,        // 90 to 97
+     -1,      -1,      -1,      -1,      -1,       -1,      -1,      -1,        // 98 to 9F
+     160,     260,     261,     321,     8364,     8222,    352,     167,       // A0 to A7
+     353,     169,     536,     171,     377,      173,     378,     379,       // A8 to AF
+     176,     177,     268,     322,     381,      8221,    182,     183,       // B0 to B7
+     382,     269,     537,     187,     338,      339,     376,     380,       // B8 to BF
+     192,     193,     194,     258,     196,      262,     198,     199,       // C0 to C7
+     200,     201,     202,     203,     204,      205,     206,     207,       // C8 to CF
+     272,     323,     210,     211,     212,      336,     214,     346,       // D0 to D7
+     368,     217,     218,     219,     220,      280,     538,     223,       // D8 to DF
+     224,     225,     226,     259,     228,      263,     230,     231,       // E0 to E7
+     232,     233,     234,     235,     236,      237,     238,     239,       // E8 to EF
+     273,     324,     242,     243,     244,      337,     246,     347,       // F0 to F7
+     369,     249,     250,     251,     252,      281,     539,     255);      // F8 to FF
+
+const
+  koi8_r_n: TTTFEncodingNames =
+    ('.notdef',   '.notdef',        '.notdef',        '.notdef',            // 00 to 03
+     '.notdef',   '.notdef',        '.notdef',        '.notdef',            // 04 to 07
+     '.notdef',   '.notdef',        '.notdef',        '.notdef',            // 08 to 0B
+     '.notdef',   '.notdef',        '.notdef',        '.notdef',            // 0C to 0F
+     '.notdef',   '.notdef',        '.notdef',        '.notdef',            // 10 to 13
+     '.notdef',   '.notdef',        '.notdef',        '.notdef',            // 14 to 17
+     '.notdef',   '.notdef',        '.notdef',        '.notdef',            // 18 to 1B
+     '.notdef',   '.notdef',        '.notdef',        '.notdef',            // 1C to 1F
+     'space',     'exclam',         'quotedbl',       'numbersign',         // 20 to 23
+     'dollar',    'percent',        'ampersand',      'quotesingle',        // 24 to 27
+     'parenleft', 'parenright',     'asterisk',       'plus',               // 28 to 2B
+     'comma',     'hyphen',         'period',         'slash',              // 2C to 2F
+     'zero',      'one',            'two',            'three',              // 30 to 33
+     'four',      'five',           'six',            'seven',              // 34 to 37
+     'eight',     'nine',           'colon',          'semicolon',          // 38 to 3B
+     'less',      'equal',          'greater',        'question',           // 3C to 3F
+     'at',        'A',              'B',              'C',                  // 40 to 43
+     'D',         'E',              'F',              'G',                  // 44 to 47
+     'H',         'I',              'J',              'K',                  // 48 to 4B
+     'L',         'M',              'N',              'O',                  // 4C to 4F
+     'P',         'Q',              'R',              'S',                  // 50 to 53
+     'T',         'U',              'V',              'W',                  // 54 to 57
+     'X',         'Y',              'Z',              'bracketleft',        // 58 to 5B
+     'backslash', 'bracketright',   'asciicircum',    'underscore',         // 5C to 5F
+     'grave',     'a',              'b',              'c',                  // 60 to 63
+     'd',         'e',              'f',              'g',                  // 64 to 67
+     'h',         'i',              'j',              'k',                  // 68 to 6B
+     'l',         'm',              'n',              'o',                  // 6C to 6F
+     'p',         'q',              'r',              's',                  // 70 to 73
+     't',         'u',              'v',              'w',                  // 74 to 77
+     'x',         'y',              'z',              'braceleft',          // 78 to 7B
+     'bar',       'braceright',     'asciitilde',     '.notdef',            // 7C to 7F
+     'SF100000',  'SF110000',       'SF010000',       'SF030000',           // 80 to 83
+     'SF020000',  'SF040000',       'SF080000',       'SF090000',           // 84 to 87
+     'SF060000',  'SF070000',       'SF050000',       'upblock',            // 88 to 8B
+     'dnblock',   'block',          'lfblock',        'rtblock',            // 8C to 8F
+     'ltshade',   'shade',          'dkshade',        'integraltp',         // 90 to 93
+     'filledbox', 'periodcentered', 'radical',        'approxequal',        // 94 to 97
+     'lessequal', 'greaterequal',   'space',          'integralbt',         // 98 to 9B
+     'degree',    'twosuperior',    'periodcentered', 'divide',             // 9C to 9F
+     'SF430000',  'SF240000',       'SF510000',       'afii10071',          // A0 to A3
+     'SF520000',  'SF390000',       'SF220000',       'SF210000',           // A4 to A7
+     'SF250000',  'SF500000',       'SF490000',       'SF380000',           // A8 to AB
+     'SF280000',  'SF270000',       'SF260000',       'SF360000',           // AC to AF
+     'SF370000',  'SF420000',       'SF190000',       'afii10023',          // B0 to B3
+     'SF200000',  'SF230000',       'SF470000',       'SF480000',           // B4 to B7
+     'SF410000',  'SF450000',       'SF460000',       'SF400000',           // B8 to BB
+     'SF540000',  'SF530000',       'SF440000',       'copyright',          // BC to BF
+     'afii10096', 'afii10065',      'afii10066',      'afii10088',          // C0 to C3
+     'afii10069', 'afii10070',      'afii10086',      'afii10068',          // C4 to C7
+     'afii10087', 'afii10074',      'afii10075',      'afii10076',          // C8 to CB
+     'afii10077', 'afii10078',      'afii10079',      'afii10080',          // CC to CF
+     'afii10081', 'afii10097',      'afii10082',      'afii10083',          // D0 to D3
+     'afii10084', 'afii10085',      'afii10072',      'afii10067',          // D4 to D7
+     'afii10094', 'afii10093',      'afii10073',      'afii10090',          // D8 to DB
+     'afii10095', 'afii10091',      'afii10089',      'afii10092',          // DC to DF
+     'afii10048', 'afii10017',      'afii10018',      'afii10040',          // E0 to E3
+     'afii10021', 'afii10022',      'afii10038',      'afii10020',          // E4 to E7
+     'afii10039', 'afii10026',      'afii10027',      'afii10028',          // E8 to EB
+     'afii10029', 'afii10030',      'afii10031',      'afii10032',          // EC to EF
+     'afii10033', 'afii10049',      'afii10034',      'afii10035',          // F0 to F3
+     'afii10036', 'afii10037',      'afii10024',      'afii10019',          // F4 to F7
+     'afii10046', 'afii10045',      'afii10025',      'afii10042',          // F8 to FB
+     'afii10047', 'afii10043',      'afii10041',      'afii10044');         // FC to FF
+
+const
+  koi8_r_v: TTTFEncodingValues =
+    (0,       1,       2,       3,       4,        5,       6,       7,         // 00 to 07
+     8,       9,       10,      11,      12,       13,      14,      15,        // 08 to 0F
+     16,      17,      18,      19,      20,       21,      22,      23,        // 10 to 17
+     24,      25,      26,      27,      28,       29,      30,      31,        // 18 to 1F
+     32,      33,      34,      35,      36,       37,      38,      39,        // 20 to 27
+     40,      41,      42,      43,      44,       45,      46,      47,        // 28 to 2F
+     48,      49,      50,      51,      52,       53,      54,      55,        // 30 to 37
+     56,      57,      58,      59,      60,       61,      62,      63,        // 38 to 3F
+     64,      65,      66,      67,      68,       69,      70,      71,        // 40 to 47
+     72,      73,      74,      75,      76,       77,      78,      79,        // 48 to 4F
+     80,      81,      82,      83,      84,       85,      86,      87,        // 50 to 57
+     88,      89,      90,      91,      92,       93,      94,      95,        // 58 to 5F
+     96,      97,      98,      99,      100,      101,     102,     103,       // 60 to 67
+     104,     105,     106,     107,     108,      109,     110,     111,       // 68 to 6F
+     112,     113,     114,     115,     116,      117,     118,     119,       // 70 to 77
+     120,     121,     122,     123,     124,      125,     126,     127,       // 78 to 7F
+     9472,    9474,    9484,    9488,    9492,     9496,    9500,    9508,      // 80 to 87
+     9516,    9524,    9532,    9600,    9604,     9608,    9612,    9616,      // 88 to 8F
+     9617,    9618,    9619,    8992,    9632,     8729,    8730,    8776,      // 90 to 97
+     8804,    8805,    160,     8993,    176,      178,     183,     247,       // 98 to 9F
+     9552,    9553,    9554,    1105,    9555,     9556,    9557,    9558,      // A0 to A7
+     9559,    9560,    9561,    9562,    9563,     9564,    9565,    9566,      // A8 to AF
+     9567,    9568,    9569,    1025,    9570,     9571,    9572,    9573,      // B0 to B7
+     9574,    9575,    9576,    9577,    9578,     9579,    9580,    169,       // B8 to BF
+     1102,    1072,    1073,    1094,    1076,     1077,    1092,    1075,      // C0 to C7
+     1093,    1080,    1081,    1082,    1083,     1084,    1085,    1086,      // C8 to CF
+     1087,    1103,    1088,    1089,    1090,     1091,    1078,    1074,      // D0 to D7
+     100,     1099,    1079,    1096,    1101,     1097,    1095,    1098,      // D8 to DF
+     1070,    1040,    1041,    1062,    1044,     1045,    1060,    1043,      // E0 to E7
+     1061,    1048,    1049,    1050,    1051,     1052,    1053,    1054,      // E8 to EF
+     1055,    1071,    1056,    1057,    1058,     1059,    1046,    1042,      // F0 to F7
+     1068,    1067,    1047,    1064,    1069,     1065,    1063,    1066);     // F8 to FF
+
+const
+  koi8_u_n: TTTFEncodingNames =
+    ('.notdef',   '.notdef',      '.notdef',        '.notdef',            // 00 to 03
+     '.notdef',   '.notdef',      '.notdef',        '.notdef',            // 04 to 07
+     '.notdef',   '.notdef',      '.notdef',        '.notdef',            // 08 to 0B
+     '.notdef',   '.notdef',      '.notdef',        '.notdef',            // 0C to 0F
+     '.notdef',   '.notdef',      '.notdef',        '.notdef',            // 10 to 13
+     '.notdef',   '.notdef',      '.notdef',        '.notdef',            // 14 to 17
+     '.notdef',   '.notdef',      '.notdef',        '.notdef',            // 18 to 1B
+     '.notdef',   '.notdef',      '.notdef',        '.notdef',            // 1C to 1F
+     'space',     'exclam',       'quotedbl',       'numbersign',         // 20 to 23
+     'dollar',    'percent',      'ampersand',      'quotesingle',        // 24 to 27
+     'parenleft', 'parenright',   'asterisk',       'plus',               // 28 to 2B
+     'comma',     'hyphen',       'period',         'slash',              // 2C to 2F
+     'zero',      'one',          'two',            'three',              // 30 to 33
+     'four',      'five',         'six',            'seven',              // 34 to 37
+     'eight',     'nine',         'colon',          'semicolon',          // 38 to 3B
+     'less',      'equal',        'greater',        'question',           // 3C to 3F
+     'at',        'A',            'B',              'C',                  // 40 to 43
+     'D',         'E',            'F',              'G',                  // 44 to 47
+     'H',         'I',            'J',              'K',                  // 48 to 4B
+     'L',         'M',            'N',              'O',                  // 4C to 4F
+     'P',         'Q',            'R',              'S',                  // 50 to 53
+     'T',         'U',            'V',              'W',                  // 54 to 57
+     'X',         'Y',            'Z',              'bracketleft',        // 58 to 5B
+     'backslash', 'bracketright', 'asciicircum',    'underscore',         // 5C to 5F
+     'grave',     'a',            'b',              'c',                  // 60 to 63
+     'd',         'e',            'f',              'g',                  // 64 to 67
+     'h',         'i',            'j',              'k',                  // 68 to 6B
+     'l',         'm',            'n',              'o',                  // 6C to 6F
+     'p',         'q',            'r',              's',                  // 70 to 73
+     't',         'u',            'v',              'w',                  // 74 to 77
+     'x',         'y',            'z',              'braceleft',          // 78 to 7B
+     'bar',       'braceright',   'asciitilde',     '.notdef',            // 7C to 7F
+     'SF100000',  'SF110000',     'SF010000',       'SF030000',           // 80 to 83
+     'SF020000',  'SF040000',     'SF080000',       'SF090000',           // 84 to 87
+     'SF060000',  'SF070000',     'SF050000',       'upblock',            // 88 to 8B
+     'dnblock',   'block',        'lfblock',        'rtblock',            // 8C to 8F
+     'ltshade',   'shade',        'dkshade',        'integraltp',         // 90 to 93
+     'filledbox', 'bullet',       'radical',        'approxequal',        // 94 to 97
+     'lessequal', 'greaterequal', 'space',          'integralbt',         // 98 to 9B
+     'degree',    'twosuperior',  'periodcentered', 'divide',             // 9C to 9F
+     'SF430000',  'SF240000',     'SF510000',       'afii10071',          // A0 to A3
+     'afii10101', 'SF390000',     'afii10103',      'afii10104',          // A4 to A7
+     'SF250000',  'SF500000',     'SF490000',       'SF380000',           // A8 to AB
+     'SF280000',  'afii10098',    'SF260000',       'SF360000',           // AC to AF
+     'SF370000',  'SF420000',     'SF190000',       'afii10023',          // B0 to B3
+     'afii10053', 'SF230000',     'afii10055',      'afii10056',          // B4 to B7
+     'SF410000',  'SF450000',     'SF460000',       'SF400000',           // B8 to BB
+     'SF540000',  'afii10050',    'SF440000',       'copyright',          // BC to BF
+     'afii10096', 'afii10065',    'afii10066',      'afii10088',          // C0 to C3
+     'afii10069', 'afii10070',    'afii10086',      'afii10068',          // C4 to C7
+     'afii10087', 'afii10074',    'afii10075',      'afii10076',          // C8 to CB
+     'afii10077', 'afii10078',    'afii10079',      'afii10080',          // CC to CF
+     'afii10081', 'afii10097',    'afii10082',      'afii10083',          // D0 to D3
+     'afii10084', 'afii10085',    'afii10072',      'afii10067',          // D4 to D7
+     'afii10094', 'afii10093',    'afii10073',      'afii10090',          // D8 to DB
+     'afii10095', 'afii10091',    'afii10089',      'afii10092',          // DC to DF
+     'afii10048', 'afii10017',    'afii10018',      'afii10040',          // E0 to E3
+     'afii10021', 'afii10022',    'afii10038',      'afii10020',          // E4 to E7
+     'afii10039', 'afii10026',    'afii10027',      'afii10028',          // E8 to EB
+     'afii10029', 'afii10030',    'afii10031',      'afii10032',          // EC to EF
+     'afii10033', 'afii10049',    'afii10034',      'afii10035',          // F0 to F3
+     'afii10036', 'afii10037',    'afii10024',      'afii10019',          // F4 to F7
+     'afii10046', 'afii10045',    'afii10025',      'afii10042',          // F8 to FB
+     'afii10047', 'afii10043',    'afii10041',      'afii10044');         // FC to FF
+
+const
+  koi8_u_v: TTTFEncodingValues =
+    (0,       1,       2,       3,       4,        5,       6,       7,         // 00 to 07
+     8,       9,       10,      11,      12,       13,      14,      15,        // 08 to 0F
+     16,      17,      18,      19,      20,       21,      22,      23,        // 10 to 17
+     24,      25,      26,      27,      28,       29,      30,      31,        // 18 to 1F
+     32,      33,      34,      35,      36,       37,      38,      39,        // 20 to 27
+     40,      41,      42,      43,      44,       45,      46,      47,        // 28 to 2F
+     48,      49,      50,      51,      52,       53,      54,      55,        // 30 to 37
+     56,      57,      58,      59,      60,       61,      62,      63,        // 38 to 3F
+     64,      65,      66,      67,      68,       69,      70,      71,        // 40 to 47
+     72,      73,      74,      75,      76,       77,      78,      79,        // 48 to 4F
+     80,      81,      82,      83,      84,       85,      86,      87,        // 50 to 57
+     88,      89,      90,      91,      92,       93,      94,      95,        // 58 to 5F
+     96,      97,      98,      99,      100,      101,     102,     103,       // 60 to 67
+     104,     105,     106,     107,     108,      109,     110,     111,       // 68 to 6F
+     112,     113,     114,     115,     116,      117,     118,     119,       // 70 to 77
+     120,     121,     122,     123,     124,      125,     126,     127,       // 78 to 7F
+     9472,    9474,    9484,    9488,    9492,     9496,    9500,    9508,      // 80 to 87
+     9516,    9524,    9532,    9600,    9604,     9608,    9612,    9616,      // 88 to 8F
+     9617,    9618,    9619,    8992,    9632,     8226,    8730,    8776,      // 90 to 97
+     8804,    8805,    160,     8993,    176,      178,     183,     247,       // 98 to 9F
+     9552,    9553,    9554,    1105,    1108,     9556,    1110,    1111,      // A0 to A7
+     9559,    9560,    9561,    9562,    9563,     1169,    9565,    9566,      // A8 to AF
+     9567,    9568,    9569,    1025,    1028,     9571,    1030,    1031,      // B0 to B7
+     9574,    9575,    9576,    9577,    9578,     1168,    9580,    169,       // B8 to BF
+     1102,    1072,    1073,    1094,    1076,     1077,    1092,    1075,      // C0 to C7
+     1093,    1080,    1081,    1082,    1083,     1084,    1085,    1086,      // C8 to CF
+     1087,    1103,    1088,    1089,    1090,     1091,    1078,    1074,      // D0 to D7
+     1100,    1099,    1079,    1096,    1101,     1097,    1095,    1098,      // D8 to DF
+     1070,    1040,    1041,    1062,    1044,     1045,    1060,    1043,      // E0 to E7
+     1061,    1048,    1049,    1050,    1051,     1052,    1053,    1054,      // E8 to EF
+     1055,    1071,    1056,    1057,    1058,     1059,    1046,    1042,      // F0 to F7
+     1068,    1067,    1047,    1064,    1069,     1065,    1063,    1066);     // F8 to FF
+
+Procedure GetEncodingTables(E : TTTFEncoding; Out ANames: PTTFEncodingNames; Out AValues: PTTFEncodingValues);
+
+begin
+
+  Case E of
+  teUnknown: begin ANames:=Nil;AValues:=Nil;end;
+  tecp874: begin ANames:=@cp874_n; AValues:=@cp874_v; end;
+  tecp1250: begin ANames:=@cp1250_n; AValues:=@cp1250_v; end;
+  tecp1251: begin ANames:=@cp1251_n; AValues:=@cp1251_v; end;
+  tecp1252: begin ANames:=@cp1252_n; AValues:=@cp1252_v; end;
+  tecp1253: begin ANames:=@cp1253_n; AValues:=@cp1253_v; end;
+  tecp1254: begin ANames:=@cp1254_n; AValues:=@cp1254_v; end;
+  tecp1255: begin ANames:=@cp1255_n; AValues:=@cp1255_v; end;
+  tecp1257: begin ANames:=@cp1257_n; AValues:=@cp1257_v; end;
+  tecp1258: begin ANames:=@cp1258_n; AValues:=@cp1258_v; end;
+  teiso_8859_1: begin ANames:=@iso_8859_1_n; AValues:=@iso_8859_1_v; end;
+  teiso_8859_2: begin ANames:=@iso_8859_2_n; AValues:=@iso_8859_2_v; end;
+  teiso_8859_4: begin ANames:=@iso_8859_4_n; AValues:=@iso_8859_4_v; end;
+  teiso_8859_5: begin ANames:=@iso_8859_5_n; AValues:=@iso_8859_5_v; end;
+  teiso_8859_7: begin ANames:=@iso_8859_7_n; AValues:=@iso_8859_7_v; end;
+  teiso_8859_9: begin ANames:=@iso_8859_9_n; AValues:=@iso_8859_9_v; end;
+  teiso_8859_11: begin ANames:=@iso_8859_11_n; AValues:=@iso_8859_11_v; end;
+  teiso_8859_15: begin ANames:=@iso_8859_15_n; AValues:=@iso_8859_15_v; end;
+  teiso_8859_16: begin ANames:=@iso_8859_16_n; AValues:=@iso_8859_16_v; end;
+  tekoi8_r: begin ANames:=@koi8_r_n; AValues:=@koi8_r_v; end;
+  tekoi8_u: begin ANames:=@koi8_u_n; AValues:=@koi8_u_v; end;
+  end;
+end;
+
+end.
+

+ 2060 - 0
packages/fcl-pdf/tests/fpparsettf_test.pas

@@ -0,0 +1,2060 @@
+unit fpparsettf_test;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils
+  {$ifdef fptest}
+  ,TestFramework
+  {$else}
+  ,fpcunit, testutils, testregistry
+  {$endif}
+  ,fpparsettf
+  ;
+
+type
+  { so we can access the protected methods }
+  TMyTFFileInfo = class(TTFFileInfo);
+
+
+  TBaseTestParseTTF = class(TTestCase)
+  private
+    FFileInfo: TMyTFFileInfo;
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+    procedure LoadFont(const AFilename: string);
+  public
+    property  FI: TMyTFFileInfo read FFileInfo;
+  end;
+
+
+  TTestEmptyParseTTF = class(TBaseTestParseTTF)
+  published
+    procedure TestEmptyTables;
+    procedure TestEmptyDirectory;
+  end;
+
+
+  TTestLiberationFont = class(TBaseTestParseTTF)
+  protected
+    procedure SetUp; override;
+  published
+    { Offset Table }
+    procedure TestDirectory_FontVersion;
+    procedure TestDirectory_NumTables;
+    procedure TestDirectory_SearchRange;
+    procedure TestDirectory_EntrySelector;
+    procedure TestDirectory_RangeShift;
+
+    { THead data structure tests }
+    procedure TestHead_FileVersion;
+    procedure TestHead_FontRevision;
+    procedure TestHead_CheckSumAdjustment;
+    procedure TestHead_MagicNumber;
+    procedure TestHead_Flags;
+    procedure TestHead_UnitsPerEm;
+    procedure TestHead_Created;
+    procedure TestHead_Modified;
+    procedure TestHead_BBox_xMin;
+    procedure TestHead_BBox_yMin;
+    procedure TestHead_BBox_xMax;
+    procedure TestHead_BBox_yMax;
+    procedure TestHead_MacStyle;
+    procedure TestHead_LowestRecPPEM;
+    procedure TestHead_FontDirectionHint;
+    procedure TestHead_IndexToLocFormat;
+    procedure TestHead_glyphDataFormat;
+
+    { THHead data structure tests }
+    procedure TestHHead_TableVersion;
+    procedure TestHHead_Ascender;
+    procedure TestHHead_Descender;
+    procedure TestHHead_LineGap;
+    procedure TestHHead_AdvanceWidthMax;
+    procedure TestHHead_MinLeftSideBearing;
+    procedure TestHHead_MinRightSideBearing;
+    procedure TestHHead_XMaxExtent;
+    procedure TestHHead_CaretSlopeRise;
+    procedure TestHHead_CaretSlopeRun;
+    procedure TestHHead_Reserved;
+    procedure TestHHead_metricDataFormat;
+    procedure TestHHead_numberOfHMetrics;
+
+    { TCmapHeader data structure tests }
+    procedure TestCMap_version;
+    procedure TestCMap_SubTableCount;
+
+    { TCmapSubTableEntry data structure tests }
+    procedure TestCMapSubTables_1;
+    procedure TestCMapSubTables_2;
+    procedure TestCMapSubTables_3;
+
+    { CmapUnicodeMap data structure tests }
+    procedure TestCmapUnicodeMap_Format;
+    procedure TestCmapUnicodeMap_Length;
+    procedure TestCmapUnicodeMap_SegmentCount2;
+    procedure TestCmapUnicodeMap_SearchRange;
+    procedure TestCmapUnicodeMap_EntrySelector;
+    procedure TestCmapUnicodeMap_RangeShift;
+
+    { TUnicodeMapSegment data structure tests }
+    procedure TestUnicodeMapSegment_1_StartCode;
+    procedure TestUnicodeMapSegment_1_EndCode;
+    procedure TestUnicodeMapSegment_1_IDDelta;
+    procedure TestUnicodeMapSegment_1_IDRangeOffset;
+    procedure TestUnicodeMapSegment_2_StartCode;
+    procedure TestUnicodeMapSegment_2_EndCode;
+    procedure TestUnicodeMapSegment_2_IDDelta;
+    procedure TestUnicodeMapSegment_2_IDRangeOffset;
+    procedure TestUnicodeMapSegment_127_StartCode;
+    procedure TestUnicodeMapSegment_127_EndCode;
+    procedure TestUnicodeMapSegment_127_IDDelta;
+    procedure TestUnicodeMapSegment_127_IDRangeOffset;
+
+    { hmtx - Horizontal Metrics data structure tests }
+    procedure TestWidths_Size;
+    procedure TestWidths_HorMetric_0_AdvanceWidth;
+    procedure TestWidths_HorMetric_0_LSB;
+    procedure TestWidths_HorMetric_1_AdvanceWidth;
+    procedure TestWidths_HorMetric_1_LSB;
+    procedure TestWidths_HorMetric_2586_AdvanceWidth;
+    procedure TestWidths_HorMetric_2586_LSB;
+
+    { maxp - Maximum Profile data structure tests }
+    procedure TestMaxP_VersionNumber;
+    procedure TestMaxP_numGlyphs;
+    procedure TestMaxP_maxPoints;
+    procedure TestMaxP_maxContours;
+    procedure TestMaxP_maxCompositePoints;
+    procedure TestMaxP_maxCompositeContours;
+    procedure TestMaxP_maxZones;
+    procedure TestMaxP_maxTwilightPoints;
+    procedure TestMaxP_maxStorage;
+    procedure TestMaxP_maxFunctionDefs;
+    procedure TestMaxP_maxInstructionDefs;
+    procedure TestMaxP_maxStackElements;
+    procedure TestMaxP_maxSizeOfInstructions;
+    procedure TestMaxP_maxComponentElements;
+    procedure TestMaxP_maxComponentDepth;
+
+    { OS2Data - OS/2 Data structure tests }
+    procedure TestOS2Data_version;
+    procedure TestOS2Data_xAvgCharWidth;
+    procedure TestOS2Data_usWeightClass;
+    procedure TestOS2Data_usWidthClass;
+    procedure TestOS2Data_fsType;
+    procedure TestOS2Data_ySubscriptXSize;
+    Procedure TestOS2Data_ySubscriptYSize;
+    Procedure TestOS2Data_ySubscriptXOffset;
+    Procedure TestOS2Data_ySubscriptYOffset;
+    Procedure TestOS2Data_ySuperscriptXSize;
+    Procedure TestOS2Data_ySuperscriptYSize;
+    Procedure TestOS2Data_ySuperscriptXOffset;
+    Procedure TestOS2Data_ySuperscriptYOffset;
+    Procedure TestOS2Data_yStrikeoutSize;
+    Procedure TestOS2Data_yStrikeoutPosition;
+    Procedure TestOS2Data_sFamilyClass;
+    procedure TestOS2Data_Panose;
+    procedure TestOS2Data_ulUnicodeRange1;
+    procedure TestOS2Data_ulUnicodeRange2;
+    procedure TestOS2Data_ulUnicodeRange3;
+    procedure TestOS2Data_ulUnicodeRange4;
+    procedure TestOS2Data_achVendID;
+    procedure TestOS2Data_fsSelection;
+    procedure TestOS2Data_usFirstCharIndex;
+    procedure TestOS2Data_usLastCharIndex;
+    procedure TestOS2Data_sTypoAscender;
+    procedure TestOS2Data_sTypoDescender;
+    procedure TestOS2Data_sTypoLineGap;
+    procedure TestOS2Data_usWinAscent;
+    procedure TestOS2Data_usWinDescent;
+    procedure TestOS2Data_ulCodePageRange1;
+    procedure TestOS2Data_ulCodePageRange2;
+    procedure TestOS2Data_sxHeight;
+    procedure TestOS2Data_sCapHeight;
+    procedure TestOS2Data_usDefaultChar;
+    procedure TestOS2Data_usBreakChar;
+    procedure TestOS2Data_usMaxContext;
+
+    { PostScript data structure }
+    procedure TestPostScript_Format;
+    procedure TestPostScript_ItalicAngle;
+    procedure TestPostScript_UnderlinePosition;
+    procedure TestPostScript_underlineThickness;
+    procedure TestPostScript_isFixedPitch;
+    procedure TestPostScript_minMemType42;
+    procedure TestPostScript_maxMemType42;
+    procedure TestPostScript_minMemType1;
+    procedure TestPostScript_maxMemType1;
+
+    { PDF Font Definition }
+    procedure TestPDFFontDefinition;
+    procedure TestMakePDFFontDefinition;
+
+    { Utility functions }
+    procedure TestGetGlyphIndex;
+    procedure TestGetAdvanceWidth;
+  end;
+
+
+  TTestFreeSansFont = class(TBaseTestParseTTF)
+  protected
+    procedure SetUp; override;
+  published
+    { Offset Table }
+    procedure TestDirectory_FontVersion;
+    procedure TestDirectory_NumTables;
+    procedure TestDirectory_SearchRange;
+    procedure TestDirectory_EntrySelector;
+    procedure TestDirectory_RangeShift;
+
+    { THead data structure tests }
+    procedure TestHead_FileVersion;
+    procedure TestHead_FontRevision;
+    procedure TestHead_CheckSumAdjustment;
+    procedure TestHead_MagicNumber;
+    procedure TestHead_Flags;
+    procedure TestHead_UnitsPerEm;
+    procedure TestHead_Created;
+    procedure TestHead_Modified;
+    procedure TestHead_BBox_xMin;
+    procedure TestHead_BBox_yMin;
+    procedure TestHead_BBox_xMax;
+    procedure TestHead_BBox_yMax;
+    procedure TestHead_MacStyle;
+    procedure TestHead_LowestRecPPEM;
+    procedure TestHead_FontDirectionHint;
+    procedure TestHead_IndexToLocFormat;
+    procedure TestHead_glyphDataFormat;
+
+    { THHead data structure tests }
+    procedure TestHHead_TableVersion;
+    procedure TestHHead_Ascender;
+    procedure TestHHead_Descender;
+    procedure TestHHead_LineGap;
+    procedure TestHHead_AdvanceWidthMax;
+    procedure TestHHead_MinLeftSideBearing;
+    procedure TestHHead_MinRightSideBearing;
+    procedure TestHHead_XMaxExtent;
+    procedure TestHHead_CaretSlopeRise;
+    procedure TestHHead_CaretSlopeRun;
+    procedure TestHHead_Reserved;
+    procedure TestHHead_metricDataFormat;
+    procedure TestHHead_numberOfHMetrics;
+
+    { TCmapHeader data structure tests }
+    procedure TestCMap_version;
+    procedure TestCMap_SubTableCount;
+
+    { TCmapSubTableEntry data structure tests }
+    procedure TestCMapSubTables_1;
+    procedure TestCMapSubTables_2;
+    procedure TestCMapSubTables_3;
+    procedure TestCMapSubTables_4;
+    procedure TestCMapSubTables_5;
+
+    { CmapUnicodeMap data structure tests }
+    procedure TestCmapUnicodeMap_Format;
+    procedure TestCmapUnicodeMap_Length;
+    procedure TestCmapUnicodeMap_SegmentCount2;
+    procedure TestCmapUnicodeMap_SearchRange;
+    procedure TestCmapUnicodeMap_EntrySelector;
+    procedure TestCmapUnicodeMap_RangeShift;
+
+    { TUnicodeMapSegment data structure tests }
+    procedure TestUnicodeMapSegment_1_StartCode;
+    procedure TestUnicodeMapSegment_1_EndCode;
+    procedure TestUnicodeMapSegment_1_IDDelta;
+    procedure TestUnicodeMapSegment_1_IDRangeOffset;
+    procedure TestUnicodeMapSegment_2_StartCode;
+    procedure TestUnicodeMapSegment_2_EndCode;
+    procedure TestUnicodeMapSegment_2_IDDelta;
+    procedure TestUnicodeMapSegment_2_IDRangeOffset;
+    procedure TestUnicodeMapSegment_127_StartCode;
+    procedure TestUnicodeMapSegment_127_EndCode;
+    procedure TestUnicodeMapSegment_127_IDDelta;
+    procedure TestUnicodeMapSegment_127_IDRangeOffset;
+
+    { hmtx - Horizontal Metrics data structure tests }
+    procedure TestWidths_Size;
+    procedure TestWidths_HorMetric_0_AdvanceWidth;
+    procedure TestWidths_HorMetric_0_LSB;
+    procedure TestWidths_HorMetric_1_AdvanceWidth;
+    procedure TestWidths_HorMetric_1_LSB;
+    procedure TestWidths_HorMetric_2586_AdvanceWidth;
+    procedure TestWidths_HorMetric_2586_LSB;
+
+    { maxp - Maximum Profile data structure tests }
+    procedure TestMaxP_VersionNumber;
+    procedure TestMaxP_numGlyphs;
+    procedure TestMaxP_maxPoints;
+    procedure TestMaxP_maxContours;
+    procedure TestMaxP_maxCompositePoints;
+    procedure TestMaxP_maxCompositeContours;
+    procedure TestMaxP_maxZones;
+    procedure TestMaxP_maxTwilightPoints;
+    procedure TestMaxP_maxStorage;
+    procedure TestMaxP_maxFunctionDefs;
+    procedure TestMaxP_maxInstructionDefs;
+    procedure TestMaxP_maxStackElements;
+    procedure TestMaxP_maxSizeOfInstructions;
+    procedure TestMaxP_maxComponentElements;
+    procedure TestMaxP_maxComponentDepth;
+
+    { OS2Data - OS/2 Data structure tests }
+    procedure TestOS2Data_version;
+    procedure TestOS2Data_xAvgCharWidth;
+    procedure TestOS2Data_usWeightClass;
+    procedure TestOS2Data_usWidthClass;
+    procedure TestOS2Data_fsType;
+    procedure TestOS2Data_ySubscriptXSize;
+    Procedure TestOS2Data_ySubscriptYSize;
+    Procedure TestOS2Data_ySubscriptXOffset;
+    Procedure TestOS2Data_ySubscriptYOffset;
+    Procedure TestOS2Data_ySuperscriptXSize;
+    Procedure TestOS2Data_ySuperscriptYSize;
+    Procedure TestOS2Data_ySuperscriptXOffset;
+    Procedure TestOS2Data_ySuperscriptYOffset;
+    Procedure TestOS2Data_yStrikeoutSize;
+    Procedure TestOS2Data_yStrikeoutPosition;
+    Procedure TestOS2Data_sFamilyClass;
+    procedure TestOS2Data_Panose;
+    procedure TestOS2Data_ulUnicodeRange1;
+    procedure TestOS2Data_ulUnicodeRange2;
+    procedure TestOS2Data_ulUnicodeRange3;
+    procedure TestOS2Data_ulUnicodeRange4;
+    procedure TestOS2Data_achVendID;
+    procedure TestOS2Data_fsSelection;
+    procedure TestOS2Data_usFirstCharIndex;
+    procedure TestOS2Data_usLastCharIndex;
+    procedure TestOS2Data_sTypoAscender;
+    procedure TestOS2Data_sTypoDescender;
+    procedure TestOS2Data_sTypoLineGap;
+    procedure TestOS2Data_usWinAscent;
+    procedure TestOS2Data_usWinDescent;
+    procedure TestOS2Data_ulCodePageRange1;
+    procedure TestOS2Data_ulCodePageRange2;
+    procedure TestOS2Data_sxHeight;
+    procedure TestOS2Data_sCapHeight;
+    procedure TestOS2Data_usDefaultChar;
+    procedure TestOS2Data_usBreakChar;
+    procedure TestOS2Data_usMaxContext;
+
+    { PostScript data structure }
+    procedure TestPostScript_Format;
+    procedure TestPostScript_ItalicAngle;
+    procedure TestPostScript_UnderlinePosition;
+    procedure TestPostScript_underlineThickness;
+    procedure TestPostScript_isFixedPitch;
+    procedure TestPostScript_minMemType42;
+    procedure TestPostScript_maxMemType42;
+    procedure TestPostScript_minMemType1;
+    procedure TestPostScript_maxMemType1;
+
+    { PDF Font Definition }
+    procedure TestPDFFontDefinition;
+    procedure TestMakePDFFontDefinition;
+  end;
+
+implementation
+
+uses
+  dateutils
+  ,strutils
+  ,IniFiles
+  ;
+
+const
+  cFont1 = 'fonts' + PathDelim + 'LiberationSans-Regular.ttf';
+  cFont2 = 'fonts' + PathDelim + 'FreeSans.ttf';
+
+{ TTestEmptyParseTTF }
+
+procedure TBaseTestParseTTF.SetUp;
+begin
+  FFileInfo := TMyTFFileInfo.Create;
+end;
+
+procedure TBaseTestParseTTF.TearDown;
+begin
+  FFileInfo.Free;
+end;
+
+procedure TBaseTestParseTTF.LoadFont(const AFilename: string);
+begin
+  Assert(FFileInfo <> nil, 'FFileInfo has not been instantiated');
+  FFileInfo.LoadFromFile(AFilename);
+end;
+
+procedure TTestEmptyParseTTF.TestEmptyTables;
+begin
+  AssertTrue('Failed on 1', Length(FI.Tables) = 0)
+end;
+
+procedure TTestEmptyParseTTF.TestEmptyDirectory;
+begin
+  AssertEquals('Failed on 1', 0, FI.Directory.FontVersion.Major);
+  AssertEquals('Failed on 2', 0, FI.Directory.FontVersion.Minor);
+  AssertEquals('Failed on 3', 0, FI.Directory.Numtables);
+end;
+
+{ TTestLiberationFont }
+
+procedure TTestLiberationFont.SetUp;
+begin
+  inherited SetUp;
+  LoadFont(cFont1);
+end;
+
+procedure TTestLiberationFont.TestDirectory_FontVersion;
+begin
+  AssertEquals('Failed on 0', '00010000', IntToHex(FI.Directory.FontVersion.Version, 8));
+  AssertEquals('Failed on Major Version', 1, FI.Directory.FontVersion.Major);
+  AssertEquals('Failed on Minor Version', 0, FI.Directory.FontVersion.Minor);
+end;
+
+procedure TTestLiberationFont.TestDirectory_NumTables;
+begin
+  AssertEquals('Failed on Numtables', 19, Int(FI.Directory.Numtables));
+end;
+
+procedure TTestLiberationFont.TestDirectory_SearchRange;
+begin
+  AssertEquals('Failed on SearchRange', 256, Int(FI.Directory.SearchRange));
+end;
+
+procedure TTestLiberationFont.TestDirectory_EntrySelector;
+begin
+  AssertEquals('Failed on EntrySelector', 4, Int(FI.Directory.EntrySelector));
+end;
+
+procedure TTestLiberationFont.TestDirectory_RangeShift;
+begin
+  AssertEquals('Failed on RangeShift', 48, Int(FI.Directory.RangeShift));
+end;
+
+procedure TTestLiberationFont.TestHead_FileVersion;
+begin
+  AssertEquals('Failed on 1', '00010000', IntToHex(FI.Head.FileVersion.Version, 8));
+  AssertEquals('Failed on 2', 1, FI.Head.FileVersion.Major);
+  AssertEquals('Failed on 3', 0, FI.Head.FileVersion.Minor);
+end;
+
+procedure TTestLiberationFont.TestHead_FontRevision;
+begin
+  AssertEquals('Failed on 1', '00020000', IntToHex(FI.Head.FontRevision.Version, 8));
+  AssertEquals('Failed on 2', 2, FI.Head.FontRevision.Major);
+  AssertEquals('Failed on 3', 0, FI.Head.FontRevision.Minor);
+end;
+
+procedure TTestLiberationFont.TestHead_CheckSumAdjustment;
+begin
+  AssertEquals('Failed on 1', $D6572D59, FI.Head.CheckSumAdjustment);
+end;
+
+procedure TTestLiberationFont.TestHead_MagicNumber;
+begin
+  AssertEquals('Failed on 1', $5F0F3CF5, FI.Head.MagicNumber);
+end;
+
+procedure TTestLiberationFont.TestHead_Flags;
+begin
+  AssertEquals('Failed on 1', $021F, FI.Head.Flags);
+end;
+
+procedure TTestLiberationFont.TestHead_UnitsPerEm;
+begin
+  AssertEquals('Failed on 1', 2048, FI.Head.UnitsPerEm);
+end;
+
+procedure TTestLiberationFont.TestHead_Created;
+var
+  dt: TDateTime;
+  s: string;
+begin
+  // LONGDATETIME: Date represented in number of seconds since 12:00 midnight,
+  //              January 1, 1904. The value is represented as a signed 64-bit integer.
+  //dt := EncodeDateTime(1904, 1, 1, 0, 0, 0, 0);
+  //s := FormatDateTime('yyyy-mm-dd hh:nn:ss', dt);
+  //AssertEquals('Failed on 1', '1904-01-01 00:00:00', s);
+
+  //dt := IncSecond(dt, FI.Head.Created);
+
+  // The above code equates to using MacToDateTime()
+  dt := MacToDateTime(FI.Head.Created);
+
+  // We don't use this AssertEquals() because it shows a huge Double data-type
+  // value as the result.
+  //AssertEquals('Failed on 1', EncodeDateTime(2012, 10, 4, 20, 2, 31, 0), dt);
+
+  // Instead we use this - which shows human readable dates.
+  s := FormatDateTime('yyyy-mm-dd hh:nn:ss', dt);
+  AssertEquals('Failed on 2', '2012-10-04 20:02:31', s);
+end;
+
+procedure TTestLiberationFont.TestHead_Modified;
+var
+  dt: TDateTime;
+  s: string;
+begin
+  dt := MacToDateTime(FI.Head.Modified);
+  s := FormatDateTime('yyyy-mm-dd hh:nn:ss', dt);
+  AssertEquals('Failed on 2', '2012-10-04 20:02:31', s);
+end;
+
+procedure TTestLiberationFont.TestHead_BBox_xMin;
+begin
+  AssertEquals('Failed on 1', -1114, FI.Head.BBox[0]);
+end;
+
+procedure TTestLiberationFont.TestHead_BBox_yMin;
+begin
+  AssertEquals('Failed on 1', -621, FI.Head.BBox[1]);
+end;
+
+procedure TTestLiberationFont.TestHead_BBox_xMax;
+begin
+  AssertEquals('Failed on 1', 2666, FI.Head.BBox[2]);
+end;
+
+procedure TTestLiberationFont.TestHead_BBox_yMax;
+begin
+  AssertEquals('Failed on 1', 2007, FI.Head.BBox[3]);
+end;
+
+procedure TTestLiberationFont.TestHead_MacStyle;
+begin
+  AssertEquals('Failed on 1', $0000, FI.Head.MacStyle);
+end;
+
+procedure TTestLiberationFont.TestHead_LowestRecPPEM;
+begin
+  AssertEquals('Failed on 1', 8, FI.Head.LowestRecPPEM);
+end;
+
+procedure TTestLiberationFont.TestHead_FontDirectionHint;
+begin
+  AssertEquals('Failed on 1', 0, FI.Head.FontDirectionHint);
+end;
+
+procedure TTestLiberationFont.TestHead_IndexToLocFormat;
+begin
+  AssertEquals('Failed on 1', 1, FI.Head.IndexToLocFormat);
+end;
+
+procedure TTestLiberationFont.TestHead_glyphDataFormat;
+begin
+  AssertEquals('Failed on 1', 0, FI.Head.glyphDataFormat);
+end;
+
+procedure TTestLiberationFont.TestHHead_TableVersion;
+begin
+  AssertEquals('Failed on 1', '00010000', IntToHex(FI.HHead.TableVersion.Version, 8));
+  AssertEquals('Failed on 2', 1, FI.HHead.TableVersion.Major);
+  AssertEquals('Failed on 3', 0, FI.HHead.TableVersion.Minor);
+end;
+
+procedure TTestLiberationFont.TestHHead_Ascender;
+begin
+  AssertEquals('Failed on 1', 1854, FI.HHead.Ascender);
+end;
+
+procedure TTestLiberationFont.TestHHead_Descender;
+begin
+  AssertEquals('Failed on 1', -434, FI.HHead.Descender);
+end;
+
+procedure TTestLiberationFont.TestHHead_LineGap;
+begin
+  AssertEquals('Failed on 1', 67, FI.HHead.LineGap);
+end;
+
+procedure TTestLiberationFont.TestHHead_AdvanceWidthMax;
+begin
+  AssertEquals('Failed on 1', 2740, FI.HHead.AdvanceWidthMax);
+end;
+
+procedure TTestLiberationFont.TestHHead_MinLeftSideBearing;
+begin
+  AssertEquals('Failed on 1', -1114, FI.HHead.MinLeftSideBearing);
+end;
+
+procedure TTestLiberationFont.TestHHead_MinRightSideBearing;
+begin
+  AssertEquals('Failed on 1', -1414, FI.HHead.MinRightSideBearing);
+end;
+
+procedure TTestLiberationFont.TestHHead_XMaxExtent;
+begin
+  AssertEquals('Failed on 1', 2666, FI.HHead.XMaxExtent);
+end;
+
+procedure TTestLiberationFont.TestHHead_CaretSlopeRise;
+begin
+  AssertEquals('Failed on 1', 1, FI.HHead.CaretSlopeRise);
+end;
+
+procedure TTestLiberationFont.TestHHead_CaretSlopeRun;
+begin
+  AssertEquals('Failed on 1', 0, FI.HHead.CaretSlopeRun);
+end;
+
+procedure TTestLiberationFont.TestHHead_Reserved;
+begin
+  AssertEquals('Failed on 1', 0, FI.HHead.Reserved[0]);
+  AssertEquals('Failed on 2', 0, FI.HHead.Reserved[1]);
+  AssertEquals('Failed on 3', 0, FI.HHead.Reserved[2]);
+  AssertEquals('Failed on 4', 0, FI.HHead.Reserved[3]);
+  AssertEquals('Failed on 5', 0, FI.HHead.Reserved[4]);
+end;
+
+procedure TTestLiberationFont.TestHHead_metricDataFormat;
+begin
+  AssertEquals('Failed on 1', 0, FI.HHead.metricDataFormat);
+end;
+
+procedure TTestLiberationFont.TestHHead_numberOfHMetrics;
+begin
+  AssertEquals('Failed on 1', 2587, FI.HHead.numberOfHMetrics);
+end;
+
+procedure TTestLiberationFont.TestCMap_version;
+begin
+  AssertEquals('Failed on 1', '0000', IntToHex(FI.CmapH.Version, 4));
+  AssertEquals('Failed on 2', 0, FI.CmapH.Version);
+end;
+
+procedure TTestLiberationFont.TestCMap_SubTableCount;
+begin
+  AssertEquals('Failed on 1', 3, FI.CmapH.SubTableCount);
+end;
+
+procedure TTestLiberationFont.TestCMapSubTables_1;
+var
+  lSubTable: TCmapSubTableEntry;
+begin
+  lSubTable := FI.CmapSubtables[0];
+  AssertEquals('Failed on 1', 0, lSubTable.PlatformID);
+  AssertEquals('Failed on 2', 3, lSubTable.EncodingID);
+  AssertEquals('Failed on 3', '0000001C', IntToHex(lSubTable.Offset, 8));
+end;
+
+procedure TTestLiberationFont.TestCMapSubTables_2;
+var
+  lSubTable: TCmapSubTableEntry;
+begin
+  lSubTable := FI.CmapSubtables[1];
+  AssertEquals('Failed on 1', 1, lSubTable.PlatformID);
+  AssertEquals('Failed on 2', 0, lSubTable.EncodingID);
+  AssertEquals('Failed on 3', '00000424', IntToHex(lSubTable.Offset, 8));
+end;
+
+procedure TTestLiberationFont.TestCMapSubTables_3;
+var
+  lSubTable: TCmapSubTableEntry;
+begin
+  lSubTable := FI.CmapSubtables[2];
+  AssertEquals('Failed on 1', 3, lSubTable.PlatformID);
+  AssertEquals('Failed on 2', 1, lSubTable.EncodingID);
+  AssertEquals('Failed on 3', '0000001C', IntToHex(lSubTable.Offset, 8));
+end;
+
+procedure TTestLiberationFont.TestCmapUnicodeMap_Format;
+begin
+  AssertEquals('Failed on 1', 4, FI.CmapUnicodeMap.Format);
+end;
+
+procedure TTestLiberationFont.TestCmapUnicodeMap_Length;
+begin
+  AssertEquals('Failed on 1', 1032, FI.CmapUnicodeMap.Length);
+end;
+
+procedure TTestLiberationFont.TestCmapUnicodeMap_SegmentCount2;
+begin
+  AssertEquals('Failed on 1', 254, FI.CmapUnicodeMap.SegmentCount2);
+end;
+
+procedure TTestLiberationFont.TestCmapUnicodeMap_SearchRange;
+begin
+  AssertEquals('Failed on 1', 128, FI.CmapUnicodeMap.SearchRange);
+end;
+
+procedure TTestLiberationFont.TestCmapUnicodeMap_EntrySelector;
+begin
+  AssertEquals('Failed on 1', 6, FI.CmapUnicodeMap.EntrySelector);
+end;
+
+procedure TTestLiberationFont.TestCmapUnicodeMap_RangeShift;
+begin
+  AssertEquals('Failed on 1', 126, FI.CmapUnicodeMap.RangeShift);
+end;
+
+procedure TTestLiberationFont.TestUnicodeMapSegment_1_StartCode;
+begin
+  AssertEquals('Failed on 1', '0020', IntToHex(FI.CmapUnicodeMapSegments[0].StartCode, 4));
+end;
+
+procedure TTestLiberationFont.TestUnicodeMapSegment_1_EndCode;
+begin
+  AssertEquals('Failed on 1', '007E', IntToHex(FI.CmapUnicodeMapSegments[0].EndCode, 4));
+end;
+
+procedure TTestLiberationFont.TestUnicodeMapSegment_1_IDDelta;
+begin
+  AssertEquals('Failed on 1', -29, FI.CmapUnicodeMapSegments[0].IDDelta);
+end;
+
+procedure TTestLiberationFont.TestUnicodeMapSegment_1_IDRangeOffset;
+begin
+  AssertEquals('Failed on 1', 0, FI.CmapUnicodeMapSegments[0].IDRangeOffset);
+end;
+
+procedure TTestLiberationFont.TestUnicodeMapSegment_2_StartCode;
+begin
+  AssertEquals('Failed on 1', '00A0', IntToHex(FI.CmapUnicodeMapSegments[1].StartCode, 4));
+end;
+
+procedure TTestLiberationFont.TestUnicodeMapSegment_2_EndCode;
+begin
+  AssertEquals('Failed on 1', '036F', IntToHex(FI.CmapUnicodeMapSegments[1].EndCode, 4));
+end;
+
+procedure TTestLiberationFont.TestUnicodeMapSegment_2_IDDelta;
+begin
+  AssertEquals('Failed on 1', -62, FI.CmapUnicodeMapSegments[1].IDDelta);
+end;
+
+procedure TTestLiberationFont.TestUnicodeMapSegment_2_IDRangeOffset;
+begin
+  AssertEquals('Failed on 1', 0, FI.CmapUnicodeMapSegments[1].IDRangeOffset);
+end;
+
+procedure TTestLiberationFont.TestUnicodeMapSegment_127_StartCode;
+begin
+  AssertEquals('Failed on 1', 'FFFF', IntToHex(FI.CmapUnicodeMapSegments[126].StartCode, 4));
+end;
+
+procedure TTestLiberationFont.TestUnicodeMapSegment_127_EndCode;
+begin
+  AssertEquals('Failed on 1', 'FFFF', IntToHex(FI.CmapUnicodeMapSegments[126].EndCode, 4));
+end;
+
+procedure TTestLiberationFont.TestUnicodeMapSegment_127_IDDelta;
+begin
+  AssertEquals('Failed on 1', 1, FI.CmapUnicodeMapSegments[126].IDDelta);
+end;
+
+procedure TTestLiberationFont.TestUnicodeMapSegment_127_IDRangeOffset;
+begin
+  AssertEquals('Failed on 1', 0, FI.CmapUnicodeMapSegments[126].IDRangeOffset);
+end;
+
+procedure TTestLiberationFont.TestWidths_Size;
+begin
+  AssertEquals('Failed on 1', 2587, Length(FI.Widths));
+end;
+
+procedure TTestLiberationFont.TestWidths_HorMetric_0_AdvanceWidth;
+begin
+  AssertEquals('Failed on 1', 1536, FI.Widths[0].AdvanceWidth);
+end;
+
+procedure TTestLiberationFont.TestWidths_HorMetric_0_LSB;
+begin
+  AssertEquals('Failed on 1', 205, FI.Widths[0].LSB);
+end;
+
+procedure TTestLiberationFont.TestWidths_HorMetric_1_AdvanceWidth;
+begin
+  AssertEquals('Failed on 1', 0, FI.Widths[1].AdvanceWidth);
+end;
+
+procedure TTestLiberationFont.TestWidths_HorMetric_1_LSB;
+begin
+  AssertEquals('Failed on 1', 0, FI.Widths[1].LSB);
+end;
+
+procedure TTestLiberationFont.TestWidths_HorMetric_2586_AdvanceWidth;
+begin
+  AssertEquals('Failed on 1', 1140, FI.Widths[2586].AdvanceWidth);
+end;
+
+procedure TTestLiberationFont.TestWidths_HorMetric_2586_LSB;
+begin
+  AssertEquals('Failed on 1', 86, FI.Widths[2586].LSB);
+end;
+
+procedure TTestLiberationFont.TestMaxP_VersionNumber;
+begin
+  AssertEquals('Failed on 1', '00010000', IntToHex(FI.MaxP.VersionNumber.Version, 8));
+  AssertEquals('Failed on 2', 1, FI.MaxP.VersionNumber.Major);
+  AssertEquals('Failed on 3', 0, FI.MaxP.VersionNumber.Minor);
+end;
+
+procedure TTestLiberationFont.TestMaxP_numGlyphs;
+begin
+  AssertEquals('Failed on 1', 2587, FI.MaxP.numGlyphs);
+end;
+
+procedure TTestLiberationFont.TestMaxP_maxPoints;
+begin
+  AssertEquals('Failed on 1', 338, FI.MaxP.maxPoints);
+end;
+
+procedure TTestLiberationFont.TestMaxP_maxContours;
+begin
+  AssertEquals('Failed on 1', 84, FI.MaxP.maxContours);
+end;
+
+procedure TTestLiberationFont.TestMaxP_maxCompositePoints;
+begin
+  AssertEquals('Failed on 1', 92, FI.MaxP.maxCompositePoints);
+end;
+
+procedure TTestLiberationFont.TestMaxP_maxCompositeContours;
+begin
+  AssertEquals('Failed on 1', 6, FI.MaxP.maxCompositeContours);
+end;
+
+procedure TTestLiberationFont.TestMaxP_maxZones;
+begin
+  AssertEquals('Failed on 1', 2, FI.MaxP.maxZones);
+end;
+
+procedure TTestLiberationFont.TestMaxP_maxTwilightPoints;
+begin
+  AssertEquals('Failed on 1', 16, FI.MaxP.maxTwilightPoints);
+end;
+
+procedure TTestLiberationFont.TestMaxP_maxStorage;
+begin
+  AssertEquals('Failed on 1', 47, FI.MaxP.maxStorage);
+end;
+
+procedure TTestLiberationFont.TestMaxP_maxFunctionDefs;
+begin
+  AssertEquals('Failed on 1', 92, FI.MaxP.maxFunctionDefs);
+end;
+
+procedure TTestLiberationFont.TestMaxP_maxInstructionDefs;
+begin
+  AssertEquals('Failed on 1', 0, FI.MaxP.maxInstructionDefs);
+end;
+
+procedure TTestLiberationFont.TestMaxP_maxStackElements;
+begin
+  AssertEquals('Failed on 1', 676, FI.MaxP.maxStackElements);
+end;
+
+procedure TTestLiberationFont.TestMaxP_maxSizeOfInstructions;
+begin
+  AssertEquals('Failed on 1', 516, FI.MaxP.maxSizeOfInstructions);
+end;
+
+procedure TTestLiberationFont.TestMaxP_maxComponentElements;
+begin
+  AssertEquals('Failed on 1', 4, FI.MaxP.maxComponentElements);
+end;
+
+procedure TTestLiberationFont.TestMaxP_maxComponentDepth;
+begin
+  AssertEquals('Failed on 1', 1, FI.MaxP.maxComponentDepth);
+end;
+
+procedure TTestLiberationFont.TestOS2Data_version;
+begin
+  AssertEquals('Failed on 1', 3, FI.OS2Data.version);
+end;
+
+procedure TTestLiberationFont.TestOS2Data_xAvgCharWidth;
+begin
+  AssertEquals('Failed on 1', 1186, FI.OS2Data.xAvgCharWidth);
+end;
+
+procedure TTestLiberationFont.TestOS2Data_usWeightClass;
+begin
+  AssertEquals('Failed on 1', 400, FI.OS2Data.usWeightClass);
+end;
+
+procedure TTestLiberationFont.TestOS2Data_usWidthClass;
+begin
+  AssertEquals('Failed on 1', 5, FI.OS2Data.usWidthClass);
+end;
+
+procedure TTestLiberationFont.TestOS2Data_fsType;
+begin
+  AssertEquals('Failed on 1', '0000', IntToHex(FI.OS2Data.fsType, 4));
+end;
+
+procedure TTestLiberationFont.TestOS2Data_ySubscriptXSize;
+begin
+  AssertEquals('Failed on 1', 1434, FI.OS2Data.ySubscriptXSize);
+end;
+
+procedure TTestLiberationFont.TestOS2Data_ySubscriptYSize;
+begin
+  AssertEquals('Failed on 1', 1331, FI.OS2Data.ySubscriptYSize);
+end;
+
+
+procedure TTestLiberationFont.TestOS2Data_ySubscriptXOffset;
+begin
+  AssertEquals('Failed on 1', 0, FI.OS2Data.ySubscriptXOffset);
+end;
+
+
+procedure TTestLiberationFont.TestOS2Data_ySubscriptYOffset;
+begin
+  AssertEquals('Failed on 1', 283, FI.OS2Data.ySubscriptYOffset);
+end;
+
+
+procedure TTestLiberationFont.TestOS2Data_ySuperscriptXSize;
+begin
+  AssertEquals('Failed on 1', 1434, FI.OS2Data.ySuperscriptXSize);
+end;
+
+
+procedure TTestLiberationFont.TestOS2Data_ySuperscriptYSize;
+begin
+  AssertEquals('Failed on 1', 1331, FI.OS2Data.ySuperscriptYSize);
+end;
+
+
+procedure TTestLiberationFont.TestOS2Data_ySuperscriptXOffset;
+begin
+  AssertEquals('Failed on 1', 0, FI.OS2Data.ySuperscriptXOffset);
+end;
+
+
+procedure TTestLiberationFont.TestOS2Data_ySuperscriptYOffset;
+begin
+  AssertEquals('Failed on 1', 977, FI.OS2Data.ySuperscriptYOffset);
+end;
+
+
+procedure TTestLiberationFont.TestOS2Data_yStrikeoutSize;
+begin
+  AssertEquals('Failed on 1', 102, FI.OS2Data.yStrikeoutSize);
+end;
+
+
+procedure TTestLiberationFont.TestOS2Data_yStrikeoutPosition;
+begin
+  AssertEquals('Failed on 1', 530, FI.OS2Data.yStrikeoutPosition);
+end;
+
+
+procedure TTestLiberationFont.TestOS2Data_sFamilyClass;
+begin
+  AssertEquals('Failed on 1', 5, Lo(FI.OS2Data.sFamilyClass));
+  AssertEquals('Failed on 2', 8, Hi(FI.OS2Data.sFamilyClass));
+  AssertEquals('Failed on 3', '0805', IntToHex(FI.OS2Data.sFamilyClass, 4));
+end;
+
+procedure TTestLiberationFont.TestOS2Data_Panose;
+begin
+  AssertEquals('Failed on 1', 2, FI.OS2Data.panose[0]);
+  AssertEquals('Failed on 2', 11, FI.OS2Data.panose[1]);
+  AssertEquals('Failed on 3', 6, FI.OS2Data.panose[2]);
+  AssertEquals('Failed on 4', 4, FI.OS2Data.panose[3]);
+  AssertEquals('Failed on 5', 2, FI.OS2Data.panose[4]);
+  AssertEquals('Failed on 6', 2, FI.OS2Data.panose[5]);
+  AssertEquals('Failed on 7', 2, FI.OS2Data.panose[6]);
+  AssertEquals('Failed on 8', 2, FI.OS2Data.panose[7]);
+  AssertEquals('Failed on 9', 2, FI.OS2Data.panose[8]);
+  AssertEquals('Failed on 10', 4, FI.OS2Data.panose[9]);
+end;
+
+procedure TTestLiberationFont.TestOS2Data_ulUnicodeRange1;
+begin
+  AssertEquals('Failed on 1', '1110 0000 0000 0000 0000 1010 1111 1111', IntToBin(FI.OS2Data.ulUnicodeRange1, 32, 4));
+  AssertEquals('Failed on 2', 'E0000AFF', IntToHex(FI.OS2Data.ulUnicodeRange1, 8));
+end;
+
+procedure TTestLiberationFont.TestOS2Data_ulUnicodeRange2;
+begin
+  AssertEquals('Failed on 1', '0101 0000 0000 0000 0111 1000 1111 1111', IntToBin(FI.OS2Data.ulUnicodeRange2, 32, 4));
+  AssertEquals('Failed on 2', '500078FF', IntToHex(FI.OS2Data.ulUnicodeRange2, 8));
+end;
+
+procedure TTestLiberationFont.TestOS2Data_ulUnicodeRange3;
+begin
+  AssertEquals('Failed on 1', '0000 0000 0000 0000 0000 0000 0010 0001', IntToBin(FI.OS2Data.ulUnicodeRange3, 32, 4));
+  AssertEquals('Failed on 2', '00000021', IntToHex(FI.OS2Data.ulUnicodeRange3, 8));
+end;
+
+procedure TTestLiberationFont.TestOS2Data_ulUnicodeRange4;
+begin
+  AssertEquals('Failed on 1', '0000 0000 0000 0000 0000 0000 0000 0000', IntToBin(FI.OS2Data.ulUnicodeRange4, 32, 4));
+  AssertEquals('Failed on 2', '00000000', IntToHex(FI.OS2Data.ulUnicodeRange4, 8));
+end;
+
+procedure TTestLiberationFont.TestOS2Data_achVendID;
+var
+  s: string;
+begin
+  s := FI.OS2Data.achVendID[0] + FI.OS2Data.achVendID[1] + FI.OS2Data.achVendID[2] +
+        FI.OS2Data.achVendID[3];
+  AssertEquals('Failed on 1', '1ASC', s);
+end;
+
+procedure TTestLiberationFont.TestOS2Data_fsSelection;
+begin
+  AssertEquals('Failed on 1', '0040', IntToHex(FI.OS2Data.fsSelection, 4));
+end;
+
+procedure TTestLiberationFont.TestOS2Data_usFirstCharIndex;
+begin
+  AssertEquals('Failed on 1', '0020', IntToHex(FI.OS2Data.usFirstCharIndex, 4));
+end;
+
+procedure TTestLiberationFont.TestOS2Data_usLastCharIndex;
+begin
+  AssertEquals('Failed on 1', 'FFFC', IntToHex(FI.OS2Data.usLastCharIndex, 4));
+end;
+
+procedure TTestLiberationFont.TestOS2Data_sTypoAscender;
+begin
+  AssertEquals('Failed on 1', 1491, FI.OS2Data.sTypoAscender);
+end;
+
+procedure TTestLiberationFont.TestOS2Data_sTypoDescender;
+begin
+  AssertEquals('Failed on 1', -431, FI.OS2Data.sTypoDescender);
+end;
+
+procedure TTestLiberationFont.TestOS2Data_sTypoLineGap;
+begin
+  AssertEquals('Failed on 1', 307, FI.OS2Data.sTypoLineGap);
+end;
+
+procedure TTestLiberationFont.TestOS2Data_usWinAscent;
+begin
+  AssertEquals('Failed on 1', 1854, FI.OS2Data.usWinAscent);
+end;
+
+procedure TTestLiberationFont.TestOS2Data_usWinDescent;
+begin
+  AssertEquals('Failed on 1', 434, FI.OS2Data.usWinDescent);
+end;
+
+procedure TTestLiberationFont.TestOS2Data_ulCodePageRange1;
+begin
+  AssertEquals('Failed on 1', '600001BF', IntToHex(FI.OS2Data.ulCodePageRange1, 8));
+end;
+
+procedure TTestLiberationFont.TestOS2Data_ulCodePageRange2;
+begin
+  AssertEquals('Failed on 1', 'DFF70000', IntToHex(FI.OS2Data.ulCodePageRange2, 8));
+end;
+
+procedure TTestLiberationFont.TestOS2Data_sxHeight;
+begin
+  AssertEquals('Failed on 1', 1082, FI.OS2Data.sxHeight);
+end;
+
+procedure TTestLiberationFont.TestOS2Data_sCapHeight;
+begin
+  AssertEquals('Failed on 1', 1409, FI.OS2Data.sCapHeight);
+end;
+
+procedure TTestLiberationFont.TestOS2Data_usDefaultChar;
+begin
+  AssertEquals('Failed on 1', '0000', IntToHex(FI.OS2Data.usDefaultChar, 4));
+end;
+
+procedure TTestLiberationFont.TestOS2Data_usBreakChar;
+begin
+  AssertEquals('Failed on 1', '0020', IntToHex(FI.OS2Data.usBreakChar, 4));
+end;
+
+procedure TTestLiberationFont.TestOS2Data_usMaxContext;
+begin
+  AssertEquals('Failed on 1', 14, FI.OS2Data.usMaxContext);
+end;
+
+procedure TTestLiberationFont.TestPostScript_Format;
+begin
+  AssertEquals('Failed on 1', '00020000', IntToHex(FI.PostScript.Format.Version, 8));
+  AssertEquals('Failed on 2', 2, FI.PostScript.Format.Major);
+  AssertEquals('Failed on 3', 0, FI.PostScript.Format.Minor);
+end;
+
+procedure TTestLiberationFont.TestPostScript_ItalicAngle;
+begin
+  AssertEquals('Failed on 1', 0.0, FI.PostScript.ItalicAngle);
+end;
+
+procedure TTestLiberationFont.TestPostScript_UnderlinePosition;
+begin
+  AssertEquals('Failed on 1', -217, FI.PostScript.UnderlinePosition);
+end;
+
+procedure TTestLiberationFont.TestPostScript_underlineThickness;
+begin
+  AssertEquals('Failed on 1', 150, FI.PostScript.underlineThickness);
+end;
+
+procedure TTestLiberationFont.TestPostScript_isFixedPitch;
+begin
+  AssertEquals('Failed on 1', 0, FI.PostScript.isFixedPitch);
+end;
+
+procedure TTestLiberationFont.TestPostScript_minMemType42;
+begin
+  AssertEquals('Failed on 1', 0, FI.PostScript.minMemType42);
+end;
+
+procedure TTestLiberationFont.TestPostScript_maxMemType42;
+begin
+  AssertEquals('Failed on 1', 0, FI.PostScript.maxMemType42);
+end;
+
+procedure TTestLiberationFont.TestPostScript_minMemType1;
+begin
+  AssertEquals('Failed on 1', 0, FI.PostScript.minMemType1);
+end;
+
+procedure TTestLiberationFont.TestPostScript_maxMemType1;
+begin
+  AssertEquals('Failed on 1', 0, FI.PostScript.maxMemType1);
+end;
+
+procedure TTestLiberationFont.TestPDFFontDefinition;
+var
+  Def: TPDFFontDefinition;
+  s: string;
+begin
+  FI.FillPDFFontDefinition(Def, cFont1, 'cp1252');
+  AssertEquals('Failed on 1', 'TrueType', Def.FontType);
+  AssertEquals('Failed on 2', 'LiberationSans', Def.FontName);
+  AssertEquals('Failed on 3', 728, Def.Ascender);
+  AssertEquals('Failed on 4', -210, Def.Descender);
+  AssertEquals('Failed on 5', 688, Def.CapHeight);
+  AssertEquals('Failed on 6', 32, Def.Flags);
+
+  s := IntToStr(Def.BBox[0]) + ' ' + IntToStr(Def.BBox[1]) + ' ' +
+        IntToStr(Def.BBox[2]) + ' ' + IntToStr(Def.BBox[3]);
+  AssertEquals('Failed on 7', '-544 -303 1302 980', s);
+
+  AssertEquals('Failed on 8', 0, Def.ItalicAngle);
+  AssertEquals('Failed on 9', 70, Def.StemV);
+  AssertEquals('Failed on 10', 0, Def.MissingWidth);
+  AssertEquals('Failed on 11', -106, Def.FontUp);
+  AssertEquals('Failed on 12', 73, Def.FontUt);
+  AssertEquals('Failed on 13', 'cp1252', Def.Encoding);
+  AssertEquals('Failed on 14', ReplaceStr(cFont1, '.ttf', '.z'), Def.FontFile); // 'fonts/LiberationSans-Regular.z'
+  AssertEquals('Failed on 15', '', Def.Diffs);
+
+  { CharWidths is only valid if we called MakePDFFontDef }
+//  AssertEquals('Failed on 16', '', Def.CharWidths);
+
+  AssertEquals('Failed on 17', 350200, Def.OriginalSize);
+end;
+
+procedure TTestLiberationFont.TestMakePDFFontDefinition;
+const
+  cSection = 'LiberationSans';
+var
+  lFile: string;
+  ini: TINIFile;
+begin
+  lFile := ChangeFileExt(GetTempFileName, '.ini');
+//  writeln( lFile);
+  AssertTrue('Failed on 1', FileExists(lFile) = False);
+  try
+    FI.MakePDFFontDef(lFile, 'cp1252', True);
+    AssertTrue('Failed on 2', FileExists(lFile) = True);
+    ini := TINIFile.Create(lFile);
+    try
+      AssertEquals('Failed on 3', 'TrueType', ini.ReadString(cSection, 'FontType', ''));
+      AssertEquals('Failed on 4', 'LiberationSans', ini.ReadString(cSection, 'FontName', ''));
+      AssertEquals('Failed on 5', 728, ini.ReadInteger(cSection, 'Ascent', 0));
+      AssertEquals('Failed on 6', -210, ini.ReadInteger(cSection, 'Descent', 0));
+      AssertEquals('Failed on 7', 688, ini.ReadInteger(cSection, 'CapHeight', 0));
+      AssertEquals('Failed on 8', 32, ini.ReadInteger(cSection, 'Flags', 0));
+      AssertEquals('Failed on 9', '-544 -303 1302 980', ini.ReadString(cSection, 'FontBBox', ''));
+      AssertEquals('Failed on 10', 0, ini.ReadInteger(cSection, 'ItalicAngle', 0));
+      AssertEquals('Failed on 11', 70, ini.ReadInteger(cSection, 'StemV', 0));
+      AssertEquals('Failed on 12', 569, ini.ReadInteger(cSection, 'MissingWidth', 0));
+      AssertEquals('Failed on 13', -106, ini.ReadInteger(cSection, 'FontUp', 0));
+      AssertEquals('Failed on 14', 73, ini.ReadInteger(cSection, 'FontUt', 0));
+      AssertEquals('Failed on 15', 'cp1252', ini.ReadString(cSection, 'Encoding', ''));
+      AssertEquals('Failed on 16', ReplaceStr(lFile, '.ini', '.z'), ini.ReadString(cSection, 'FontFile', ''));
+      AssertEquals('Failed on 17', '', ini.ReadString(cSection, 'Diffs', ''));
+      AssertTrue('Failed on 18', ini.ReadString(cSection, 'CharWidth', '') <> '');
+      AssertEquals('Failed on 19', 350200, ini.ReadInteger(cSection, 'OriginalSize', 0));
+    finally
+      ini.Free;
+    end;
+  finally
+    DeleteFile(lFile);
+  end
+end;
+
+procedure TTestLiberationFont.TestGetGlyphIndex;
+begin
+  AssertEquals('Failed on 1.1', 67, Ord('C'));
+  AssertEquals('Failed on 1.2', 111, Ord('o'));
+
+  AssertEquals('Failed on 2.1', 38, FI.GetGlyphIndex(Ord('C')));
+  AssertEquals('Failed on 2.2', 82, FI.GetGlyphIndex(Ord('o')));
+  AssertEquals('Failed on 2.3', 88, FI.GetGlyphIndex(Ord('u')));
+  AssertEquals('Failed on 2.4', 87, FI.GetGlyphIndex(Ord('t')));
+  AssertEquals('Failed on 2.5', 85, FI.GetGlyphIndex(Ord('r')));
+  AssertEquals('Failed on 2.6', 92, FI.GetGlyphIndex(Ord('y')));
+  AssertEquals('Failed on 2.7', 3, FI.GetGlyphIndex(Ord(' ')));
+  AssertEquals('Failed on 2.8', 51, FI.GetGlyphIndex(Ord('P')));
+  AssertEquals('Failed on 2.9', 80, FI.GetGlyphIndex(Ord('m')));
+  AssertEquals('Failed on 2.10', 79, FI.GetGlyphIndex(Ord('l')));
+  AssertEquals('Failed on 2.11', 19, FI.GetGlyphIndex(Ord('0')));
+  AssertEquals('Failed on 2.12', 20, FI.GetGlyphIndex(Ord('1')));
+end;
+
+procedure TTestLiberationFont.TestGetAdvanceWidth;
+begin
+  AssertEquals('Failed on 1', 1479, FI.GetAdvanceWidth(38));  // 'C'
+  AssertEquals('Failed on 2', 1139, FI.GetAdvanceWidth(82));  // 'o'
+  AssertEquals('Failed on 3', 1139, FI.GetAdvanceWidth(88));  // 'u'
+  AssertEquals('Failed on 4', 569, FI.GetAdvanceWidth(87));   // 't'
+  AssertEquals('Failed on 5', 682, FI.GetAdvanceWidth(85));   // 'r'
+  AssertEquals('Failed on 6', 1024, FI.GetAdvanceWidth(92));  // 'y'
+  AssertEquals('Failed on 7', 569, FI.GetAdvanceWidth(3));    // ' '
+  AssertEquals('Failed on 8', 1366, FI.GetAdvanceWidth(51));  // 'P'
+  AssertEquals('Failed on 9', 1706, FI.GetAdvanceWidth(80));  // 'm'
+  AssertEquals('Failed on 10', 455, FI.GetAdvanceWidth(79));  // 'l'
+  AssertEquals('Failed on 11', 1139, FI.GetAdvanceWidth(19));  // '0'
+  AssertEquals('Failed on 12', 1139, FI.GetAdvanceWidth(20));  // '1'
+end;
+
+{ TTestFreeSansFont }
+
+procedure TTestFreeSansFont.SetUp;
+begin
+  inherited SetUp;
+  AssertTrue('Failed to find TTF font file <' + cFont2 + '>' + LineEnding +
+    'You can download it from [http://ftp.gnu.org/gnu/freefont/freefont-ttf-20140503.zip]',
+    FileExists(cFont2) = True);
+  LoadFont(cFont2);
+end;
+
+procedure TTestFreeSansFont.TestDirectory_FontVersion;
+begin
+  AssertEquals('Failed on 0', '00010000', IntToHex(FI.Directory.FontVersion.Version, 8));
+  AssertEquals('Failed on Major Version', 1, FI.Directory.FontVersion.Major);
+  AssertEquals('Failed on Minor Version', 0, FI.Directory.FontVersion.Minor);
+end;
+
+procedure TTestFreeSansFont.TestDirectory_NumTables;
+begin
+  AssertEquals('Failed on Numtables', 19, Int(FI.Directory.Numtables));
+end;
+
+procedure TTestFreeSansFont.TestDirectory_SearchRange;
+begin
+  AssertEquals('Failed on SearchRange', 256, Int(FI.Directory.SearchRange));
+end;
+
+procedure TTestFreeSansFont.TestDirectory_EntrySelector;
+begin
+  AssertEquals('Failed on EntrySelector', 4, Int(FI.Directory.EntrySelector));
+end;
+
+procedure TTestFreeSansFont.TestDirectory_RangeShift;
+begin
+  AssertEquals('Failed on RangeShift', 48, Int(FI.Directory.RangeShift));
+end;
+
+procedure TTestFreeSansFont.TestHead_FileVersion;
+begin
+  AssertEquals('Failed on 1', '00010000', IntToHex(FI.Head.FileVersion.Version, 8));
+  AssertEquals('Failed on 2', 1, FI.Head.FileVersion.Major);
+  AssertEquals('Failed on 3', 0, FI.Head.FileVersion.Minor);
+end;
+
+procedure TTestFreeSansFont.TestHead_FontRevision;
+begin
+  { graemeg (2015-09-11): Microsoft's ttfdump tools says the version of this
+    font is 412.2 and Linux's FontForge says it is 412.2268. I'm making the
+    assumption that Microsoft's tool simply truncated the version number to
+    one decimal. }
+  AssertEquals('Failed on 1', 412, FI.Head.FontRevision.Major);
+  AssertEquals('Failed on 2', 2268, FI.Head.FontRevision.Minor);
+end;
+
+procedure TTestFreeSansFont.TestHead_CheckSumAdjustment;
+begin
+  AssertEquals('Failed on 1', $BDD896C1, FI.Head.CheckSumAdjustment);
+end;
+
+procedure TTestFreeSansFont.TestHead_MagicNumber;
+begin
+  AssertEquals('Failed on 1', $5F0F3CF5, FI.Head.MagicNumber);
+end;
+
+procedure TTestFreeSansFont.TestHead_Flags;
+begin
+  AssertEquals('Failed on 1', $021F, FI.Head.Flags);
+end;
+
+procedure TTestFreeSansFont.TestHead_UnitsPerEm;
+begin
+  AssertEquals('Failed on 1', 1000, FI.Head.UnitsPerEm);
+end;
+
+procedure TTestFreeSansFont.TestHead_Created;
+var
+  dt: TDateTime;
+  s: string;
+begin
+  // LONGDATETIME: Date represented in number of seconds since 12:00 midnight,
+  //              January 1, 1904. The value is represented as a signed 64-bit integer.
+  //dt := EncodeDateTime(1904, 1, 1, 0, 0, 0, 0);
+  //s := FormatDateTime('yyyy-mm-dd hh:nn:ss', dt);
+  //AssertEquals('Failed on 1', '1904-01-01 00:00:00', s);
+
+  //dt := IncSecond(dt, FI.Head.Created);
+
+  // The above code equates to using MacToDateTime()
+  dt := MacToDateTime(FI.Head.Created);
+
+  // We don't use this AssertEquals() because it shows a huge Double data-type
+  // value as the result.
+  //AssertEquals('Failed on 1', EncodeDateTime(2012, 10, 4, 20, 2, 31, 0), dt);
+
+  // Instead we use this - which shows human readable dates.
+  s := FormatDateTime('yyyy-mm-dd hh:nn:ss', dt);
+  AssertEquals('Failed on 2', '2012-05-02 22:34:25', s);
+end;
+
+procedure TTestFreeSansFont.TestHead_Modified;
+var
+  dt: TDateTime;
+  s: string;
+begin
+  dt := MacToDateTime(FI.Head.Modified);
+  s := FormatDateTime('yyyy-mm-dd hh:nn:ss', dt);
+  AssertEquals('Failed on 2', '2012-05-02 22:34:25', s);
+end;
+
+procedure TTestFreeSansFont.TestHead_BBox_xMin;
+begin
+  AssertEquals('Failed on 1', -1166, FI.Head.BBox[0]);
+end;
+
+procedure TTestFreeSansFont.TestHead_BBox_yMin;
+begin
+  AssertEquals('Failed on 1', -638, FI.Head.BBox[1]);
+end;
+
+procedure TTestFreeSansFont.TestHead_BBox_xMax;
+begin
+  AssertEquals('Failed on 1', 2260, FI.Head.BBox[2]);
+end;
+
+procedure TTestFreeSansFont.TestHead_BBox_yMax;
+begin
+  AssertEquals('Failed on 1', 1050, FI.Head.BBox[3]);
+end;
+
+procedure TTestFreeSansFont.TestHead_MacStyle;
+begin
+  AssertEquals('Failed on 1', $0000, FI.Head.MacStyle);
+end;
+
+procedure TTestFreeSansFont.TestHead_LowestRecPPEM;
+begin
+  AssertEquals('Failed on 1', 8, FI.Head.LowestRecPPEM);
+end;
+
+procedure TTestFreeSansFont.TestHead_FontDirectionHint;
+begin
+  AssertEquals('Failed on 1', 0, FI.Head.FontDirectionHint);
+end;
+
+procedure TTestFreeSansFont.TestHead_IndexToLocFormat;
+begin
+  AssertEquals('Failed on 1', 1, FI.Head.IndexToLocFormat);
+end;
+
+procedure TTestFreeSansFont.TestHead_glyphDataFormat;
+begin
+  AssertEquals('Failed on 1', 0, FI.Head.glyphDataFormat);
+end;
+
+procedure TTestFreeSansFont.TestHHead_TableVersion;
+begin
+  AssertEquals('Failed on 1', '00010000', IntToHex(FI.HHead.TableVersion.Version, 8));
+  AssertEquals('Failed on 2', 1, FI.HHead.TableVersion.Major);
+  AssertEquals('Failed on 3', 0, FI.HHead.TableVersion.Minor);
+end;
+
+procedure TTestFreeSansFont.TestHHead_Ascender;
+begin
+  AssertEquals('Failed on 1', 900, FI.HHead.Ascender);
+end;
+
+procedure TTestFreeSansFont.TestHHead_Descender;
+begin
+  AssertEquals('Failed on 1', -200, FI.HHead.Descender);
+end;
+
+procedure TTestFreeSansFont.TestHHead_LineGap;
+begin
+  AssertEquals('Failed on 1', 100, FI.HHead.LineGap);
+end;
+
+procedure TTestFreeSansFont.TestHHead_AdvanceWidthMax;
+begin
+  AssertEquals('Failed on 1', 2256, FI.HHead.AdvanceWidthMax);
+end;
+
+procedure TTestFreeSansFont.TestHHead_MinLeftSideBearing;
+begin
+  AssertEquals('Failed on 1', -1166, FI.HHead.MinLeftSideBearing);
+end;
+
+procedure TTestFreeSansFont.TestHHead_MinRightSideBearing;
+begin
+  AssertEquals('Failed on 1', -724, FI.HHead.MinRightSideBearing);
+end;
+
+procedure TTestFreeSansFont.TestHHead_XMaxExtent;
+begin
+  AssertEquals('Failed on 1', 2260, FI.HHead.XMaxExtent);
+end;
+
+procedure TTestFreeSansFont.TestHHead_CaretSlopeRise;
+begin
+  AssertEquals('Failed on 1', 1, FI.HHead.CaretSlopeRise);
+end;
+
+procedure TTestFreeSansFont.TestHHead_CaretSlopeRun;
+begin
+  AssertEquals('Failed on 1', 0, FI.HHead.CaretSlopeRun);
+end;
+
+procedure TTestFreeSansFont.TestHHead_Reserved;
+begin
+  AssertEquals('Failed on 1', 0, FI.HHead.Reserved[0]);
+  AssertEquals('Failed on 2', 0, FI.HHead.Reserved[1]);
+  AssertEquals('Failed on 3', 0, FI.HHead.Reserved[2]);
+  AssertEquals('Failed on 4', 0, FI.HHead.Reserved[3]);
+  AssertEquals('Failed on 5', 0, FI.HHead.Reserved[4]);
+end;
+
+procedure TTestFreeSansFont.TestHHead_metricDataFormat;
+begin
+  AssertEquals('Failed on 1', 0, FI.HHead.metricDataFormat);
+end;
+
+procedure TTestFreeSansFont.TestHHead_numberOfHMetrics;
+begin
+  AssertEquals('Failed on 1', 6272, FI.HHead.numberOfHMetrics);
+end;
+
+procedure TTestFreeSansFont.TestCMap_version;
+begin
+  AssertEquals('Failed on 1', '0000', IntToHex(FI.CmapH.Version, 4));
+  AssertEquals('Failed on 2', 0, FI.CmapH.Version);
+end;
+
+procedure TTestFreeSansFont.TestCMap_SubTableCount;
+begin
+  AssertEquals('Failed on 1', 5, FI.CmapH.SubTableCount);
+end;
+
+procedure TTestFreeSansFont.TestCMapSubTables_1;
+var
+  lSubTable: TCmapSubTableEntry;
+begin
+  lSubTable := FI.CmapSubtables[0];
+  AssertEquals('Failed on 1', 0, lSubTable.PlatformID);
+  AssertEquals('Failed on 2', 3, lSubTable.EncodingID);
+  AssertEquals('Failed on 3', '0000002C', IntToHex(lSubTable.Offset, 8));
+end;
+
+procedure TTestFreeSansFont.TestCMapSubTables_2;
+var
+  lSubTable: TCmapSubTableEntry;
+begin
+  lSubTable := FI.CmapSubtables[1];
+  AssertEquals('Failed on 1', 0, lSubTable.PlatformID);
+  AssertEquals('Failed on 2', 10, lSubTable.EncodingID);
+  AssertEquals('Failed on 3', '00000644', IntToHex(lSubTable.Offset, 8));
+end;
+
+procedure TTestFreeSansFont.TestCMapSubTables_3;
+var
+  lSubTable: TCmapSubTableEntry;
+begin
+  lSubTable := FI.CmapSubtables[2];
+  AssertEquals('Failed on 1', 1, lSubTable.PlatformID);
+  AssertEquals('Failed on 2', 0, lSubTable.EncodingID);
+  AssertEquals('Failed on 3', '00000FA8', IntToHex(lSubTable.Offset, 8));
+end;
+
+procedure TTestFreeSansFont.TestCMapSubTables_4;
+var
+  lSubTable: TCmapSubTableEntry;
+begin
+  lSubTable := FI.CmapSubtables[3];
+  AssertEquals('Failed on 1', 3, lSubTable.PlatformID);
+  AssertEquals('Failed on 2', 1, lSubTable.EncodingID);
+  AssertEquals('Failed on 3', '0000002C', IntToHex(lSubTable.Offset, 8));
+end;
+
+procedure TTestFreeSansFont.TestCMapSubTables_5;
+var
+  lSubTable: TCmapSubTableEntry;
+begin
+  lSubTable := FI.CmapSubtables[4];
+  AssertEquals('Failed on 1', 3, lSubTable.PlatformID);
+  AssertEquals('Failed on 2', 10, lSubTable.EncodingID);
+  AssertEquals('Failed on 3', '00000644', IntToHex(lSubTable.Offset, 8));
+end;
+
+procedure TTestFreeSansFont.TestCmapUnicodeMap_Format;
+begin
+  AssertEquals('Failed on 1', 4, FI.CmapUnicodeMap.Format);
+end;
+
+procedure TTestFreeSansFont.TestCmapUnicodeMap_Length;
+begin
+  AssertEquals('Failed on 1', 1560, FI.CmapUnicodeMap.Length);
+end;
+
+procedure TTestFreeSansFont.TestCmapUnicodeMap_SegmentCount2;
+begin
+  AssertEquals('Failed on 1', 386, FI.CmapUnicodeMap.SegmentCount2);
+end;
+
+procedure TTestFreeSansFont.TestCmapUnicodeMap_SearchRange;
+begin
+  AssertEquals('Failed on 1', 256, FI.CmapUnicodeMap.SearchRange);
+end;
+
+procedure TTestFreeSansFont.TestCmapUnicodeMap_EntrySelector;
+begin
+  AssertEquals('Failed on 1', 7, FI.CmapUnicodeMap.EntrySelector);
+end;
+
+procedure TTestFreeSansFont.TestCmapUnicodeMap_RangeShift;
+begin
+  AssertEquals('Failed on 1', 130, FI.CmapUnicodeMap.RangeShift);
+end;
+
+procedure TTestFreeSansFont.TestUnicodeMapSegment_1_StartCode;
+begin
+  AssertEquals('Failed on 1', '0020', IntToHex(FI.CmapUnicodeMapSegments[0].StartCode, 4));
+end;
+
+procedure TTestFreeSansFont.TestUnicodeMapSegment_1_EndCode;
+begin
+  AssertEquals('Failed on 1', '007E', IntToHex(FI.CmapUnicodeMapSegments[0].EndCode, 4));
+end;
+
+procedure TTestFreeSansFont.TestUnicodeMapSegment_1_IDDelta;
+begin
+  AssertEquals('Failed on 1', -29, FI.CmapUnicodeMapSegments[0].IDDelta);
+end;
+
+procedure TTestFreeSansFont.TestUnicodeMapSegment_1_IDRangeOffset;
+begin
+  AssertEquals('Failed on 1', 0, FI.CmapUnicodeMapSegments[0].IDRangeOffset);
+end;
+
+procedure TTestFreeSansFont.TestUnicodeMapSegment_2_StartCode;
+begin
+  AssertEquals('Failed on 1', '00A0', IntToHex(FI.CmapUnicodeMapSegments[1].StartCode, 4));
+end;
+
+procedure TTestFreeSansFont.TestUnicodeMapSegment_2_EndCode;
+begin
+  AssertEquals('Failed on 1', '01BB', IntToHex(FI.CmapUnicodeMapSegments[1].EndCode, 4));
+end;
+
+procedure TTestFreeSansFont.TestUnicodeMapSegment_2_IDDelta;
+begin
+  AssertEquals('Failed on 1', -62, FI.CmapUnicodeMapSegments[1].IDDelta);
+end;
+
+procedure TTestFreeSansFont.TestUnicodeMapSegment_2_IDRangeOffset;
+begin
+  AssertEquals('Failed on 1', 0, FI.CmapUnicodeMapSegments[1].IDRangeOffset);
+end;
+
+procedure TTestFreeSansFont.TestUnicodeMapSegment_127_StartCode;
+begin
+  AssertEquals('Failed on 1', '2190', IntToHex(FI.CmapUnicodeMapSegments[126].StartCode, 4));
+end;
+
+procedure TTestFreeSansFont.TestUnicodeMapSegment_127_EndCode;
+begin
+  AssertEquals('Failed on 1', '2199', IntToHex(FI.CmapUnicodeMapSegments[126].EndCode, 4));
+end;
+
+procedure TTestFreeSansFont.TestUnicodeMapSegment_127_IDDelta;
+begin
+  AssertEquals('Failed on 1', -5123, FI.CmapUnicodeMapSegments[126].IDDelta);
+end;
+
+procedure TTestFreeSansFont.TestUnicodeMapSegment_127_IDRangeOffset;
+begin
+  AssertEquals('Failed on 1', 0, FI.CmapUnicodeMapSegments[126].IDRangeOffset);
+end;
+
+procedure TTestFreeSansFont.TestWidths_Size;
+begin
+  AssertEquals('Failed on 1', 6272, Length(FI.Widths));
+end;
+
+procedure TTestFreeSansFont.TestWidths_HorMetric_0_AdvanceWidth;
+begin
+  AssertEquals('Failed on 1', 800, FI.Widths[0].AdvanceWidth);
+end;
+
+procedure TTestFreeSansFont.TestWidths_HorMetric_0_LSB;
+begin
+  AssertEquals('Failed on 1', 35, FI.Widths[0].LSB);
+end;
+
+procedure TTestFreeSansFont.TestWidths_HorMetric_1_AdvanceWidth;
+begin
+  AssertEquals('Failed on 1', 0, FI.Widths[1].AdvanceWidth);
+end;
+
+procedure TTestFreeSansFont.TestWidths_HorMetric_1_LSB;
+begin
+  AssertEquals('Failed on 1', 0, FI.Widths[1].LSB);
+end;
+
+procedure TTestFreeSansFont.TestWidths_HorMetric_2586_AdvanceWidth;
+begin
+  AssertEquals('Failed on 1', 516, FI.Widths[2586].AdvanceWidth);
+end;
+
+procedure TTestFreeSansFont.TestWidths_HorMetric_2586_LSB;
+begin
+  AssertEquals('Failed on 1', 50, FI.Widths[2586].LSB);
+end;
+
+procedure TTestFreeSansFont.TestMaxP_VersionNumber;
+begin
+  AssertEquals('Failed on 1', '00010000', IntToHex(FI.MaxP.VersionNumber.Version, 8));
+  AssertEquals('Failed on 2', 1, FI.MaxP.VersionNumber.Major);
+  AssertEquals('Failed on 3', 0, FI.MaxP.VersionNumber.Minor);
+end;
+
+procedure TTestFreeSansFont.TestMaxP_numGlyphs;
+begin
+  AssertEquals('Failed on 1', 6272, FI.MaxP.numGlyphs);
+end;
+
+procedure TTestFreeSansFont.TestMaxP_maxPoints;
+begin
+  AssertEquals('Failed on 1', 439, FI.MaxP.maxPoints);
+end;
+
+procedure TTestFreeSansFont.TestMaxP_maxContours;
+begin
+  AssertEquals('Failed on 1', 100, FI.MaxP.maxContours);
+end;
+
+procedure TTestFreeSansFont.TestMaxP_maxCompositePoints;
+begin
+  AssertEquals('Failed on 1', 117, FI.MaxP.maxCompositePoints);
+end;
+
+procedure TTestFreeSansFont.TestMaxP_maxCompositeContours;
+begin
+  AssertEquals('Failed on 1', 8, FI.MaxP.maxCompositeContours);
+end;
+
+procedure TTestFreeSansFont.TestMaxP_maxZones;
+begin
+  AssertEquals('Failed on 1', 2, FI.MaxP.maxZones);
+end;
+
+procedure TTestFreeSansFont.TestMaxP_maxTwilightPoints;
+begin
+  AssertEquals('Failed on 1', 1, FI.MaxP.maxTwilightPoints);
+end;
+
+procedure TTestFreeSansFont.TestMaxP_maxStorage;
+begin
+  AssertEquals('Failed on 1', 2, FI.MaxP.maxStorage);
+end;
+
+procedure TTestFreeSansFont.TestMaxP_maxFunctionDefs;
+begin
+  AssertEquals('Failed on 1', 22, FI.MaxP.maxFunctionDefs);
+end;
+
+procedure TTestFreeSansFont.TestMaxP_maxInstructionDefs;
+begin
+  AssertEquals('Failed on 1', 0, FI.MaxP.maxInstructionDefs);
+end;
+
+procedure TTestFreeSansFont.TestMaxP_maxStackElements;
+begin
+  AssertEquals('Failed on 1', 256, FI.MaxP.maxStackElements);
+end;
+
+procedure TTestFreeSansFont.TestMaxP_maxSizeOfInstructions;
+begin
+  AssertEquals('Failed on 1', 1424, FI.MaxP.maxSizeOfInstructions);
+end;
+
+procedure TTestFreeSansFont.TestMaxP_maxComponentElements;
+begin
+  AssertEquals('Failed on 1', 8, FI.MaxP.maxComponentElements);
+end;
+
+procedure TTestFreeSansFont.TestMaxP_maxComponentDepth;
+begin
+  AssertEquals('Failed on 1', 4, FI.MaxP.maxComponentDepth);
+end;
+
+procedure TTestFreeSansFont.TestOS2Data_version;
+begin
+  AssertEquals('Failed on 1', 3, FI.OS2Data.version);
+end;
+
+procedure TTestFreeSansFont.TestOS2Data_xAvgCharWidth;
+begin
+  AssertEquals('Failed on 1', 657, FI.OS2Data.xAvgCharWidth);
+end;
+
+procedure TTestFreeSansFont.TestOS2Data_usWeightClass;
+begin
+  AssertEquals('Failed on 1', 400, FI.OS2Data.usWeightClass);
+end;
+
+procedure TTestFreeSansFont.TestOS2Data_usWidthClass;
+begin
+  AssertEquals('Failed on 1', 5, FI.OS2Data.usWidthClass);
+end;
+
+procedure TTestFreeSansFont.TestOS2Data_fsType;
+begin
+  AssertEquals('Failed on 1', '0000', IntToHex(FI.OS2Data.fsType, 4));
+end;
+
+procedure TTestFreeSansFont.TestOS2Data_ySubscriptXSize;
+begin
+  AssertEquals('Failed on 1', 650, FI.OS2Data.ySubscriptXSize);
+end;
+
+procedure TTestFreeSansFont.TestOS2Data_ySubscriptYSize;
+begin
+  AssertEquals('Failed on 1', 666, FI.OS2Data.ySubscriptYSize);
+end;
+
+
+procedure TTestFreeSansFont.TestOS2Data_ySubscriptXOffset;
+begin
+  AssertEquals('Failed on 1', 0, FI.OS2Data.ySubscriptXOffset);
+end;
+
+
+procedure TTestFreeSansFont.TestOS2Data_ySubscriptYOffset;
+begin
+  AssertEquals('Failed on 1', 200, FI.OS2Data.ySubscriptYOffset);
+end;
+
+
+procedure TTestFreeSansFont.TestOS2Data_ySuperscriptXSize;
+begin
+  AssertEquals('Failed on 1', 650, FI.OS2Data.ySuperscriptXSize);
+end;
+
+
+procedure TTestFreeSansFont.TestOS2Data_ySuperscriptYSize;
+begin
+  AssertEquals('Failed on 1', 666, FI.OS2Data.ySuperscriptYSize);
+end;
+
+
+procedure TTestFreeSansFont.TestOS2Data_ySuperscriptXOffset;
+begin
+  AssertEquals('Failed on 1', 0, FI.OS2Data.ySuperscriptXOffset);
+end;
+
+
+procedure TTestFreeSansFont.TestOS2Data_ySuperscriptYOffset;
+begin
+  AssertEquals('Failed on 1', 390, FI.OS2Data.ySuperscriptYOffset);
+end;
+
+
+procedure TTestFreeSansFont.TestOS2Data_yStrikeoutSize;
+begin
+  AssertEquals('Failed on 1', 49, FI.OS2Data.yStrikeoutSize);
+end;
+
+
+procedure TTestFreeSansFont.TestOS2Data_yStrikeoutPosition;
+begin
+  AssertEquals('Failed on 1', 258, FI.OS2Data.yStrikeoutPosition);
+end;
+
+
+procedure TTestFreeSansFont.TestOS2Data_sFamilyClass;
+begin
+  AssertEquals('Failed on 1', 8, Hi(FI.OS2Data.sFamilyClass));
+  AssertEquals('Failed on 2', 5, Lo(FI.OS2Data.sFamilyClass));
+  AssertEquals('Failed on 3', '0805', IntToHex(FI.OS2Data.sFamilyClass, 4));
+end;
+
+procedure TTestFreeSansFont.TestOS2Data_Panose;
+begin
+  AssertEquals('Failed on 1', 2, FI.OS2Data.panose[0]);
+  AssertEquals('Failed on 2', 11, FI.OS2Data.panose[1]);
+  AssertEquals('Failed on 3', 5, FI.OS2Data.panose[2]);
+  AssertEquals('Failed on 4', 4, FI.OS2Data.panose[3]);
+  AssertEquals('Failed on 5', 2, FI.OS2Data.panose[4]);
+  AssertEquals('Failed on 6', 2, FI.OS2Data.panose[5]);
+  AssertEquals('Failed on 7', 2, FI.OS2Data.panose[6]);
+  AssertEquals('Failed on 8', 2, FI.OS2Data.panose[7]);
+  AssertEquals('Failed on 9', 2, FI.OS2Data.panose[8]);
+  AssertEquals('Failed on 10', 4, FI.OS2Data.panose[9]);
+end;
+
+procedure TTestFreeSansFont.TestOS2Data_ulUnicodeRange1;
+begin
+  AssertEquals('Failed on 1', 'E4839EFF', IntToHex(FI.OS2Data.ulUnicodeRange1, 8));
+end;
+
+procedure TTestFreeSansFont.TestOS2Data_ulUnicodeRange2;
+begin
+  AssertEquals('Failed on 1', '4600FDFF', IntToHex(FI.OS2Data.ulUnicodeRange2, 8));
+end;
+
+procedure TTestFreeSansFont.TestOS2Data_ulUnicodeRange3;
+begin
+  AssertEquals('Failed on 1', '000030A0', IntToHex(FI.OS2Data.ulUnicodeRange3, 8));
+end;
+
+procedure TTestFreeSansFont.TestOS2Data_ulUnicodeRange4;
+begin
+  AssertEquals('Failed on 1', '00000584', IntToHex(FI.OS2Data.ulUnicodeRange4, 8));
+end;
+
+procedure TTestFreeSansFont.TestOS2Data_achVendID;
+var
+  s: string;
+begin
+  s := FI.OS2Data.achVendID[0] + FI.OS2Data.achVendID[1] + FI.OS2Data.achVendID[2] +
+        FI.OS2Data.achVendID[3];
+  AssertEquals('Failed on 1', 'GNU ', s);
+end;
+
+procedure TTestFreeSansFont.TestOS2Data_fsSelection;
+begin
+  AssertEquals('Failed on 1', '0040', IntToHex(FI.OS2Data.fsSelection, 4));
+end;
+
+procedure TTestFreeSansFont.TestOS2Data_usFirstCharIndex;
+begin
+  AssertEquals('Failed on 1', '0020', IntToHex(FI.OS2Data.usFirstCharIndex, 4));
+end;
+
+procedure TTestFreeSansFont.TestOS2Data_usLastCharIndex;
+begin
+  AssertEquals('Failed on 1', 'FFFF', IntToHex(FI.OS2Data.usLastCharIndex, 4));
+end;
+
+procedure TTestFreeSansFont.TestOS2Data_sTypoAscender;
+begin
+  AssertEquals('Failed on 1', 800, FI.OS2Data.sTypoAscender);
+end;
+
+procedure TTestFreeSansFont.TestOS2Data_sTypoDescender;
+begin
+  AssertEquals('Failed on 1', -200, FI.OS2Data.sTypoDescender);
+end;
+
+procedure TTestFreeSansFont.TestOS2Data_sTypoLineGap;
+begin
+  AssertEquals('Failed on 1', 100, FI.OS2Data.sTypoLineGap);
+end;
+
+procedure TTestFreeSansFont.TestOS2Data_usWinAscent;
+begin
+  AssertEquals('Failed on 1', 900, FI.OS2Data.usWinAscent);
+end;
+
+procedure TTestFreeSansFont.TestOS2Data_usWinDescent;
+begin
+  AssertEquals('Failed on 1', 300, FI.OS2Data.usWinDescent);
+end;
+
+procedure TTestFreeSansFont.TestOS2Data_ulCodePageRange1;
+begin
+  AssertEquals('Failed on 1', '600001BF', IntToHex(FI.OS2Data.ulCodePageRange1, 8));
+end;
+
+procedure TTestFreeSansFont.TestOS2Data_ulCodePageRange2;
+begin
+  AssertEquals('Failed on 1', 'DFF70000', IntToHex(FI.OS2Data.ulCodePageRange2, 8));
+end;
+
+procedure TTestFreeSansFont.TestOS2Data_sxHeight;
+begin
+  AssertEquals('Failed on 1', 524, FI.OS2Data.sxHeight);
+end;
+
+procedure TTestFreeSansFont.TestOS2Data_sCapHeight;
+begin
+  AssertEquals('Failed on 1', 729, FI.OS2Data.sCapHeight);
+end;
+
+procedure TTestFreeSansFont.TestOS2Data_usDefaultChar;
+begin
+  AssertEquals('Failed on 1', '0000', IntToHex(FI.OS2Data.usDefaultChar, 4));
+end;
+
+procedure TTestFreeSansFont.TestOS2Data_usBreakChar;
+begin
+  AssertEquals('Failed on 1', '0020', IntToHex(FI.OS2Data.usBreakChar, 4));
+end;
+
+procedure TTestFreeSansFont.TestOS2Data_usMaxContext;
+begin
+  AssertEquals('Failed on 1', 10, FI.OS2Data.usMaxContext);
+end;
+
+procedure TTestFreeSansFont.TestPostScript_Format;
+begin
+  AssertEquals('Failed on 1', '00020000', IntToHex(FI.PostScript.Format.Version, 8));
+  AssertEquals('Failed on 2', 2, FI.PostScript.Format.Major);
+  AssertEquals('Failed on 3', 0, FI.PostScript.Format.Minor);
+end;
+
+procedure TTestFreeSansFont.TestPostScript_ItalicAngle;
+begin
+  AssertEquals('Failed on 1', 0.0, FI.PostScript.ItalicAngle);
+end;
+
+procedure TTestFreeSansFont.TestPostScript_UnderlinePosition;
+begin
+  AssertEquals('Failed on 1', -176, FI.PostScript.UnderlinePosition);
+end;
+
+procedure TTestFreeSansFont.TestPostScript_underlineThickness;
+begin
+  AssertEquals('Failed on 1', 50, FI.PostScript.underlineThickness);
+end;
+
+procedure TTestFreeSansFont.TestPostScript_isFixedPitch;
+begin
+  AssertEquals('Failed on 1', 0, FI.PostScript.isFixedPitch);
+end;
+
+procedure TTestFreeSansFont.TestPostScript_minMemType42;
+begin
+  AssertEquals('Failed on 1', 0, FI.PostScript.minMemType42);
+end;
+
+procedure TTestFreeSansFont.TestPostScript_maxMemType42;
+begin
+  AssertEquals('Failed on 1', 0, FI.PostScript.maxMemType42);
+end;
+
+procedure TTestFreeSansFont.TestPostScript_minMemType1;
+begin
+  AssertEquals('Failed on 1', 0, FI.PostScript.minMemType1);
+end;
+
+procedure TTestFreeSansFont.TestPostScript_maxMemType1;
+begin
+  AssertEquals('Failed on 1', 0, FI.PostScript.maxMemType1);
+end;
+
+procedure TTestFreeSansFont.TestPDFFontDefinition;
+var
+  Def: TPDFFontDefinition;
+  s: string;
+begin
+  FI.FillPDFFontDefinition(Def, cFont1, 'cp1252');
+  AssertEquals('Failed on 1', 'TrueType', Def.FontType);
+  AssertEquals('Failed on 2', 'FreeSans', Def.FontName);
+  AssertEquals('Failed on 3', 800, Def.Ascender);
+  AssertEquals('Failed on 4', -200, Def.Descender);
+  AssertEquals('Failed on 5', 729, Def.CapHeight);
+  AssertEquals('Failed on 6', 32, Def.Flags);
+
+  s := IntToStr(Def.BBox[0]) + ' ' + IntToStr(Def.BBox[1]) + ' ' +
+        IntToStr(Def.BBox[2]) + ' ' + IntToStr(Def.BBox[3]);
+  AssertEquals('Failed on 7', '-1166 -638 2260 1050', s);
+
+  AssertEquals('Failed on 8', 0, Def.ItalicAngle);
+  AssertEquals('Failed on 9', 70, Def.StemV);
+  AssertEquals('Failed on 10', 0, Def.MissingWidth);
+  AssertEquals('Failed on 11', -176, Def.FontUp);
+  AssertEquals('Failed on 12', 50, Def.FontUt);
+  AssertEquals('Failed on 13', 'cp1252', Def.Encoding);
+  AssertEquals('Failed on 14', ReplaceStr(cFont1, '.ttf', '.z'), Def.FontFile); // 'fonts/LiberationSans-Regular.z'
+  AssertEquals('Failed on 15', '', Def.Diffs);
+
+  { CharWidths is only valid if we called MakePDFFontDef }
+//  AssertEquals('Failed on 16', '', Def.CharWidths);
+
+  AssertEquals('Failed on 17', 1563256, Def.OriginalSize);
+end;
+
+procedure TTestFreeSansFont.TestMakePDFFontDefinition;
+const
+  cSection = 'FreeSans';
+var
+  lFile: string;
+  ini: TINIFile;
+begin
+  lFile := ChangeFileExt(GetTempFileName, '.ini');
+//  writeln( lFile);
+  AssertTrue('Failed on 1', FileExists(lFile) = False);
+  try
+    FI.MakePDFFontDef(lFile, 'cp1252', True);
+    AssertTrue('Failed on 2', FileExists(lFile) = True);
+    ini := TINIFile.Create(lFile);
+    try
+      AssertEquals('Failed on 3', 'TrueType', ini.ReadString(cSection, 'FontType', ''));
+      AssertEquals('Failed on 4', 'FreeSans', ini.ReadString(cSection, 'FontName', ''));
+      AssertEquals('Failed on 5', 800, ini.ReadInteger(cSection, 'Ascent', 0));
+      AssertEquals('Failed on 6', -200, ini.ReadInteger(cSection, 'Descent', 0));
+      AssertEquals('Failed on 7', 729, ini.ReadInteger(cSection, 'CapHeight', 0));
+      AssertEquals('Failed on 8', 32, ini.ReadInteger(cSection, 'Flags', 0));
+      AssertEquals('Failed on 9', '-1166 -638 2260 1050', ini.ReadString(cSection, 'FontBBox', ''));
+      AssertEquals('Failed on 10', 0, ini.ReadInteger(cSection, 'ItalicAngle', 0));
+      AssertEquals('Failed on 11', 70, ini.ReadInteger(cSection, 'StemV', 0));
+      AssertEquals('Failed on 12', 250, ini.ReadInteger(cSection, 'MissingWidth', 0));
+      AssertEquals('Failed on 13', -176, ini.ReadInteger(cSection, 'FontUp', 0));
+      AssertEquals('Failed on 14', 50, ini.ReadInteger(cSection, 'FontUt', 0));
+      AssertEquals('Failed on 15', 'cp1252', ini.ReadString(cSection, 'Encoding', ''));
+      AssertEquals('Failed on 16', ReplaceStr(lFile, '.ini', '.z'), ini.ReadString(cSection, 'FontFile', ''));
+      AssertEquals('Failed on 17', '', ini.ReadString(cSection, 'Diffs', ''));
+      AssertTrue('Failed on 18', ini.ReadString(cSection, 'CharWidth', '') <> '');
+      AssertEquals('Failed on 19', 1563256, ini.ReadInteger(cSection, 'OriginalSize', 0));
+    finally
+      ini.Free;
+    end;
+  finally
+    DeleteFile(lFile);
+  end
+end;
+
+
+
+
+initialization
+  RegisterTest(TTestEmptyParseTTF{$ifdef fptest}.Suite{$endif});
+  RegisterTest(TTestLiberationFont{$ifdef fptest}.Suite{$endif});
+  RegisterTest(TTestFreeSansFont{$ifdef fptest}.Suite{$endif});
+
+end.
+

+ 1655 - 0
packages/fcl-pdf/tests/fppdf_test.pas

@@ -0,0 +1,1655 @@
+unit fppdf_test;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils
+  {$ifdef fptest}
+  ,TestFramework
+  {$else}
+  ,fpcunit, testutils, testregistry
+  {$endif}
+  ,fppdf
+  ;
+
+type
+
+  TBasePDFTest = class(TTestCase)
+  private
+    FPDF: TPDFDocument;
+    FStream: TStringStream;
+  protected
+    procedure   SetUp; override;
+    procedure   TearDown; override;
+  public
+    property    PDF: TPDFDocument read FPDF;
+    property    S: TStringStream read FStream;
+  end;
+
+
+  TTestPDFObject = class(TBasePDFTest)
+  published
+    procedure   TestFloatStr;
+    procedure   TestWriteString;
+  end;
+
+
+  TTestTPDFDocumentObject = class(TBasePDFTest)
+  published
+    procedure   TestSetWidth;
+  end;
+
+
+  TTestPDFBoolean = class(TBasePDFTest)
+  published
+    procedure   TestWriteTrue;
+    procedure   TestWriteFalse;
+  end;
+
+
+  TTestPDFMoveTo = class(TBasePDFTest)
+  published
+    procedure   TestCommandPDFFloat;
+    procedure   TestCommandPDFCoord;
+  end;
+
+
+  TTestPDFInteger = class(TBasePDFTest)
+  published
+    procedure   TestWrite;
+  end;
+
+
+  TTestPDFReference = class(TBasePDFTest)
+  published
+    procedure   TestWrite;
+  end;
+
+
+  TTestPDFName = class(TBasePDFTest)
+  published
+    procedure   TestWrite;
+    procedure   TestValidNames1;
+    procedure   TestValidNames2;
+  end;
+
+
+  TTestPDFString = class(TBasePDFTest)
+  published
+    procedure   TestWrite;
+    procedure   TestWriteEscaped;
+    procedure   TestWriteEscaped2;
+  end;
+
+
+  TTestPDFArray = class(TBasePDFTest)
+  published
+    procedure   TestWrite;
+  end;
+
+
+  TTestPDFStream = class(TBasePDFTest)
+  published
+    procedure   TestWrite;
+  end;
+
+
+  TTestPDFEmbeddedFont = class(TBasePDFTest)
+  published
+    procedure   TestWrite;
+    procedure   TestWriteEmbeddedFont;
+  end;
+
+
+  TTestPDFText = class(TBasePDFTest)
+  published
+    procedure   TestWrite;
+  end;
+
+
+  TTestPDFLineSegment = class(TBasePDFTest)
+  published
+    procedure   TestCommand;
+    procedure   TestWrite;
+  end;
+
+
+  TTestTPDFRectangle = class(TBasePDFTest)
+  published
+    procedure   TestWrite_NoFill_NoStroke;
+    procedure   TestWrite_Fill_Stroke;
+    procedure   TestWrite_NoFill_Stroke;
+    procedure   TestWrite_Fill_NoStroke;
+  end;
+
+
+  TTestPDFCurveC = class(TBasePDFTest)
+  published
+    procedure   TestCommand;
+    procedure   TestWrite_Stroke;
+    procedure   TestWrite_NoStroke;
+  end;
+
+
+  TTestPDFCurveV = class(TBasePDFTest)
+  published
+    procedure   TestWrite_Stroke;
+    procedure   TestWrite_NoStroke;
+  end;
+
+
+  TTestPDFCurveY = class(TBasePDFTest)
+  published
+    procedure   TestWrite_Stroke;
+    procedure   TestWrite_NoStroke;
+  end;
+
+
+  TTestPDFEllipse = class(TBasePDFTest)
+  published
+    procedure   TestWrite_NoFill_NoStroke;
+    procedure   TestWrite_Fill_NoStroke;
+    procedure   TestWrite_NoFill_Stroke;
+    procedure   TestWrite_Fill_Stroke;
+  end;
+
+
+  TTestPDFSurface = class(TBasePDFTest)
+  published
+    procedure   TestWrite;
+    procedure   TestWrite_noFill;
+    procedure   TestWrite_noClose;
+  end;
+
+
+  TTestPDFImage = class(TBasePDFTest)
+  published
+    procedure   TestWrite;
+  end;
+
+
+  TTestPDFLineStyle = class(TBasePDFTest)
+  published
+    procedure   TestWrite_ppsSolid;
+    procedure   TestWrite_ppsDash;
+    procedure   TestWrite_ppsDot;
+    procedure   TestWrite_ppsDashDot;
+    procedure   TestWrite_ppsDashDotDot;
+  end;
+
+
+  TTestPDFColor = class(TBasePDFTest)
+  published
+    procedure   TestWrite_Stroke;
+    procedure   TestWrite_noStroke;
+  end;
+
+
+  TTestPDFDictionaryItem = class(TBasePDFTest)
+  published
+    procedure   TestWrite;
+  end;
+
+
+  TTestPDFDictionary = class(TBasePDFTest)
+  published
+    procedure   TestWrite;
+  end;
+
+
+  TTestPDFXRef = class(TBasePDFTest)
+  published
+    procedure   TestWrite;
+  end;
+
+
+  TTestPDFPage = class(TBasePDFTest)
+  published
+    procedure   TestPageDocument;
+    procedure   TestPageDefaultUnitOfMeasure;
+    procedure   TestMatrix;
+    procedure   TestUnitOfMeasure_MM;
+    procedure   TestUnitOfMeasure_Inches;
+    procedure   TestUnitOfMeasure_CM;
+  end;
+
+
+  TTestCompressionDecompression = class(TTestCase)
+  private
+    function  GetTestString: string;
+  published
+    procedure TestStreamCompressionDecompression;
+    procedure TestStringCompressionDecompression;
+  end;
+
+
+  TTestTPDFImageItem = class(TTestCase)
+  published
+    procedure TestCreateStreamedData;
+  end;
+
+implementation
+
+uses
+  FPImage;
+
+type
+  // so we can access Protected methods in the tests
+  TMockPDFObject = class(TPDFObject);
+  TMockPDFDocumentObject = class(TPDFDocumentObject);
+  TMockPDFBoolean = class(TPDFBoolean);
+  TMockPDFMoveTo = class(TPDFMoveTo);
+  TMockPDFInteger = class(TPDFInteger);
+  TMockPDFReference = class(TPDFReference);
+  TMockPDFName = class(TPDFName);
+  TMockPDFString = class(TPDFString);
+  TMockPDFArray = class(TPDFArray);
+  TMockPDFStream = class(TPDFStream);
+  TMockPDFEmbeddedFont = class(TPDFEmbeddedFont);
+  TMockPDFText = class(TPDFText);
+  TMockPDFLineSegment = class(TPDFLineSegment);
+  TMockPDFRectangle = class(TPDFRectangle);
+  TMockPDFCurveC = class(TPDFCurveC);
+  TMockPDFCurveV = class(TPDFCurveV);
+  TMockPDFCurveY = class(TPDFCurveY);
+  TMockPDFEllipse = class(TPDFEllipse);
+  TMockPDFSurface = class(TPDFSurface);
+  TMockPDFImage = class(TPDFImage);
+  TMockPDFLineStyle = class(TPDFLineStyle);
+  TMockPDFColor = class(TPDFColor);
+  TMockPDFDictionaryItem = class(TPDFDictionaryItem);
+  TMockPDFDictionary = class(TPDFDictionary);
+  TMockPDFXRef = class(TPDFXRef);
+  TMockPDFPage = class(TPDFPage);
+
+
+{ TBasePDFTest }
+
+procedure TBasePDFTest.SetUp;
+begin
+  inherited SetUp;
+  FPDF := TPDFDocument.Create(nil);
+  FStream := TStringStream.Create('');
+end;
+
+procedure TBasePDFTest.TearDown;
+begin
+  FStream.Free;
+  FPDF.Free;
+  inherited TearDown;
+end;
+
+{ TTestPDFObject }
+
+procedure TTestPDFObject.TestFloatStr;
+begin
+  AssertEquals('Failed on 1', '0.12', TMockPDFObject.FloatStr(TPDFFLoat(0.12)));
+  AssertEquals('Failed on 2', '12', TMockPDFObject.FloatStr(TPDFFLoat(12.00)));
+  AssertEquals('Failed on 3', '12.3', TMockPDFObject.FloatStr(TPDFFLoat(12.30)));
+  AssertEquals('Failed on 4', '12.34', TMockPDFObject.FloatStr(TPDFFLoat(12.34)));
+end;
+
+procedure TTestPDFObject.TestWriteString;
+var
+  o: TMockPDFObject;
+begin
+  o := TMockPDFObject.Create(PDF);
+  try
+    o.WriteString('Hello', S);
+    AssertEquals('Failed on 1', 'Hello', s.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+{ TTestTPDFDocumentObject }
+
+procedure TTestTPDFDocumentObject.TestSetWidth;
+var
+  o: TMockPDFDocumentObject;
+begin
+  o := TMockPDFDocumentObject.Create(PDF);
+  try
+    o.SetWidth(TPDFFloat(300.5), S);
+    AssertEquals('Failed on 1',
+      '1 J'+CRLF+
+      '300.5 w'+CRLF,             // line width
+      s.DataString);
+
+    // this shouldn't cause any change
+    o.SetWidth(TPDFFloat(300.5), S);
+    AssertEquals('Failed on 1',
+      '1 J'+CRLF+
+      '300.5 w'+CRLF,             // line width
+      s.DataString);
+
+    // but this will
+    o.SetWidth(TPDFFloat(123), S);
+    AssertEquals('Failed on 1',
+      '1 J'+CRLF+
+      '300.5 w'+CRLF+           // line width 300.5
+      '1 J'+CRLF+
+      '123 w'+CRLF,             // line width 123
+      s.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+{ TTestPDFBoolean }
+
+procedure TTestPDFBoolean.TestWriteTrue;
+var
+  o: TPDFBoolean;
+begin
+  o := TPDFBoolean.Create(PDF, True);
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    TMockPDFBoolean(o).Write(S);
+    AssertEquals('Failed on 2', 'true', S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+procedure TTestPDFBoolean.TestWriteFalse;
+var
+  o: TPDFBoolean;
+begin
+  o := TPDFBoolean.Create(PDF, False);
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    TMockPDFBoolean(o).Write(S);
+    AssertEquals('Failed on 2', 'false', S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+{ TTestPDFMoveTo }
+
+procedure TTestPDFMoveTo.TestCommandPDFFloat;
+var
+  o: TPDFMoveTo;
+begin
+  o := TPDFMoveTo.Create(PDF, 10, 20);
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    TMockPDFMoveTo(o).Write(S);
+    AssertEquals('Failed on 2', '10 20 m'+CRLF, S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+procedure TTestPDFMoveTo.TestCommandPDFCoord;
+var
+  c: TPDFCoord;
+  o: TPDFMoveTo;
+begin
+  c.X := 10;
+  c.Y := 20;
+  o := TPDFMoveTo.Create(PDF, c);
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    TMockPDFMoveTo(o).Write(S);
+    AssertEquals('Failed on 2', '10 20 m'+CRLF, S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+{ TTestPDFInteger }
+
+procedure TTestPDFInteger.TestWrite;
+var
+  o: TPDFInteger;
+begin
+  o := TPDFInteger.Create(PDF, 15);
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    TMockPDFInteger(o).Write(S);
+    AssertEquals('Failed on 2', '15', S.DataString);
+    TMockPDFInteger(o).inc;
+    TMockPDFInteger(o).Write(S);
+    AssertEquals('Failed on 3', '1516', S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+{ TTestPDFReference }
+
+procedure TTestPDFReference.TestWrite;
+var
+  o: TPDFReference;
+begin
+  o := TPDFReference.Create(PDF, 10);
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    TMockPDFReference(o).Write(S);
+    AssertEquals('Failed on 2', '10 0 R', S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+{ TTestPDFName }
+
+procedure TTestPDFName.TestWrite;
+var
+  o: TPDFName;
+begin
+  o := TPDFName.Create(PDF, 'Test');
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    TMockPDFName(o).Write(S);
+    AssertEquals('Failed on 2', '/Test', S.DataString);
+  finally
+    o.Free;
+  end;
+
+  { Length1 seems to be a special case? }
+  o := TPDFName.Create(PDF, 'Length1');
+  try
+    TMockPDFName(o).Write(S);
+    AssertEquals('Failed on 2', '/Test/Length1', S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+procedure TTestPDFName.TestValidNames1;
+var
+  o: TPDFName;
+begin
+  o := TPDFName.Create(PDF, 'paired()parentheses');
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    TMockPDFName(o).Write(S);
+    AssertEquals('Failed on 2', '/paired()parentheses', S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+procedure TTestPDFName.TestValidNames2;
+var
+  o: TPDFName;
+begin
+  o := TPDFName.Create(PDF, 'Adobe Green');
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    TMockPDFName(o).Write(S);
+    AssertEquals('Failed on 2', '/Adobe Green', S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+
+{ TTestPDFString }
+
+procedure TTestPDFString.TestWrite;
+var
+  o: TPDFString;
+begin
+  PDF.Options := []; // disable all compression
+  o := TPDFString.Create(PDF, 'Test');
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    TMockPDFString(o).Write(S);
+    AssertEquals('Failed on 2', '(Test)', S.DataString);
+  finally
+    o.Free;
+  end;
+
+  { Length1 seems to be a special case? }
+  o := TPDFString.Create(PDF, #$C2#$A3+#$C2#$BB); //  UTF-8 text of "£»"
+  try
+    TMockPDFString(o).Write(S);  // write will convert UTF-8 to ANSI
+    AssertEquals('Failed on 3', '(Test)('+#163#187+')', S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+{ The symbols ( ) and \ get escaped before written to PDF }
+procedure TTestPDFString.TestWriteEscaped;
+var
+  o: TPDFString;
+begin
+  o := TPDFString.Create(PDF, 'a(b)c\def/g');
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    TMockPDFString(o).Write(S);
+    AssertEquals('Failed on 2', '(a\(b\)c\\def/g)', S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+procedure TTestPDFString.TestWriteEscaped2;
+var
+  o: TPDFString;
+begin
+  o := TPDFString.Create(PDF, 'Special characters (*!&}^% and so on).');
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    TMockPDFString(o).Write(S);
+    AssertEquals('Failed on 2', '(Special characters \(*!&}^% and so on\).)', S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+{ TTestPDFArray }
+
+procedure TTestPDFArray.TestWrite;
+var
+  o: TPDFArray;
+begin
+  o := TPDFArray.Create(PDF);
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    TMockPDFArray(o).AddIntArray('1 2 3 4');  // no trailing space in string
+    TMockPDFArray(o).Write(S);
+    AssertEquals('Failed on 2', '[1 2 3 4]', S.DataString);
+
+    TMockPDFArray(o).AddIntArray('1 2 3 4 ');  // now we have a trailing space
+    TMockPDFArray(o).Write(S);
+    AssertEquals('Failed on 3', '[1 2 3 4][1 2 3 4 1 2 3 4]', S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+{ TTestPDFStream }
+
+procedure TTestPDFStream.TestWrite;
+var
+  o: TPDFStream;
+begin
+  o := TPDFStream.Create(PDF, True);
+  try
+    TMockPDFStream(o).AddItem(TPDFString.Create(PDF, 'Hello World'));
+    AssertEquals('Failed on 1', '', S.DataString);
+    TMockPDFStream(o).Write(S);
+    AssertEquals('Failed on 2', '(Hello World)', S.DataString);
+    TMockPDFStream(o).AddItem(TPDFString.Create(PDF, '12345'));
+    TMockPDFStream(o).Write(S);
+    AssertEquals('Failed on 3', '(Hello World)(Hello World)(12345)', S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+{ TTestPDFEmbeddedFont }
+
+procedure TTestPDFEmbeddedFont.TestWrite;
+var
+  o: TPDFEmbeddedFont;
+begin
+  o := TPDFEmbeddedFont.Create(PDF, 1, '16');
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    TMockPDFEmbeddedFont(o).Write(S);
+    AssertEquals('Failed on 2', '/F1 16 Tf'+CRLF, S.DataString);  // DON't change CRLF to anything else
+  finally
+    o.Free;
+  end;
+end;
+
+procedure TTestPDFEmbeddedFont.TestWriteEmbeddedFont;
+var
+  o: TPDFEmbeddedFont;
+  lStream: TMemoryStream;
+  str: String;
+begin
+  PDF.Options := []; // disable compressed fonts
+  str := 'Hello World';
+  o := TPDFEmbeddedFont.Create(PDF, 1, '16');
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    lStream := TMemoryStream.Create;
+    lStream.Write(str[1], Length(str));
+    TMockPDFEmbeddedFont(o).WriteEmbeddedFont(PDF, lStream, S);
+    lStream.Free;
+    // DON't change CRLF to anything else
+    AssertEquals('Failed on 2', CRLF+'stream'+CRLF+'Hello World'+CRLF+'endstream', S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+{ TTestPDFText }
+
+procedure TTestPDFText.TestWrite;
+var
+  o: TPDFText;
+  x, y: TPDFFloat;
+begin
+  x := 10.5;
+  y := 20.0;
+  o := TPDFText.Create(PDF, x, y, 'Hello World!');
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    TMockPDFText(o).Write(S);
+    AssertEquals('Failed on 2',
+      'BT'+CRLF+
+      '10.5 20 TD'+CRLF+
+      '(Hello World!) Tj'+CRLF+
+      'ET'+CRLF,
+      S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+{ TTestPDFLineSegment }
+
+procedure TTestPDFLineSegment.TestCommand;
+var
+  pos: TPDFCoord;
+begin
+  pos.X := 10.0;
+  pos.Y := 55.5;
+  AssertEquals('Failed on 1', '10 55.5 l'+CRLF, TPDFLineSegment.Command(pos));
+end;
+
+procedure TTestPDFLineSegment.TestWrite;
+var
+  o: TPDFLineSegment;
+  Width, X1,Y1, X2,Y2: TPDFFLoat;
+begin
+  Width := 2.0;
+  X1 := 10.0;
+  Y1 := 15.5;
+  X2 := 50.0;
+  Y2 := 55.5;
+  o := TPDFLineSegment.Create(PDF, Width, X1, Y1, X2, Y2);
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    TMockPDFLineSegment(o).Write(S);
+    AssertEquals('Failed on 2',
+      '1 J'+CRLF+
+      '2 w'+CRLF+             // line width
+      '10 15.5 m'+CRLF+       // moveto command
+      '50 55.5 l'+CRLF+       // line segment
+      'S'+CRLF,               // end line segment
+      S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+{ TTestTPDFRectangle }
+
+procedure TTestTPDFRectangle.TestWrite_NoFill_NoStroke;
+var
+  o: TMockPDFRectangle;
+  lPosX, lPosY, lWidth, lHeight, lLineWidth: TPDFFLoat;
+begin
+  lPosX := 10;
+  lPosY := 11;
+  lWidth := 100;
+  lHeight := 200;
+  lLineWidth := 1;
+  o := TMockPDFRectangle.Create(PDF, lPosX, lPosY, lWidth, lHeight, lLineWidth, False, False);
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    o.Write(S);
+    AssertEquals('Failed on 2',
+      '10 11 100 200 re'+CRLF,
+      S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+procedure TTestTPDFRectangle.TestWrite_Fill_Stroke;
+var
+  o: TMockPDFRectangle;
+  lPosX, lPosY, lWidth, lHeight, lLineWidth: TPDFFLoat;
+begin
+  lPosX := 10;
+  lPosY := 11;
+  lWidth := 100;
+  lHeight := 200;
+  lLineWidth := 2;
+  o := TMockPDFRectangle.Create(PDF, lPosX, lPosY, lWidth, lHeight, lLineWidth, True, True);
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    o.Write(S);
+    AssertEquals('Failed on 2',
+      '1 J'+CRLF+
+      '2 w'+CRLF+
+      '10 11 100 200 re'+CRLF+
+      'b'+CRLF,
+      S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+procedure TTestTPDFRectangle.TestWrite_NoFill_Stroke;
+var
+  o: TMockPDFRectangle;
+  lPosX, lPosY, lWidth, lHeight, lLineWidth: TPDFFLoat;
+begin
+  lPosX := 10;
+  lPosY := 11;
+  lWidth := 100;
+  lHeight := 200;
+  lLineWidth := 2;
+  o := TMockPDFRectangle.Create(PDF, lPosX, lPosY, lWidth, lHeight, lLineWidth, False, True);
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    o.Write(S);
+    AssertEquals('Failed on 2',
+      '1 J'+CRLF+
+      '2 w'+CRLF+
+      '10 11 100 200 re'+CRLF+
+      'S'+CRLF,
+      S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+procedure TTestTPDFRectangle.TestWrite_Fill_NoStroke;
+var
+  o: TMockPDFRectangle;
+  lPosX, lPosY, lWidth, lHeight, lLineWidth: TPDFFLoat;
+begin
+  lPosX := 10;
+  lPosY := 11;
+  lWidth := 100;
+  lHeight := 200;
+  lLineWidth := 2;
+  o := TMockPDFRectangle.Create(PDF, lPosX, lPosY, lWidth, lHeight, lLineWidth, True, False);
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    o.Write(S);
+    AssertEquals('Failed on 2',
+      '10 11 100 200 re'+CRLF+
+      'f'+CRLF,
+      S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+{ TTestPDFCurveC }
+
+procedure TTestPDFCurveC.TestCommand;
+var
+  X1,Y1: TPDFFloat;
+  X2,Y2: TPDFFloat;
+  X3,Y3: TPDFFloat;
+  s1: string;
+begin
+  X1 := 10;
+  Y1 := 11;
+  X2 := 100;
+  Y2 := 9;
+  X3 := 200;
+  Y3 := 250;
+  s1 := TMockPDFCurveC.Command(x1, y1, x2, y2, x3, y3);
+  AssertEquals('Failed on 1', '10 11 100 9 200 250 c'+CRLF, s1);
+end;
+
+procedure TTestPDFCurveC.TestWrite_Stroke;
+var
+  o: TMockPDFCurveC;
+  X1,Y1: TPDFFloat;
+  X2,Y2: TPDFFloat;
+  X3,Y3: TPDFFloat;
+  lLineWidth: TPDFFLoat;
+begin
+  X1 := 10;
+  Y1 := 11;
+  X2 := 100;
+  Y2 := 9;
+  X3 := 200;
+  Y3 := 250;
+  lLineWidth := 2;
+  o := TMockPDFCurveC.Create(PDF, x1, y1, x2, y2, x3, y3, lLineWidth, True);
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    o.Write(S);
+    AssertEquals('Failed on 2',
+      '1 J'+CRLF+
+      '2 w'+CRLF+
+      '10 11 100 9 200 250 c'+CRLF+
+      'S'+CRLF,
+      S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+procedure TTestPDFCurveC.TestWrite_NoStroke;
+var
+  o: TMockPDFCurveC;
+  X1,Y1: TPDFFloat;
+  X2,Y2: TPDFFloat;
+  X3,Y3: TPDFFloat;
+  lLineWidth: TPDFFLoat;
+begin
+  X1 := 10;
+  Y1 := 11;
+  X2 := 100;
+  Y2 := 9;
+  X3 := 200;
+  Y3 := 250;
+  lLineWidth := 2;
+  o := TMockPDFCurveC.Create(PDF, x1, y1, x2, y2, x3, y3, lLineWidth, False);
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    o.Write(S);
+    AssertEquals('Failed on 2',
+      '10 11 100 9 200 250 c'+CRLF,
+      S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+{ TTestPDFCurveV }
+
+procedure TTestPDFCurveV.TestWrite_Stroke;
+var
+  o: TMockPDFCurveV;
+  X2,Y2: TPDFFloat;
+  X3,Y3: TPDFFloat;
+  lLineWidth: TPDFFLoat;
+begin
+  X2 := 100;
+  Y2 := 9;
+  X3 := 200;
+  Y3 := 250;
+  lLineWidth := 2;
+  o := TMockPDFCurveV.Create(PDF, x2, y2, x3, y3, lLineWidth, True);
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    o.Write(S);
+    AssertEquals('Failed on 2',
+      '1 J'+CRLF+
+      '2 w'+CRLF+
+      '100 9 200 250 v'+CRLF+
+      'S'+CRLF,
+      S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+procedure TTestPDFCurveV.TestWrite_NoStroke;
+var
+  o: TMockPDFCurveV;
+  X2,Y2: TPDFFloat;
+  X3,Y3: TPDFFloat;
+  lLineWidth: TPDFFLoat;
+begin
+  X2 := 100;
+  Y2 := 9;
+  X3 := 200;
+  Y3 := 250;
+  lLineWidth := 2;
+  o := TMockPDFCurveV.Create(PDF, x2, y2, x3, y3, lLineWidth, False);
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    o.Write(S);
+    AssertEquals('Failed on 2',
+      '100 9 200 250 v'+CRLF,
+      S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+{ TTestPDFCurveY }
+
+procedure TTestPDFCurveY.TestWrite_Stroke;
+var
+  o: TMockPDFCurveY;
+  X2,Y2: TPDFFloat;
+  X3,Y3: TPDFFloat;
+  lLineWidth: TPDFFLoat;
+begin
+  X2 := 100;
+  Y2 := 9;
+  X3 := 200;
+  Y3 := 250;
+  lLineWidth := 2;
+  o := TMockPDFCurveY.Create(PDF, x2, y2, x3, y3, lLineWidth, True);
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    o.Write(S);
+    AssertEquals('Failed on 2',
+      '1 J'+CRLF+
+      '2 w'+CRLF+
+      '100 9 200 250 y'+CRLF+
+      'S'+CRLF,
+      S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+procedure TTestPDFCurveY.TestWrite_NoStroke;
+var
+  o: TMockPDFCurveY;
+  X2,Y2: TPDFFloat;
+  X3,Y3: TPDFFloat;
+  lLineWidth: TPDFFLoat;
+begin
+  X2 := 100;
+  Y2 := 9;
+  X3 := 200;
+  Y3 := 250;
+  lLineWidth := 2;
+  o := TMockPDFCurveY.Create(PDF, x2, y2, x3, y3, lLineWidth, False);
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    o.Write(S);
+    AssertEquals('Failed on 2',
+      '100 9 200 250 y'+CRLF,
+      S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+{ TTestPDFEllipse }
+
+procedure TTestPDFEllipse.TestWrite_NoFill_NoStroke;
+var
+  o: TMockPDFEllipse;
+  lPosX, lPosY, lWidth, lHeight, lLineWidth: TPDFFloat;
+begin
+  lPosX := 10;
+  lPosY := 20;
+  lWidth := 200;
+  lHeight := 250;
+  lLineWidth := 2;
+  o := TMockPDFEllipse.Create(PDF, lPosX, lPosY, lWidth, lHeight, lLineWidth, False, False);
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    o.Write(S);
+    AssertEquals('Failed on 2',
+      // move to
+      '10 145 m'+CRLF+
+      // curveC 1
+      '10 76.25 55 20 110 20 c'+CRLF+
+      // curveC 2
+      '165 20 210 76.25 210 145 c'+CRLF+
+      // curveC 3
+      '210 213.75 165 270 110 270 c'+CRLF+
+      // curveC 4
+      '55 270 10 213.75 10 145 c'+CRLF,
+      S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+procedure TTestPDFEllipse.TestWrite_Fill_NoStroke;
+var
+  o: TMockPDFEllipse;
+  lPosX, lPosY, lWidth, lHeight, lLineWidth: TPDFFloat;
+begin
+  lPosX := 10;
+  lPosY := 20;
+  lWidth := 200;
+  lHeight := 250;
+  lLineWidth := 2;
+  o := TMockPDFEllipse.Create(PDF, lPosX, lPosY, lWidth, lHeight, lLineWidth, True, False);
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    o.Write(S);
+    AssertEquals('Failed on 2',
+      // move to
+      '10 145 m'+CRLF+
+      // curveC 1
+      '10 76.25 55 20 110 20 c'+CRLF+
+      // curveC 2
+      '165 20 210 76.25 210 145 c'+CRLF+
+      // curveC 3
+      '210 213.75 165 270 110 270 c'+CRLF+
+      // curveC 4
+      '55 270 10 213.75 10 145 c'+CRLF+
+      'f'+CRLF,
+      S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+procedure TTestPDFEllipse.TestWrite_NoFill_Stroke;
+var
+  o: TMockPDFEllipse;
+  lPosX, lPosY, lWidth, lHeight, lLineWidth: TPDFFloat;
+begin
+  lPosX := 10;
+  lPosY := 20;
+  lWidth := 200;
+  lHeight := 250;
+  lLineWidth := 2;
+  o := TMockPDFEllipse.Create(PDF, lPosX, lPosY, lWidth, lHeight, lLineWidth, False, True);
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    o.Write(S);
+    AssertEquals('Failed on 2',
+      '1 J'+CRLF+
+      '2 w'+CRLF+
+      // move to
+      '10 145 m'+CRLF+
+      // curveC 1
+      '10 76.25 55 20 110 20 c'+CRLF+
+      // curveC 2
+      '165 20 210 76.25 210 145 c'+CRLF+
+      // curveC 3
+      '210 213.75 165 270 110 270 c'+CRLF+
+      // curveC 4
+      '55 270 10 213.75 10 145 c'+CRLF+
+      'S'+CRLF,
+      S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+procedure TTestPDFEllipse.TestWrite_Fill_Stroke;
+var
+  o: TMockPDFEllipse;
+  lPosX, lPosY, lWidth, lHeight, lLineWidth: TPDFFloat;
+begin
+  lPosX := 10;
+  lPosY := 20;
+  lWidth := 200;
+  lHeight := 250;
+  lLineWidth := 2;
+  o := TMockPDFEllipse.Create(PDF, lPosX, lPosY, lWidth, lHeight, lLineWidth, True, True);
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    o.Write(S);
+    AssertEquals('Failed on 2',
+      '1 J'+CRLF+
+      '2 w'+CRLF+
+      // move to
+      '10 145 m'+CRLF+
+      // curveC 1
+      '10 76.25 55 20 110 20 c'+CRLF+
+      // curveC 2
+      '165 20 210 76.25 210 145 c'+CRLF+
+      // curveC 3
+      '210 213.75 165 270 110 270 c'+CRLF+
+      // curveC 4
+      '55 270 10 213.75 10 145 c'+CRLF+
+      'b'+CRLF,
+      S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+{ TTestPDFSurface }
+
+procedure TTestPDFSurface.TestWrite;
+var
+  o: TMockPDFSurface;
+  ar: TPDFCoordArray;
+  p1, p2, p3: TPDFCoord;
+begin
+  SetLength(ar, 3);
+  p1.X := 10; p1.Y := 20;
+  p2.X := 30; p2.Y := 40;
+  p3.X := 50; p3.Y := 60;
+  ar[0] := p1;
+  ar[1] := p2;
+  ar[2] := p3;
+  o := TMockPDFSurface.Create(PDF, ar, True, True);
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    o.Write(S);
+    AssertEquals('Failed on 2',
+      // move to - p0
+      '10 20 m'+CRLF+
+      // line segment - p1
+      '30 40 l'+CRLF+
+      // line segment - p2
+      '50 60 l'+CRLF+
+      'h'+CRLF+   // close
+      'f'+CRLF,   // fill
+      S.DataString);
+  finally
+    SetLength(ar, 0);
+    o.Free;
+  end;
+end;
+
+procedure TTestPDFSurface.TestWrite_noFill;
+var
+  o: TMockPDFSurface;
+  ar: TPDFCoordArray;
+  p1, p2, p3: TPDFCoord;
+begin
+  SetLength(ar, 3);
+  p1.X := 10; p1.Y := 20;
+  p2.X := 30; p2.Y := 40;
+  p3.X := 50; p3.Y := 60;
+  ar[0] := p1;
+  ar[1] := p2;
+  ar[2] := p3;
+  o := TMockPDFSurface.Create(PDF, ar, True, False);
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    o.Write(S);
+    AssertEquals('Failed on 2',
+      // move to - p0
+      '10 20 m'+CRLF+
+      // line segment - p1
+      '30 40 l'+CRLF+
+      // line segment - p2
+      '50 60 l'+CRLF+
+      'h'+CRLF,   // close
+      S.DataString);
+  finally
+    SetLength(ar, 0);
+    o.Free;
+  end;
+end;
+
+procedure TTestPDFSurface.TestWrite_noClose;
+var
+  o: TMockPDFSurface;
+  ar: TPDFCoordArray;
+  p1, p2, p3: TPDFCoord;
+begin
+  SetLength(ar, 3);
+  p1.X := 10; p1.Y := 20;
+  p2.X := 30; p2.Y := 40;
+  p3.X := 50; p3.Y := 60;
+  ar[0] := p1;
+  ar[1] := p2;
+  ar[2] := p3;
+  o := TMockPDFSurface.Create(PDF, ar, False, True);
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    o.Write(S);
+    AssertEquals('Failed on 2',
+      // move to - p0
+      '10 20 m'+CRLF+
+      // line segment - p1
+      '30 40 l'+CRLF+
+      // line segment - p2
+      '50 60 l'+CRLF+
+      'f'+CRLF,   // fill
+      S.DataString);
+  finally
+    SetLength(ar, 0);
+    o.Free;
+  end;
+end;
+
+{ TTestPDFImage }
+
+procedure TTestPDFImage.TestWrite;
+var
+  o: TMockPDFImage;
+  ar: TPDFCoordArray;
+  x, y: TPDFFLoat;
+begin
+  x := 100;
+  y := 200;
+  o := TMockPDFImage.Create(PDF, x, y, 150, 75, 1);
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    o.Write(S);
+    AssertEquals('Failed on 2',
+      // save graphics state
+      'q'+CRLF+
+      '150 0 0 75 100 200 cm'+CRLF+
+      '/I1 Do'+CRLF+
+      // restore graphics state
+      'Q'+CRLF,
+      S.DataString);
+  finally
+    SetLength(ar, 0);
+    o.Free;
+  end;
+end;
+
+{ TTestPDFLineStyle }
+
+procedure TTestPDFLineStyle.TestWrite_ppsSolid;
+var
+  o: TMockPDFLineStyle;
+begin
+  o := TMockPDFLineStyle.Create(PDF, ppsSolid, 1);
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    o.Write(S);
+    AssertEquals('Failed on 2',
+      '[] 1 d'+CRLF,
+      S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+procedure TTestPDFLineStyle.TestWrite_ppsDash;
+var
+  o: TMockPDFLineStyle;
+begin
+  o := TMockPDFLineStyle.Create(PDF, ppsDash, 2);
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    o.Write(S);
+    AssertEquals('Failed on 2',
+      '[5 3] 2 d'+CRLF,
+      S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+procedure TTestPDFLineStyle.TestWrite_ppsDot;
+var
+  o: TMockPDFLineStyle;
+begin
+  o := TMockPDFLineStyle.Create(PDF, ppsDot, 3);
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    o.Write(S);
+    AssertEquals('Failed on 2',
+      '[1 3] 3 d'+CRLF,
+      S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+procedure TTestPDFLineStyle.TestWrite_ppsDashDot;
+var
+  o: TMockPDFLineStyle;
+begin
+  o := TMockPDFLineStyle.Create(PDF, ppsDashDot, 4);
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    o.Write(S);
+    AssertEquals('Failed on 2',
+      '[5 3 1 3] 4 d'+CRLF,
+      S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+procedure TTestPDFLineStyle.TestWrite_ppsDashDotDot;
+var
+  o: TMockPDFLineStyle;
+begin
+  o := TMockPDFLineStyle.Create(PDF, ppsDashDotDot, 1);
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    o.Write(S);
+    AssertEquals('Failed on 2',
+      '[5 3 1 3 1 3] 1 d'+CRLF,
+      S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+{ TTestPDFColor }
+
+procedure TTestPDFColor.TestWrite_Stroke;
+var
+  o: TMockPDFColor;
+begin
+  o := TMockPDFColor.Create(PDF, True, $AABBCC);
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    o.Write(S);
+    AssertEquals('Failed on 2',
+      '0.66 0.73 0.8 RG'+CRLF,
+      S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+procedure TTestPDFColor.TestWrite_noStroke;
+var
+  o: TMockPDFColor;
+begin
+  o := TMockPDFColor.Create(PDF, False, $AABBCC);
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    o.Write(S);
+    AssertEquals('Failed on 2',
+      '0.66 0.73 0.8 rg'+CRLF,
+      S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+{ TTestPDFDictionaryItem }
+
+procedure TTestPDFDictionaryItem.TestWrite;
+var
+  o: TMockPDFDictionaryItem;
+  v: TPDFString;
+begin
+  v := TPDFString.Create(PDF, 'TestValue');
+  o := TMockPDFDictionaryItem.Create(PDF, 'tv', v);
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    o.Write(S);
+    AssertEquals('Failed on 2',
+      '/tv (TestValue)'+CRLF,
+      S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+{ TTestPDFDictionary }
+
+procedure TTestPDFDictionary.TestWrite;
+var
+  o: TMockPDFDictionary;
+  v: TPDFString;
+begin
+  v := TPDFString.Create(PDF, 'TestValue');
+  o := TMockPDFDictionary.Create(PDF);
+  o.AddName('key1','value1');
+  o.AddElement('key2', v);
+  o.AddInteger('key3', 1234);
+  o.AddString('key4', 'string4');
+  o.AddReference('key5', 987);
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    o.Write(S);
+    AssertEquals('Failed on 2',
+      '<<'+CRLF+
+      '/key1 /value1'+CRLF+
+      '/key2 (TestValue)'+CRLF+
+      '/key3 1234'+CRLF+
+      '/key4 (string4)'+CRLF+
+      '/key5 987 0 R'+CRLF+
+      '>>',
+      S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+{ TTestPDFXRef }
+
+procedure TTestPDFXRef.TestWrite;
+var
+  o: TMockPDFXRef;
+begin
+  o := TMockPDFXRef.Create(PDF);
+  try
+    AssertEquals('Failed on 1', '', S.DataString);
+    o.Write(S);
+    AssertEquals('Failed on 2',
+      '0000000000 00000 n'+CRLF,
+      S.DataString);
+
+    o.Offset := 234;
+    o.Write(S);
+    AssertEquals('Failed on 3',
+      '0000000000 00000 n'+CRLF+
+      '0000000234 00000 n'+CRLF,
+      S.DataString);
+  finally
+    o.Free;
+  end;
+end;
+
+{ TTestPDFPage }
+
+procedure TTestPDFPage.TestPageDocument;
+var
+  p: TPDFPage;
+begin
+  p := PDF.Pages.AddPage;
+  AssertTrue('Failed on 1', p.Document = PDF);
+  AssertTrue('Failed on 2', p.UnitOfMeasure = uomMillimeters);
+end;
+
+procedure TTestPDFPage.TestPageDefaultUnitOfMeasure;
+var
+  p: TPDFPage;
+begin
+  p := PDF.Pages.AddPage;
+  AssertTrue('Failed on 1', p.UnitOfMeasure = uomMillimeters);
+end;
+
+procedure TTestPDFPage.TestMatrix;
+var
+  p: TPDFPage;
+  pt1, pt2: TPDFCoord;
+begin
+  p := PDF.Pages.AddPage;
+  AssertTrue('Failed on 1', p.UnitOfMeasure = uomMillimeters);
+  AssertEquals('Failed on 2', mmToPDF(p.Matrix._21), p.Paper.H);
+
+  pt1.X := 10;
+  pt1.Y := 20;
+  pt2 := p.Matrix.Transform(pt1);
+  AssertEquals('Failed on 3', 10, pt2.X);
+  AssertEquals('Failed on 4', 297-20, pt2.Y, 0.1);
+
+  pt1 := p.Matrix.ReverseTransform(pt2);
+  AssertEquals('Failed on 5', 10, pt1.X);
+  AssertEquals('Failed on 6', 20, pt1.Y, 0.1);
+end;
+
+procedure TTestPDFPage.TestUnitOfMeasure_MM;
+var
+  p: TPDFPage;
+  pt: TPDFCoord;
+begin
+  p := PDF.Pages.AddPage;
+  p.UnitOfMeasure := uomMillimeters;
+
+  pt.X := 20;
+  pt.Y := 35;
+  TMockPDFPage(p).doUnitConversion(pt);
+  AssertEquals('Failed on 1', 56.69, pt.X, 0.01);
+  AssertEquals('Failed on 2', 99.21, pt.Y, 0.01);
+
+  pt.X := 40;
+  pt.Y := 20;
+  TMockPDFPage(p).doUnitConversion(pt);
+  AssertEquals('Failed on 3', 113.38, pt.X, 0.01);
+  AssertEquals('Failed on 4', 56.69, pt.Y, 0.01);
+end;
+
+procedure TTestPDFPage.TestUnitOfMeasure_Inches;
+var
+  p: TPDFPage;
+  pt: TPDFCoord;
+begin
+  p := PDF.Pages.AddPage;
+  p.UnitOfMeasure := uomInches;
+
+  pt.X := 1;
+  pt.Y := 1.5;
+  TMockPDFPage(p).doUnitConversion(pt);
+  AssertEquals('Failed on 1', 72.0, pt.X, 0.01);
+  AssertEquals('Failed on 2', 108.0, pt.Y, 0.01);
+
+  pt.X := 2;
+  pt.Y := 1;
+  TMockPDFPage(p).doUnitConversion(pt);
+  AssertEquals('Failed on 3', 144.0, pt.X, 0.01);
+  AssertEquals('Failed on 4', 72.0, pt.Y, 0.01);
+end;
+
+procedure TTestPDFPage.TestUnitOfMeasure_CM;
+var
+  p: TPDFPage;
+  pt: TPDFCoord;
+begin
+  p := PDF.Pages.AddPage;
+  p.UnitOfMeasure := uomMillimeters;
+
+  pt.X := 2.0;
+  pt.Y := 3.5;
+  TMockPDFPage(p).doUnitConversion(pt);
+  AssertEquals('Failed on 1', 5.669, pt.X, 0.01);
+  AssertEquals('Failed on 2', 9.921, pt.Y, 0.01);
+
+  pt.X := 4.0;
+  pt.Y := 2.0;
+  TMockPDFPage(p).doUnitConversion(pt);
+  AssertEquals('Failed on 3', 11.338, pt.X, 0.01);
+  AssertEquals('Failed on 4', 5.669, pt.Y, 0.01);
+end;
+
+
+{ TTestCompressionDecompression }
+
+function TTestCompressionDecompression.GetTestString: string;
+var
+  i: integer;
+  lsLine: string;
+begin
+  result := '';
+  lsLine := '';
+  for i := 1 to 1000 do
+    lsLine := lsLine + Chr(ord('A')+Random(ord('z')-ord('A')));
+  for i := 1 to 200 do
+    result := result + lsLine + LineEnding;
+  Result := 'Hello World';
+end;
+
+procedure TTestCompressionDecompression.TestStreamCompressionDecompression;
+var
+  lSBefore: TStringStream;
+  lSAfter: TStringStream;
+  lCompressed: TMemoryStream;
+  lBefore: string;
+  lAfter: string;
+begin
+  lBefore := GetTestString;
+  lSBefore := TStringStream.Create(lBefore);
+  lCompressed := TMemoryStream.Create;
+  CompressStream(lSBefore, lCompressed);
+  try
+    lSAfter := TStringStream.Create('');
+    DecompressStream(lCompressed, lSAfter);
+    lAfter := lSAfter.DataString;
+    AssertTrue('Compression failed. Strings are not the same. ' +IntToStr(Length(lBefore)) + ' vs ' + IntToStr(Length(lAfter)), lBefore = lAfter);
+  finally
+    lSBefore.Free;
+    lCompressed.Free;
+    lSAfter.Free;
+  end;
+end;
+
+procedure TTestCompressionDecompression.TestStringCompressionDecompression;
+var
+  lBefore: string;
+  lCompressed: string;
+  lAfter: string;
+  s: TStringStream;
+  e: TStringStream;
+begin
+  lBefore := GetTestString;
+  lCompressed := '';
+  CompressString(lBefore, lCompressed);
+  s := TStringStream.Create(lCompressed);
+  try
+    e := TStringStream.Create('');
+    s.Position := 0;
+    DecompressStream(s, e);
+    lAfter := e.DataString;
+  finally
+    e.Free;
+    s.Free;
+  end;
+
+  AssertTrue('Compression failed. Strings are not the same. ' +IntToStr(Length(lBefore)) + ' vs ' + IntToStr(Length(lAfter)), lBefore = lAfter);
+end;
+
+{ TTestTPDFImageItem }
+
+procedure TTestTPDFImageItem.TestCreateStreamedData;
+var
+  itm: TPDFImageItem;
+  img: TFPMemoryImage;
+  b: TBytes;
+begin
+  itm := TPDFImageItem.Create(nil);
+  try
+    itm.OwnsImage := True;
+    img := TFPMemoryImage.Create(5, 5);
+    itm.Image := img;
+    b := itm.StreamedData;
+    AssertEquals('Failed on 1', 75 {5*5*3}, Length(b));
+  finally
+    itm.Free;
+  end;
+
+  itm := TPDFImageItem.Create(nil);
+  try
+    itm.OwnsImage := True;
+    img := TFPMemoryImage.Create(10, 20);
+    itm.Image := img;
+    { this try..except as to prove that we had a bug before we fixed it. }
+    try
+      b := itm.StreamedData;
+    except
+      Fail('Failed on 2 - itm.StreamedData raised an exception');
+    end;
+    AssertEquals('Failed on 3', 600 {10*20*3}, Length(b));
+  finally
+    itm.Free;
+  end;
+end;
+
+
+initialization
+  RegisterTest(TTestPDFObject{$ifdef fptest}.Suite{$endif});
+  RegisterTest(TTestTPDFDocumentObject{$ifdef fptest}.Suite{$endif});
+  RegisterTest(TTestPDFBoolean{$ifdef fptest}.Suite{$endif});
+  RegisterTest(TTestPDFMoveTo{$ifdef fptest}.Suite{$endif});
+  RegisterTest(TTestPDFInteger{$ifdef fptest}.Suite{$endif});
+  RegisterTest(TTestPDFReference{$ifdef fptest}.Suite{$endif});
+  RegisterTest(TTestPDFName{$ifdef fptest}.Suite{$endif});
+  RegisterTest(TTestPDFString{$ifdef fptest}.Suite{$endif});
+  RegisterTest(TTestPDFArray{$ifdef fptest}.Suite{$endif});
+  RegisterTest(TTestPDFStream{$ifdef fptest}.Suite{$endif});
+  RegisterTest(TTestPDFEmbeddedFont{$ifdef fptest}.Suite{$endif});
+  RegisterTest(TTestPDFText{$ifdef fptest}.Suite{$endif});
+  RegisterTest(TTestPDFLineSegment{$ifdef fptest}.Suite{$endif});
+  RegisterTest(TTestTPDFRectangle{$ifdef fptest}.Suite{$endif});
+  RegisterTest(TTestPDFCurveC{$ifdef fptest}.Suite{$endif});
+  RegisterTest(TTestPDFCurveV{$ifdef fptest}.Suite{$endif});
+  RegisterTest(TTestPDFCurveY{$ifdef fptest}.Suite{$endif});
+  RegisterTest(TTestPDFEllipse{$ifdef fptest}.Suite{$endif});
+  RegisterTest(TTestPDFSurface{$ifdef fptest}.Suite{$endif});
+  RegisterTest(TTestPDFImage{$ifdef fptest}.Suite{$endif});
+  RegisterTest(TTestPDFLineStyle{$ifdef fptest}.Suite{$endif});
+  RegisterTest(TTestPDFColor{$ifdef fptest}.Suite{$endif});
+  RegisterTest(TTestPDFDictionaryItem{$ifdef fptest}.Suite{$endif});
+  RegisterTest(TTestPDFDictionary{$ifdef fptest}.Suite{$endif});
+  RegisterTest(TTestPDFXRef{$ifdef fptest}.Suite{$endif});
+  RegisterTest(TTestPDFPage{$ifdef fptest}.Suite{$endif});
+  RegisterTest(TTestCompressionDecompression{$ifdef fptest}.Suite{$endif});
+  RegisterTest(TTestTPDFImageItem{$ifdef fptest}.Suite{$endif});
+
+end.
+

+ 308 - 0
packages/fcl-pdf/tests/fpttf_test.pas

@@ -0,0 +1,308 @@
+unit fpttf_test;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils
+  {$ifdef fptest}
+  ,TestFramework
+  {$else}
+  ,fpcunit, testutils, testregistry
+  {$endif}
+  ,fpttf
+  ;
+
+type
+
+  TFPFontCacheItemTest = class(TTestCase)
+  private
+    FCacheItem: TFPFontCacheItem;
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  public
+    property CI: TFPFontCacheItem read FCacheItem;
+  published
+    procedure TestIsRegular;
+    procedure TestIsBold;
+    procedure TestIsItalic;
+    procedure TestIsFixedWidth;
+    procedure TestRegularVsFixedWidth;
+    procedure TestFileName;
+    procedure TestTextWidth_FontUnits;
+    procedure TestTextWidth_Pixels;
+  end;
+
+
+  TFPFontCacheListTest = class(TTestCase)
+  private
+    FFontCacheList: TFPFontCacheList;
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  public
+    property FC: TFPFontCacheList read FFontCacheList;
+  published
+    procedure TestCount;
+    procedure TestBuildFontCache;
+    procedure TestClear;
+    procedure TestFind_FamilyName;
+  end;
+
+implementation
+
+uses
+  fpparsettf;
+
+{ TFPFontCacheItemTest }
+
+procedure TFPFontCacheItemTest.SetUp;
+begin
+  inherited SetUp;
+  FCacheItem := TFPFontCacheItem.Create('mytest.ttf');
+end;
+
+procedure TFPFontCacheItemTest.TearDown;
+begin
+  FCacheItem.Free;
+  inherited TearDown;
+end;
+
+procedure TFPFontCacheItemTest.TestIsRegular;
+begin
+  CheckEquals(True, CI.IsRegular, 'Failed on 1');
+  CI.IsRegular := True;
+  CI.IsRegular := True;  // to make sure bitwise masks work correctly
+  CheckEquals(True, CI.IsRegular, 'Failed on 2');
+  CI.IsItalic := True;
+  CheckEquals(True, CI.IsRegular, 'Failed on 3');
+  CI.IsRegular := False;
+  CheckEquals(False, CI.IsRegular, 'Failed on 4');
+  CI.IsRegular := False;  // to make sure bitwise masks work correctly. eg: xor usage
+  CheckEquals(False, CI.IsRegular, 'Failed on 5');
+end;
+
+procedure TFPFontCacheItemTest.TestIsBold;
+begin
+  CheckEquals(False, CI.IsBold, 'Failed on 1');
+  CI.IsBold := True;
+  CI.IsBold := True;  // to make sure bitwise masks work correctly
+  CheckEquals(True, CI.IsBold, 'Failed on 2');
+  CI.IsBold := True;
+  CI.IsItalic := True;
+  CheckEquals(True, CI.IsBold, 'Failed on 3');
+  CI.IsBold := False;
+  CheckEquals(False, CI.IsBold, 'Failed on 4');
+  CI.IsBold := False;  // to make sure bitwise masks work correctly. eg: xor usage
+  CheckEquals(False, CI.IsBold, 'Failed on 5');
+end;
+
+procedure TFPFontCacheItemTest.TestIsItalic;
+begin
+  CheckEquals(False, CI.IsItalic, 'Failed on 1');
+  CI.IsItalic := True;
+  CI.IsItalic := True;  // to make sure bitwise masks work correctly
+  CheckEquals(True, CI.IsItalic, 'Failed on 2');
+  CI.IsBold := True;
+  CI.IsItalic := True;
+  CheckEquals(True, CI.IsItalic, 'Failed on 3');
+  CI.IsItalic := False;
+  CheckEquals(False, CI.IsItalic, 'Failed on 4');
+  CI.IsItalic := False;  // to make sure bitwise masks work correctly. eg: xor usage
+  CheckEquals(False, CI.IsItalic, 'Failed on 5');
+end;
+
+procedure TFPFontCacheItemTest.TestIsFixedWidth;
+begin
+  CheckEquals(False, CI.IsFixedWidth, 'Failed on 1');
+  CI.IsFixedWidth := True;
+  CheckEquals(True, CI.IsFixedWidth, 'Failed on 2');
+  CI.IsFixedWidth := True;  // to make sure bitwise masks work correctly
+  CheckEquals(True, CI.IsFixedWidth, 'Failed on 3');
+  CI.IsItalic := True;  // changing another bitmask doesn't affect IsFixedWidth
+  CheckEquals(True, CI.IsFixedWidth, 'Failed on 4');
+  CI.IsFixedWidth := False;
+  CheckEquals(False, CI.IsFixedWidth, 'Failed on 5');
+  CI.IsFixedWidth := False;  // to make sure bitwise masks work correctly. eg: xor usage
+  CheckEquals(False, CI.IsFixedWidth, 'Failed on 6');
+end;
+
+procedure TFPFontCacheItemTest.TestRegularVsFixedWidth;
+begin
+  CheckEquals(True, CI.IsRegular, 'Failed on 1');
+  CheckEquals(False, CI.IsFixedWidth, 'Failed on 2');
+  CI.IsFixedWidth := True;  // this should toggle IsRegular's value
+  CheckEquals(False, CI.IsRegular, 'Failed on 3');
+  CheckEquals(True, CI.IsFixedWidth, 'Failed on 4');
+  CI.IsRegular := True;  // this should toggle IsFixedWidth's value
+  CheckEquals(True, CI.IsRegular, 'Failed on 5');
+  CheckEquals(False, CI.IsFixedWidth, 'Failed on 6');
+end;
+
+procedure TFPFontCacheItemTest.TestFileName;
+begin
+  CI.FileName := '';
+  try
+    CI.GetFontData;
+    Fail('Failed on 1. GetFontData should work if FileName is empty.');
+  except
+    on e: Exception do
+      begin
+        CheckEquals(E.ClassName, 'ETTF', 'Failed on 2.');
+      end;
+  end;
+end;
+
+procedure TFPFontCacheItemTest.TestTextWidth_FontUnits;
+var
+  lFC: TFPFontCacheList;
+  lCI: TFPFontCacheItem;
+begin
+  lFC := TFPFontCacheList.Create;
+  try
+    lFC.SearchPath.Add(ExtractFilePath(ParamStr(0)) + 'fonts');
+    lFC.BuildFontCache;
+
+    lCI := lFC.Find('Liberation Sans');
+    AssertEquals('Failed on 1', 14684, round(lCI.TextWidth('Country Ppml01', 0.0)));
+
+    lCI := lFC.Find('DejaVu Sans');
+    AssertEquals('Failed on 2', 16492, round(lCI.TextWidth('Country Ppml01', 0.0)));
+
+    lCI := lFC.Find('Ubuntu'); // 7333 is the raw glyph width, but with kerning it is 7339
+    AssertEquals('Failed on 3', 7333, round(lCI.TextWidth('Country Ppml01', 0.0)));
+  finally
+    lFC.Free;
+  end;
+end;
+
+procedure TFPFontCacheItemTest.TestTextWidth_Pixels;
+var
+  lFC: TFPFontCacheList;
+  lCI: TFPFontCacheItem;
+  px: single;
+begin
+  lFC := TFPFontCacheList.Create;
+  try
+    lFC.SearchPath.Add(ExtractFilePath(ParamStr(0)) + 'fonts');
+    lFC.BuildFontCache;
+
+    lCI := lFC.Find('Liberation Sans');
+    px := 14684 * 10 * 96 / (72 * 2048);  // 95.599px
+    AssertEquals('Failed on 1', px, lCI.TextWidth('Country Ppml01', 10.0));
+    px := 14684 * 12 * 96 / (72 * 2048);  // 114.7188px
+    AssertEquals('Failed on 2', px, lCI.TextWidth('Country Ppml01', 12.0));
+    px := 14684 * 24 * 96 / (72 * 2048);  // 229.4375px
+    AssertEquals('Failed on 3', px, lCI.TextWidth('Country Ppml01', 24.0));
+
+    lCI := lFC.Find('DejaVu Sans');
+    px := 16492 * 10 * 96 / (72 * 2048);  // 107.369px
+    AssertEquals('Failed on 4', px, lCI.TextWidth('Country Ppml01', 10.0));
+    px := 16492 * 12 * 96 / (72 * 2048);  // 128.8438px
+    AssertEquals('Failed on 5', px, lCI.TextWidth('Country Ppml01', 12.0));
+    px := 16492 * 24 * 96 / (72 * 2048);  // 205.6875px
+    AssertEquals('Failed on 6', px, lCI.TextWidth('Country Ppml01', 24.0));
+
+    lCI := lFC.Find('Ubuntu');
+    px := 7333 * 10 * 96 / (72 * 1000);  // 97.7733px
+    AssertEquals('Failed on 7', px, lCI.TextWidth('Country Ppml01', 10.0));
+    px := 7333 * 12 * 96 / (72 * 1000);  // 117.328px
+    AssertEquals('Failed on 8', px, lCI.TextWidth('Country Ppml01', 12.0));
+    px := 7333 * 24 * 96 / (72 * 1000);  // 234.656px
+    AssertEquals('Failed on 9', px, lCI.TextWidth('Country Ppml01', 24.0));
+  finally
+    lFC.Free;
+  end;
+end;
+
+{ TFPFontCacheListTest }
+
+procedure TFPFontCacheListTest.SetUp;
+begin
+  inherited SetUp;
+  FFontCacheList := TFPFontCacheList.Create;
+end;
+
+procedure TFPFontCacheListTest.TearDown;
+begin
+  FFontCacheList.Free;
+  inherited TearDown;
+end;
+
+procedure TFPFontCacheListTest.TestCount;
+begin
+  CheckEquals(0, FC.Count, 'Failed on 1');
+  FC.SearchPath.Add(ExtractFilePath(ParamStr(0)) + 'fonts');
+  CheckEquals(0, FC.Count, 'Failed on 2');
+  FC.BuildFontCache;
+  CheckEquals(4, FC.Count, 'Failed on 3');
+end;
+
+procedure TFPFontCacheListTest.TestBuildFontCache;
+begin
+  CheckEquals(0, FC.Count, 'Failed on 1');
+  try
+    FC.BuildFontCache;
+    Fail('Failed on 2. We don''t have font paths, so BuildFontCache shouldn''t run.');
+  except
+    on e: Exception do
+      begin
+        CheckEquals(E.ClassName, 'ETTF', 'Failed on 3.');
+      end;
+  end;
+
+  FC.SearchPath.Add(ExtractFilePath(ParamStr(0)) + 'fonts');
+  CheckEquals(0, FC.Count, 'Failed on 4');
+  FC.BuildFontCache;
+  CheckEquals(4, FC.Count, 'Failed on 5');
+end;
+
+procedure TFPFontCacheListTest.TestClear;
+begin
+  CheckEquals(0, FC.Count, 'Failed on 1');
+  FC.SearchPath.Add(ExtractFilePath(ParamStr(0)) + 'fonts');
+  FC.BuildFontCache;
+  CheckEquals(4, FC.Count, 'Failed on 2');
+  FC.Clear;
+  CheckEquals(0, FC.Count, 'Failed on 3');
+end;
+
+procedure TFPFontCacheListTest.TestFind_FamilyName;
+var
+  lCI: TFPFontCacheItem;
+begin
+  lCI := nil;
+  CheckEquals(0, FC.Count, 'Failed on 1');
+  lCI := FC.Find('Ubuntu');
+  CheckTrue(lCI = nil, 'Failed on 2');
+  FC.SearchPath.Add(ExtractFilePath(ParamStr(0)) + 'fonts');
+  FC.BuildFontCache;
+  CheckEquals(4, FC.Count, 'Failed on 3');
+  lCI := FC.Find('Ubuntu');
+  CheckTrue(Assigned(lCI), 'Failed on 4');
+
+  { TODO: We should try and extend this to make font paths user configure
+           thus the tests could be more flexible. }
+
+  lCI := FC.Find('Ubuntu', True); // bold font
+  CheckTrue(lCI = nil, 'Failed on 5');
+  lCI := FC.Find('Ubuntu', False, True); // italic font
+  CheckTrue(lCI = nil, 'Failed on 6');
+  lCI := FC.Find('Ubuntu', True, True); // bold+italic font
+  CheckTrue(lCI = nil, 'Failed on 7');
+
+  lCI := FC.Find('DejaVu Sans');
+  CheckTrue(Assigned(lCI), 'Failed on 8');
+  lCI := FC.Find('DejaVu Sans Bold');
+  CheckTrue(lCI = nil, 'Failed on 9');
+end;
+
+
+initialization
+  RegisterTest(TFPFontCacheItemTest{$ifdef fptest}.Suite{$endif});
+  RegisterTest(TFPFontCacheListTest{$ifdef fptest}.Suite{$endif});
+
+end.
+

+ 8 - 0
packages/fcl-pdf/tests/readme.txt

@@ -0,0 +1,8 @@
+In order for the  demos to work properly, 
+the following 4 fonts must be downloaded and placed in the fonts directory:
+
+DejaVuSans.ttf (and DejaVuSans.fnt)
+FreeSans.ttf 
+LiberationSans-Regular.ttf 
+Ubuntu-R.ttf 
+

+ 5 - 0
packages/fcl-pdf/tests/testunits.inc

@@ -0,0 +1,5 @@
+  ,fpparsettf_test
+  ,fppdf_test
+  ,fpttf_test
+
+

+ 94 - 0
packages/fcl-pdf/tests/unittests_console.lpi

@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="9"/>
+    <General>
+      <Flags>
+        <LRSInOutputDirectory Value="False"/>
+      </Flags>
+      <SessionStorage Value="InIDEConfig"/>
+      <MainUnit Value="0"/>
+      <Title Value="unittests_console"/>
+    </General>
+    <VersionInfo>
+      <Language Value=""/>
+      <CharSet Value=""/>
+      <StringTable ProductVersion=""/>
+    </VersionInfo>
+    <BuildModes Count="1">
+      <Item1 Name="default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+      <IgnoreBinaries Value="False"/>
+      <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
+      <ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
+    </PublishOptions>
+    <RunParams>
+      <local>
+        <FormatVersion Value="1"/>
+        <LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
+      </local>
+    </RunParams>
+    <RequiredPackages Count="2">
+      <Item1>
+        <PackageName Value="FPCUnitConsoleRunner"/>
+      </Item1>
+      <Item2>
+        <PackageName Value="FCL"/>
+      </Item2>
+    </RequiredPackages>
+    <Units Count="4">
+      <Unit0>
+        <Filename Value="unittests_console.lpr"/>
+        <IsPartOfProject Value="True"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="testunits.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit1>
+      <Unit2>
+        <Filename Value="fpparsettf_test.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit2>
+      <Unit3>
+        <Filename Value="fppdf_test.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit3>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <Target>
+      <Filename Value="unittests_console"/>
+    </Target>
+    <SearchPaths>
+      <OtherUnitFiles Value="../src"/>
+      <UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
+    </SearchPaths>
+    <Parsing>
+      <SyntaxOptions>
+        <CStyleOperator Value="False"/>
+        <UseAnsiStrings Value="False"/>
+      </SyntaxOptions>
+    </Parsing>
+    <Linking>
+      <Debugging>
+        <UseHeaptrc Value="True"/>
+      </Debugging>
+    </Linking>
+    <Other>
+      <CustomOptions Value="-dfptestX"/>
+    </Other>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="2">
+      <Item1>
+        <Name Value="ECodetoolError"/>
+      </Item1>
+      <Item2>
+        <Name Value="EFOpenError"/>
+      </Item2>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 30 - 0
packages/fcl-pdf/tests/unittests_console.lpr

@@ -0,0 +1,30 @@
+program unittests_console;
+
+{$mode objfpc}{$H+}
+
+uses
+  Classes
+  ,consoletestrunner
+  {$i testunits.inc}
+  ;
+
+type
+
+  { TLazTestRunner }
+
+  TMyTestRunner = class(TTestRunner)
+  protected
+  // override the protected methods of TTestRunner to customize its behavior
+  end;
+
+var
+  Application: TMyTestRunner;
+
+begin
+  DefaultFormat:=fPlain;
+  DefaultRunAllTests:=True;
+  Application := TMyTestRunner.Create(nil);
+  Application.Initialize;
+  Application.Run;
+  Application.Free;
+end.

+ 94 - 0
packages/fcl-pdf/tests/unittests_gui.lpi

@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="9"/>
+    <General>
+      <Flags>
+        <LRSInOutputDirectory Value="False"/>
+      </Flags>
+      <SessionStorage Value="InIDEConfig"/>
+      <MainUnit Value="0"/>
+      <Title Value="unittests_gui"/>
+    </General>
+    <VersionInfo>
+      <Language Value=""/>
+      <CharSet Value=""/>
+      <StringTable ProductVersion=""/>
+    </VersionInfo>
+    <BuildModes Count="1">
+      <Item1 Name="default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+      <IgnoreBinaries Value="False"/>
+      <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
+      <ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
+    </PublishOptions>
+    <RunParams>
+      <local>
+        <FormatVersion Value="1"/>
+        <LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
+      </local>
+    </RunParams>
+    <RequiredPackages Count="1">
+      <Item1>
+        <PackageName Value="FPCUnitTestRunner"/>
+      </Item1>
+    </RequiredPackages>
+    <Units Count="4">
+      <Unit0>
+        <Filename Value="unittests_gui.lpr"/>
+        <IsPartOfProject Value="True"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="testunits.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit1>
+      <Unit2>
+        <Filename Value="fpparsettf_test.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit2>
+      <Unit3>
+        <Filename Value="fppdf_test.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit3>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <Target>
+      <Filename Value="unittests_gui"/>
+    </Target>
+    <SearchPaths>
+      <OtherUnitFiles Value="../src"/>
+      <UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
+    </SearchPaths>
+    <Parsing>
+      <SyntaxOptions>
+        <CStyleOperator Value="False"/>
+        <IncludeAssertionCode Value="True"/>
+      </SyntaxOptions>
+    </Parsing>
+    <Linking>
+      <Debugging>
+        <UseHeaptrc Value="True"/>
+      </Debugging>
+    </Linking>
+    <Other>
+      <CustomOptions Value="-dfptestX"/>
+    </Other>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="ECodetoolError"/>
+      </Item1>
+      <Item2>
+        <Name Value="EFOpenError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EAssertionFailedError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 26 - 0
packages/fcl-pdf/tests/unittests_gui.lpr

@@ -0,0 +1,26 @@
+program unittests_gui;
+
+{$mode objfpc}{$H+}
+
+uses
+  Classes
+  ,Interfaces
+  ,Forms
+  ,GuiTestRunner
+  {$i testunits.inc}
+  ;
+
+
+
+
+procedure MainProc;
+begin
+  Application.Initialize;
+  Application.CreateForm(TGUITestRunner, TestRunner);
+  Application.Run;
+end;
+
+
+begin
+  MainProc;
+end.

+ 83 - 0
packages/fcl-pdf/utils/mkpdffontdef.lpi

@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="9"/>
+    <General>
+      <Flags>
+        <MainUnitHasCreateFormStatements Value="False"/>
+        <MainUnitHasTitleStatement Value="False"/>
+      </Flags>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <Title Value="mkpdffontdef"/>
+      <UseAppBundle Value="False"/>
+      <ResourceType Value="res"/>
+    </General>
+    <i18n>
+      <EnableI18N LFM="False"/>
+    </i18n>
+    <VersionInfo>
+      <StringTable ProductVersion=""/>
+    </VersionInfo>
+    <BuildModes Count="1">
+      <Item1 Name="Default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+    </PublishOptions>
+    <RunParams>
+      <local>
+        <FormatVersion Value="1"/>
+        <CommandLineParams Value="/usr/share/fonts/truetype/msttcorefonts/arial.ttf cp1252 arial.fnt"/>
+      </local>
+    </RunParams>
+    <Units Count="3">
+      <Unit0>
+        <Filename Value="mkpdffontdef.pp"/>
+        <IsPartOfProject Value="True"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="fpttfencodings.pp"/>
+        <IsPartOfProject Value="True"/>
+      </Unit1>
+      <Unit2>
+        <Filename Value="fpparsettf.pp"/>
+        <IsPartOfProject Value="True"/>
+      </Unit2>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <Target>
+      <Filename Value="mkpdffontdef"/>
+    </Target>
+    <SearchPaths>
+      <IncludeFiles Value="$(ProjOutDir)"/>
+      <OtherUnitFiles Value="../src"/>
+      <UnitOutputDirectory Value="units/"/>
+    </SearchPaths>
+    <Parsing>
+      <SyntaxOptions>
+        <UseAnsiStrings Value="False"/>
+      </SyntaxOptions>
+    </Parsing>
+    <Linking>
+      <Debugging>
+        <UseHeaptrc Value="True"/>
+      </Debugging>
+    </Linking>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="EAbort"/>
+      </Item1>
+      <Item2>
+        <Name Value="ECodetoolError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EFOpenError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 36 - 0
packages/fcl-pdf/utils/mkpdffontdef.pp

@@ -0,0 +1,36 @@
+{
+    This file is part of the Free Component Library (FCL)
+    Copyright (c) 2014 by Michael Van Canneyt
+
+    This small program reads a TTF font file and creates a definition in a .ini file for later use
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$mode objfpc}
+{$h+}
+
+program mkpdffontdef;
+
+uses sysutils, fpttfencodings, fpparsettf;
+
+begin
+  if (ParamCount<3) then
+    begin
+    writeln('Usage : ',ExtractFileName(paramstr(0)),' ttffilename encoding fntfilename');
+    Halt(1);
+    end;
+  With TTFFileInfo.Create do
+    try
+      LoadFromFile(ParamStr(1));
+      MakePDFFontDef(Paramstr(3),Paramstr(2),False)
+    finally
+      Free;
+    end;
+end.
+

+ 2 - 1
packages/fpmake_add.inc

@@ -125,4 +125,5 @@
   add_zlib(ADirectory+IncludeTrailingPathDelimiter('zlib'));
   add_libenet(ADirectory+IncludeTrailingPathDelimiter('libenet'));
   add_zorba(ADirectory+IncludeTrailingPathDelimiter('zorba'));
-  add_Google(ADirectory+IncludeTrailingPathDelimiter('googleapi'));
+  add_Google(ADirectory+IncludeTrailingPathDelimiter('googleapi'));
+  add_fcl_pdf(ADirectory+IncludeTrailingPathDelimiter('fcl-pdf'));

+ 5 - 0
packages/fpmake_proc.inc

@@ -725,3 +725,8 @@ end;
 
 {$include googleapi/fpmake.pp}
 
+procedure add_fcl_pdf(const ADirectory: string);
+begin
+  with Installer do
+{$include fcl-pdf/fpmake.pp}
+end;