summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/PDFA_def.ps40
-rw-r--r--lib/ghostpdf.catbin7290 -> 9756 bytes
-rw-r--r--lib/gslp.ps79
-rw-r--r--lib/viewgif.ps6
-rw-r--r--lib/zugferd.ps452
5 files changed, 401 insertions, 176 deletions
diff --git a/lib/PDFA_def.ps b/lib/PDFA_def.ps
index f77c90ef..c5e2aa68 100644
--- a/lib/PDFA_def.ps
+++ b/lib/PDFA_def.ps
@@ -35,13 +35,13 @@ def
/CMYK eq {
/N 4 false
}{
- (ColorConversionStrategy not a device space, falling back to ProcessColorModel, output may not be valid PDF/A.)=
+ (\tColorConversionStrategy not a device space, falling back to ProcessColorModel, output may not be valid PDF/A.\n)=
true
} ifelse
} ifelse
} ifelse
} {
- (ColorConversionStrategy not set, falling back to ProcessColorModel, output may not be valid PDF/A.)=
+ (\tColorConversionStrategy not set, falling back to ProcessColorModel, output may not be valid PDF/A.\n)=
true
} ifelse
@@ -56,7 +56,7 @@ def
dup /DeviceCMYK eq {
pop /N 4
} {
- (ProcessColorModel not a device space.)=
+ (\tProcessColorModel not a device space.)=
/ProcessColorModel cvx /rangecheck signalerror
} ifelse
} ifelse
@@ -65,15 +65,27 @@ def
%% ----------8<--------------8<-------------8<--------------8<----------
>> /PUT pdfmark
-[{icc_PDFA} ICCProfile (r) file /PUT pdfmark
+[
+{icc_PDFA}
+{ICCProfile (r) file} stopped
+{
+ (\n\tFailed to open the supplied ICCProfile for reading. This may be due to\n) print
+ (\t an incorrect filename or a failure to add --permif-file-read=<profile>\n) print
+ (\t to the command line. This PostScript program needs to open the file\n) print
+ (\t and you must explicitly grant it permission to do so.\n\n) print
+ (\tPDF/A processing aborted, output may not be a PDF/A file.\n\n) print
+ cleartomark
+}
+{
+ /PUT pdfmark
+ % Define the output intent dictionary :
-% Define the output intent dictionary :
-
-[/_objdef {OutputIntent_PDFA} /type /dict /OBJ pdfmark
-[{OutputIntent_PDFA} <<
- /Type /OutputIntent % Must be so (the standard requires).
- /S /GTS_PDFA1 % Must be so (the standard requires).
- /DestOutputProfile {icc_PDFA} % Must be so (see above).
- /OutputConditionIdentifier (sRGB) % Customize
->> /PUT pdfmark
-[{Catalog} <</OutputIntents [ {OutputIntent_PDFA} ]>> /PUT pdfmark
+ [/_objdef {OutputIntent_PDFA} /type /dict /OBJ pdfmark
+ [{OutputIntent_PDFA} <<
+ /Type /OutputIntent % Must be so (the standard requires).
+ /S /GTS_PDFA1 % Must be so (the standard requires).
+ /DestOutputProfile {icc_PDFA} % Must be so (see above).
+ /OutputConditionIdentifier (sRGB) % Customize
+ >> /PUT pdfmark
+ [{Catalog} <</OutputIntents [ {OutputIntent_PDFA} ]>> /PUT pdfmark
+} ifelse
diff --git a/lib/ghostpdf.cat b/lib/ghostpdf.cat
index 4c6fc304..ec51696f 100644
--- a/lib/ghostpdf.cat
+++ b/lib/ghostpdf.cat
Binary files differ
diff --git a/lib/gslp.ps b/lib/gslp.ps
index 173d52c2..9a3a2f3e 100644
--- a/lib/gslp.ps
+++ b/lib/gslp.ps
@@ -38,10 +38,13 @@
% --detect
% treat the file as PostScript if it starts with %!
% --first-page <n>
-% --duplex(|-long-edge|-short-edge)
-% use duplex if available; if not specified, select long edge
-% for portrait printing, short edge for landscape
+% --duplex(|-long-edge|-short-edge)
+% use duplex if available; if not specified, select long edge
+% for portrait printing, short edge for landscape
% start printing at page <n>
+% --encoding <encodingname> default ISOLatin1Encoding
+% Note this only takes effect during -f or -F option thus the
+% body text and header text can use different encodings.
% --kern <file.afm>
% kern using information from the given .AFM file
% --last-page <n>
@@ -60,17 +63,26 @@
/lpdict 150 dict def
lpdict begin
-% build iso-latin-1 version of a font
-/font-to-iso-latin-1 { % <font> font-to-iso-latin-1 <font>
+/encoding /ISOLatin1Encoding def % the default encoding
+
+% build a version of the font with the requested encoding (default ISOLatin1)
+/font-to-encoding { % <font> font-to-encoding <font>
%% reencode for iso latin1; from the 2nd edition red book, sec 5.6.1
dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall
- /Encoding ISOLatin1Encoding def currentdict end
- dup /FontName get 80 string cvs (-ISOLatin1) concatstrings cvn
+ /Encoding encoding /Encoding findresource readonly def
+ currentdict end
+ % strip off the "Encoding" part of the encoding (if present)
+ dup /FontName get 80 string cvs
+ encoding 256 string cvs (Encoding) search {
+ exch pop exch pop
+ } if
+ exch (-) concatstrings exch
+ concatstrings cvn
exch definefont
} def
/find-latin-font { % <name> find-latin-font <font>
- findfont font-to-iso-latin-1
+ findfont font-to-encoding
} def
% Define the initial values of the printing parameters.
@@ -275,14 +287,17 @@ lpdict begin
/StringTAB (\t) def
/CharTAB StringTAB 0 get def
-/showline % line -> leftover_line (handles \f)
- { { showline1 dup length 0 eq { exit } if
- dup 0 get CharFF ne { exit } if
+/showline { % line -> leftover_line (handles \f)
+ { showline1 dup length 0 eq { exit } if
+ dup 0 get CharFF ne {
+ Truncate { pop () } if
+ exit
+ } if
EjectFF { endpage beginpage } { endcolumn } ifelse
skip1
- }
+ }
loop
- } def
+} def
/showline1 % line -> leftover_line (handles page break)
{ lindex llength eq { endpage beginpage } if
@@ -409,9 +424,9 @@ lpdict begin
/S {currentfile =string readline pop show} lpdef
/RE { % <isoname> <fontname> RE <font>
findfont
- %% reencode for iso latin1; from the 2nd edition red book, sec 5.6.1
+ %% reencode for current 'encoding' from the 2nd edition red book, sec 5.6.1
dup length dict begin {1 index /FID ne {def} {pop pop} ifelse} forall
- /Encoding ISOLatin1Encoding def currentdict end
+ /Encoding encoding def currentdict end
definefont
} lpdef
} def
@@ -506,24 +521,31 @@ lpdict begin
% Iterate through the file.
lpline
- { dup length /pos exch def
- lbuf exch 0 exch putinterval
- { lpfile lbuf pos lbuf length pos sub getinterval readline } stopped
- { % Filled the line before a CR or EOF.
- exch pop showline
- }
- { % Reached CR and/or EOF first.
+ % First handle new-lines in the initial string (--detect mode)
+ (\n) search {
+ showline % output up to the first new-line
+ pop pop % done with that string and the new-line
+ (\n) search {
+ showline % output the second new-line
+ pop pop % done
+ } if
+ } if
+ { dup length /pos exch def
+ lbuf exch 0 exch putinterval
+ { lpfile lbuf pos lbuf length pos sub getinterval readline } stopped
+ { % Filled the line before a CR or EOF.
+ exch pop showline
+ }
+ { % Reached CR and/or EOF first.
exch length pos add lbuf exch 0 exch getinterval
1 index { showline } if % omit final empty line
- { dup length 0 eq Truncate or { pop () exit } if
+ { dup length 0 eq { pop () exit } if
showline
- }
- loop
+ } loop
exch not { exit } if
- }
- ifelse
+ } ifelse
pindex PageLast gt { exit } if
- } loop
+ } loop
pop
% Wrap up.
@@ -588,6 +610,7 @@ lpdict begin
/--duplex { /Duplex {Landscape} def } def
/--duplex-long-edge { /Duplex false def } def
/--duplex-short-edge { /Duplex true def } def
+/--encoding { cvn /encoding exch def } def
/--first-page { cvi /PageFirst exch def } def
/--footing-center { /FootingCenter exch def /Footers true def } def
/--footing-left { /FootingLeft exch def /Footers true def } def
diff --git a/lib/viewgif.ps b/lib/viewgif.ps
index a261bf7e..0426e2f4 100644
--- a/lib/viewgif.ps
+++ b/lib/viewgif.ps
@@ -42,7 +42,9 @@
GlobalColor
{ PaletteSize 3 mul string readstring pop
/GlobalPalette exch def
- } if
+ } {
+ pop
+ } ifelse
currentdict end
} bind def
@@ -159,7 +161,7 @@
} bind def
% This lets you do stuff on the command line like:
-% gs -sDEVICE=pdfwrite -o stuff%03d.pdf viewgif.ps -c "(image.gif) << /PageSize 2 index viewGIFgetsize 2 array astore >> setpagedevice viewGIF"
+% gs -sDEVICE=pdfwrite -o stuff%03d.pdf viewgif.ps -c "(image.gif) << /PageSize 2 index viewGIFgetsize 2 array astore /HWResolution [ 72 72 ] >> setpagedevice viewGIF"
% so the output size is influenced by the original image.
/viewGIFgetsize % <file|string> ==> [width height]
{
diff --git a/lib/zugferd.ps b/lib/zugferd.ps
index 0320fb69..97d33d4d 100644
--- a/lib/zugferd.ps
+++ b/lib/zugferd.ps
@@ -1,3 +1,5 @@
+%!PS
+
% Copyright (C) 2001-2021 Artifex Software, Inc.
% All Rights Reserved.
%
@@ -12,38 +14,68 @@
% Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato,
% CA 94945, U.S.A., +1(415)492-9861, for further information.
%
-% zugferd.ps
-% This program will create an (unsigned) ZUGFeRD compliant PDF file. In
-% order to do so the user must provide certain information, or edit this program.
+% ZUGFeRD.ps
+% This program will create an (unsigned) ZUGFeRD compliant PDF file.
+% In order to do so the user must provide certain information, or edit
+% this program.
+%
+% Required information is the path to the XML file containing the invoice
+% data, and the path to an ICC profile appropriate for the chosen
+% ColorConversionStrategy.
+%
+% -sZUGFeRDXMLFile defines a path to the XML invoice file.
+%
+% -sZUGFeRDProfile defines the path to the ICC profile.
+%
+% -sZUGFeRDVersion defines the version of the ZUGFeRD standard to be used.
+% Missing or invalid values would be silently replaced by the default ("2p1").
+%
+% -sZUGFeRDConformanceLevel defines the level of conformance.
+% Missing or invalid values would be silently replaced by the default ("BASIC").
%
-% Required information is the path to the XML file containing the invoice data,
-% and the path to an ICC profile appropriate for the chosen ColorConversionStrategy.
-% -sZUGFeRDXMLFile defines a path to the XML invoice file and -sZUGFeRDProfile
-% defines the path to the ICC profile.
+% Note that the ZUGFeRD standard states:
%
-% The user must additionally set -dPDFA=3 and -sColorConversionStrategy on the
-% Ghostscript command line, and set the permissions for Ghostscript to read
-% both these files. It is simplest to put the files in a directory and then
-% permit reading of the entire directory.
+% The content of the field fx:ConformanceLevel has to be picked from
+% the content of the element "GuidelineSpecifiedDocumentContextParameter"
+% (specification identifier BT-24) of the XML instance file.
+%
+% The user must additionally set -dPDFA=3 and -sColorConversionStrategy
+% on the Ghostscript command line, and set the permissions for Ghostscript
+% to read both these files. It is simplest to put the files in a directory
+% and then permit reading of the entire directory.
%
% Example command line :
%
-% gs --permit-file-read=/usr/home/me/zugferd/ -sDEVICE=pdfwrite -dPDFA=3 -sColorConversionStrategy=RGB \
-% -sZUGFeRDXMLFile=/usr/home/me/zugferd/invoice.xml -sZUGFeRDProfile=/usr/home/me/rgb.icc \
-% -o /usr/home/me/zugferd/zugferd.pdf /usr/home/me/zugferd/zugferd.ps /usr/home/me/zugferd/original.pdf
+% gs --permit-file-read=/usr/home/me/zugferd/ \
+% -sDEVICE=pdfwrite \
+% -dPDFA=3 \
+% -sColorConversionStrategy=RGB \
+% -sZUGFeRDXMLFile=/usr/home/me/zugferd/invoice.xml \
+% -sZUGFeRDProfile=/usr/home/me/zugferd/rgb.icc \
+% -sZUGFeRDVersion=2p1 \
+% -sZUGFeRDConformanceLevel=BASIC \
+% -o /usr/home/me/zugferd/zugferd.pdf \
+% /usr/home/me/zugferd/zugferd.ps \
+% /usr/home/me/zugferd/original.pdf
%
-% Much of this program results from a Ghostscript bug report, the thread can be found at
-% https://bugs.ghostscript.com/show_bug.cgi?id=696472 Portions of the code below were
-% supplied by Reinhard Nissl and I'm indebted to him for his efforts in helping me create
-% a solution for this problem as well as for the code he supplied, particularly for the
+% Much of this program results from a Ghostscript bug report, the thread
+% can be found at
+% https://bugs.ghostscript.com/show_bug.cgi?id=696472
+% Portions of the code below were supplied by Reinhard Nissl and
+% I'm indebted to him for his efforts in helping me create a solution for
+% this problem as well as for the code he supplied, particularly for the
% SimpleUTF16BE routine.
%
-% It should not be necessary to modify this program, the comments in the code are there purely for information,
-% but there are two areas which might reasonably be altered. The section with the --8<-- lines could be replaced
-% with a simpler /N 3 or /N 4 if you always intend to produce the same kind of files; RGB or CMYK.
-% In step 7, the large XML string will need to be replaced if you want to produce a ZUGFeRD 2.1
-% file, and in future may require similar modification for later versions.
+% The program was further refined and expanded by Adrian Devries in :
+% https://bugs.ghostscript.com/show_bug.cgi?id=703862
+%
+% It should not be necessary to modify this program, the comments in the
+% code are there purely for information, but there is one area which
+% might reasonably be altered. The section with the --8<-- lines could be
+% replaced with a simpler /N 3 or /N 4 if you always intend to produce
+% the same kind of files; RGB or CMYK.
%
+% Remaining tasks have been marked with "TODO".
% istring SimpleUTF16BE ostring
/SimpleUTF16BE
@@ -52,13 +84,11 @@
1 add
2 mul
string
-
% istring ostring
dup 0 16#FE put
dup 1 16#FF put
2
3 -1 roll
-
% ostring index istring
{
% ostring index ichar
@@ -74,12 +104,246 @@
% ostring index
}
forall
-
% ostring index
pop
}
bind def
+% Cf. https://en.wikibooks.org/wiki/PostScript_FAQ#How_to_concatenate_strings%3F
+/concatstringarray { % [(a) (b) ... (z)] --> (ab...z)
+ 0 1 index {
+ length add
+ } forall
+ string
+ 0 3 2 roll {
+ 3 copy putinterval
+ length add
+ } forall
+ pop
+} bind def
+
+/ZUGFeRDVersion where {
+ pop % Discard the dictionary
+ ZUGFeRDVersion (rc) ne {
+ ZUGFeRDVersion (1p0) ne {
+ ZUGFeRDVersion (2p0) ne {
+ ZUGFeRDVersion (2p1) ne {
+ /ZUGFeRDVersion (2p1) def
+ } if
+ } if
+ } if
+ } if
+}{
+ /ZUGFeRDVersion (2p1) def
+} ifelse
+
+/ZUGFeRDConformanceLevel where {
+ pop % Discard the dictionary
+ ZUGFeRDVersion (rc) eq
+ ZUGFeRDVersion (1p0) eq or {
+ ZUGFeRDConformanceLevel (BASIC) ne {
+ ZUGFeRDConformanceLevel (COMFORT) ne {
+ ZUGFeRDConformanceLevel (EXTENDED) ne {
+ /ZUGFeRDConformanceLevel (BASIC) def
+ } if
+ } if
+ } if
+ } if
+ ZUGFeRDVersion (2p0) eq
+ ZUGFeRDVersion (2p1) eq or {
+ ZUGFeRDConformanceLevel (MINIMUM) ne {
+ ZUGFeRDConformanceLevel (BASIC WL) ne {
+ ZUGFeRDConformanceLevel (BASIC) ne {
+ ZUGFeRDConformanceLevel (EN 16931) ne {
+ ZUGFeRDConformanceLevel (EXTENDED) ne {
+ ZUGFeRDConformanceLevel (XRECHNUNG) ne {
+ /ZUGFeRDConformanceLevel (BASIC) def
+ } if
+ } if
+ } if
+ } if
+ } if
+ } if
+ } if
+}{
+ /ZUGFeRDConformanceLevel (BASIC) def
+} ifelse
+
+% ZUGFeRDSchema
+/ZUGFeRDSchema () def
+ZUGFeRDVersion (rc) eq
+ZUGFeRDVersion (1p0) eq or
+ZUGFeRDVersion (2p0) eq or {
+ /ZUGFeRDSchema (ZUGFeRD PDFA Extension Schema) def
+} if
+ZUGFeRDVersion (2p1) eq {
+ /ZUGFeRDSchema (Factur-X PDFA Extension Schema) def
+} if
+
+% ZUGFeRDNamespaceURI
+/ZUGFeRDNamespaceURI () def
+ZUGFeRDVersion (rc) eq {
+ /ZUGFeRDNamespaceURI (urn:ferd:pdfa:invoice:rc#) def
+} if
+ZUGFeRDVersion (1p0) eq {
+ /ZUGFeRDNamespaceURI (urn:ferd:pdfa:CrossIndustryDocument:invoice:1p0#) def
+} if
+ZUGFeRDVersion (2p0) eq {
+ /ZUGFeRDNamespaceURI (urn:zugferd:pdfa:CrossIndustryDocument:invoice:2p0#) def
+} if
+ZUGFeRDVersion (2p1) eq {
+ /ZUGFeRDNamespaceURI (urn:factur-x:pdfa:CrossIndustryDocument:invoice:1p0#) def
+} if
+
+% ZUGFeRDPrefix
+/ZUGFeRDPrefix () def
+ZUGFeRDVersion (rc) eq
+ZUGFeRDVersion (1p0) eq or
+ZUGFeRDVersion (2p0) eq or {
+ /ZUGFeRDPrefix (zf) def
+} if
+ZUGFeRDVersion (2p1) eq {
+ /ZUGFeRDPrefix (fx) def
+} if
+
+% ZUGFeRDVersionDescription
+/ZUGFeRDVersionDescription () def
+ZUGFeRDVersion (rc) eq
+ZUGFeRDVersion (1p0) eq or
+ZUGFeRDVersion (2p0) eq or {
+ /ZUGFeRDVersionDescription (The actual version of the ZUGFeRD XML schema) def
+} if
+ZUGFeRDVersion (2p1) eq {
+ /ZUGFeRDVersionDescription (The actual version of the Factur-X XML schema) def
+} if
+
+% ZUGFeRDConformanceLevelDescription
+/ZUGFeRDConformanceLevelDescription () def
+ZUGFeRDVersion (rc) eq
+ZUGFeRDVersion (1p0) eq or
+ZUGFeRDVersion (2p0) eq or {
+ /ZUGFeRDConformanceLevelDescription (The conformance level of the embedded ZUGFeRD data) def
+} if
+ZUGFeRDVersion (2p1) eq {
+ /ZUGFeRDConformanceLevelDescription (The conformance level of the embedded Factur-X data) def
+} if
+
+% ZUGFeRDDocumentFileName
+/ZUGFeRDDocumentFileName () def
+ZUGFeRDVersion (rc) eq {
+ /ZUGFeRDDocumentFileName (ZUGFeRD-invoice.xml) def
+} if
+ZUGFeRDVersion (1p0) eq {
+ /ZUGFeRDDocumentFileName (ZUGFeRD-invoice.xml) def
+} if
+ZUGFeRDVersion (2p0) eq {
+ ZUGFeRDConformanceLevel (XRECHNUNG) ne {
+ /ZUGFeRDDocumentFileName (zugferd-invoice.xml) def
+ }{
+ /ZUGFeRDDocumentFileName (xrechnung.xml) def
+ } ifelse
+} if
+ZUGFeRDVersion (2p1) eq {
+ ZUGFeRDConformanceLevel (XRECHNUNG) ne {
+ /ZUGFeRDDocumentFileName (factur-x.xml) def
+ }{
+ /ZUGFeRDDocumentFileName (xrechnung.xml) def
+ } ifelse
+} if
+
+% ZUGFeRDVersionData
+/ZUGFeRDVersionData () def
+ZUGFeRDVersion (rc) eq {
+ /ZUGFeRDVersionData (RC) def
+} if
+ZUGFeRDVersion (1p0) eq {
+ /ZUGFeRDVersionData (1.0) def
+} if
+ZUGFeRDVersion (2p0) eq {
+ ZUGFeRDConformanceLevel (XRECHNUNG) ne {
+ /ZUGFeRDVersionData (2p0) def
+ }{
+ /ZUGFeRDVersionData (1p2) def
+ } ifelse
+} if
+ZUGFeRDVersion (2p1) eq {
+ ZUGFeRDConformanceLevel (XRECHNUNG) ne {
+ /ZUGFeRDVersionData (1.0) def
+ }{
+ /ZUGFeRDVersionData (1p2) def
+ } ifelse
+} if
+
+/ZUGFeRDMetadata [
+(
+<rdf:Description)
+( xmlns:pdfaExtension="http://www.aiim.org/pdfa/ns/extension/")
+( xmlns:pdfaProperty="http://www.aiim.org/pdfa/ns/property#")
+( xmlns:pdfaSchema="http://www.aiim.org/pdfa/ns/schema#")
+( rdf:about="">
+ <pdfaExtension:schemas>
+ <rdf:Bag>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaSchema:schema>)ZUGFeRDSchema(</pdfaSchema:schema>
+ <pdfaSchema:namespaceURI>)ZUGFeRDNamespaceURI(</pdfaSchema:namespaceURI>
+ <pdfaSchema:prefix>)ZUGFeRDPrefix(</pdfaSchema:prefix>
+ <pdfaSchema:property>
+ <rdf:Seq>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:name>DocumentFileName</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ <pdfaProperty:category>external</pdfaProperty:category>
+ <pdfaProperty:description>Name of the embedded XML invoice file</pdfaProperty:description>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:name>DocumentType</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ <pdfaProperty:category>external</pdfaProperty:category>
+ <pdfaProperty:description>INVOICE</pdfaProperty:description>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:name>Version</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ <pdfaProperty:category>external</pdfaProperty:category>
+ <pdfaProperty:description>)ZUGFeRDVersionDescription(</pdfaProperty:description>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <pdfaProperty:name>ConformanceLevel</pdfaProperty:name>
+ <pdfaProperty:valueType>Text</pdfaProperty:valueType>
+ <pdfaProperty:category>external</pdfaProperty:category>
+ <pdfaProperty:description>)ZUGFeRDConformanceLevelDescription(</pdfaProperty:description>
+ </rdf:li>
+ </rdf:Seq>
+ </pdfaSchema:property>
+ </rdf:li>
+ </rdf:Bag>
+ </pdfaExtension:schemas>
+</rdf:Description>
+<rdf:Description xmlns:)ZUGFeRDPrefix(=")ZUGFeRDNamespaceURI(" rdf:about="">
+ <)ZUGFeRDPrefix(:ConformanceLevel>)ZUGFeRDConformanceLevel(</)ZUGFeRDPrefix(:ConformanceLevel>
+ <)ZUGFeRDPrefix(:DocumentFileName>)ZUGFeRDDocumentFileName(</)ZUGFeRDPrefix(:DocumentFileName>
+ <)ZUGFeRDPrefix(:DocumentType>INVOICE</)ZUGFeRDPrefix(:DocumentType>
+ <)ZUGFeRDPrefix(:Version>)ZUGFeRDVersionData(</)ZUGFeRDPrefix(:Version>
+</rdf:Description>
+)
+ ] concatstringarray def
+
+/Usage {
+ (example usage: \n) print
+ ( gs --permit-file-read=/usr/home/me/zugferd/ \\\n) print
+ ( -sDEVICE=pdfwrite \\\n) print
+ ( -dPDFA=3 \\\n) print
+ ( -sColorConversionStrategy=RGB \\\n) print
+ ( -sZUGFeRDXMLFile=/usr/home/me/zugferd/invoice.xml \\\n) print
+ ( -sZUGFeRDProfile=/usr/home/me/zugferd\rgb.icc \\\n) print
+ ( -sZUGFeRDVersion=2p1 \\\n) print
+ ( -sZUGFeRDConformanceLevel=BASIC \\\n) print
+ ( -o /usr/home/me/zugferd/zugferd.pdf \\\n) print
+ ( /usr/home/me/zugferd/zugferd.ps \\\n) print
+ ( /usr/home/me/zugferd/original.pdf \n) print
+ flush
+} def
+
% First check that the user has defined the XML invoice file on the command line
%
/ZUGFeRDXMLFile where {
@@ -90,7 +354,9 @@ bind def
/ZUGFeRDProfile where {
pop % Discard the dictionary
- % Step 1, add the required PDF/A boilerplate. This is mostly copied from lib/pdfa_de.ps
+ % Step 1, add the required PDF/A boilerplate.
+ % This is mostly copied from lib/pdfa_def.ps
+
% Create a PDF stream object to hold the ICC profile.
[ /_objdef {icc_PDFA} /type /stream /OBJ pdfmark
@@ -157,45 +423,43 @@ bind def
/Type /OutputIntent
/S /GTS_PDFA1 % Required for PDF/A.
/DestOutputProfile {icc_PDFA} % The actual profile.
- /OutputConditionIdentifier (Custom) % A better solution is a string from the ICC Registry, but Custom is always valid.
+ /OutputConditionIdentifier (Custom) % TODO: A better solution is a
+ % a string from the ICC
+ % Registry, but Custom
+ % is always valid.
>> /PUT pdfmark
% And now add the OutputIntent to the Catalog dictionary
[ {Catalog} << /OutputIntents [ {OutputIntent_PDFA} ]>> /PUT pdfmark
-
% Step 2, define the XML file and read it into the PDF
% First we define the PDF stream to contain the XML invoice
[ /_objdef {InvoiceStream} /type /stream /OBJ pdfmark
-
% Fill in the dictionary elements we need. We believe the
% ModDate is not useful so it's just set to a valid value.
[ {InvoiceStream} <<
- /Type /EmbeddedFile
- /Subtype (text/xml) cvn
+ /Type /EmbeddedFile
+ /Subtype (text/xml) cvn
+ % TODO: Determine file length, and add /Length entry
/Params <<
- /ModDate (D:20130121081433+01’00’)
+ /ModDate (D:20130121081433+01'00') % TODO: Determine file date.
>>
>> /PUT pdfmark
-
% Now read the data from the file and store it in the stream
[ {InvoiceStream} ZUGFeRDXMLFile (r) file /PUT pdfmark
-
% and close the stream
[ {InvoiceStream} /CLOSE pdfmark
-
% Step 3 create the File Specification dictionary for the embedded file
% Create the dictionary
[ /_objdef {FSDict} /type /dict /OBJ pdfmark
-
% Fill in the required dictionary elements
[ {FSDict} <<
/Type /FileSpec
- /F ZUGFeRDXMLFile
- /UF ZUGFeRDXMLFile SimpleUTF16BE
+ /F ZUGFeRDDocumentFileName
+ /UF ZUGFeRDDocumentFileName SimpleUTF16BE
/Desc (ZUGFeRD electronic invoice)
- /AFRelationship /Alternative
+ /AFRelationship /Alternative
/EF <<
/F {InvoiceStream}
/UF {InvoiceStream}
@@ -203,114 +467,38 @@ bind def
>>
/PUT pdfmark
-
% Step 4 Create the Associated Files dictionary to hold the FS dict
% Create the dictionary
[ /_objdef {AFArray} /type /array /OBJ pdfmark
-
% Put (append) the FS dictionary into the Associated Files array
[ {AFArray} {FSDict} /APPEND pdfmark
-
% Step 5 Add an entry in the Catalog dictionary containing the AF array
[ {Catalog} << /AF {AFArray} >> /PUT pdfmark
-
% Step 6 use the EMBED pdfmark to add the XML file and FS dictionary to the PDF name tree
- [ /Name ZUGFeRDXMLFile /FS {FSDict} /EMBED pdfmark
-
+ [ /Name ZUGFeRDDocumentFileName /FS {FSDict} /EMBED pdfmark
% Step 7 Add the extra ZUGFeRD XML data to the Metadata
- [ /XML
-(
- <!-- XMP extension schema container for the zugferd schema -->
- <rdf:Description rdf:about=""
- xmlns:pdfaExtension="http://www.aiim.org/pdfa/ns/extension/"
- xmlns:pdfaSchema="http://www.aiim.org/pdfa/ns/schema#"
- xmlns:pdfaProperty="http://www.aiim.org/pdfa/ns/property#">
-
- <!-- Container for all embedded extension schema descriptions -->
- <pdfaExtension:schemas>
- <rdf:Bag>
- <rdf:li rdf:parseType="Resource">
- <!-- Optional description of schema -->
- <pdfaSchema:schema>ZUGFeRD PDFA Extension Schema</pdfaSchema:schema>
- <!-- Schema namespace URI -->
- <pdfaSchema:namespaceURI>urn:ferd:pdfa:invoice:rc#</pdfaSchema:namespaceURI>
- <!-- Preferred schema namespace prefix -->
- <pdfaSchema:prefix>zf</pdfaSchema:prefix>
-
- <!-- Description of schema properties -->
- <pdfaSchema:property>
- <rdf:Seq>!
- <rdf:li rdf:parseType="Resource">
- <!-- DocumentFileName: Name of the embedded file;
- must be equal with the value of the /F tag in the /EF
- structure -->
- <pdfaProperty:name>DocumentFileName</pdfaProperty:name>
- <pdfaProperty:valueType>Text</pdfaProperty:valueType>
- <pdfaProperty:category>external</pdfaProperty:category>
- <pdfaProperty:description>name of the embedded xml invoice file</pdfaProperty:description>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <!-- DocumentType: INVOICE -->
- <pdfaProperty:name>DocumentType</pdfaProperty:name>
- <pdfaProperty:valueType>Text</pdfaProperty:valueType>
- <pdfaProperty:category>external</pdfaProperty:category>
- <pdfaProperty:description>INVOICE</pdfaProperty:description>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <!-- Version: The actual version of the
- ZUGFeRD standard -->
- <pdfaProperty:name>Version</pdfaProperty:name>
- <pdfaProperty:valueType>Text</pdfaProperty:valueType>
- <pdfaProperty:category>external</pdfaProperty:category>
- <pdfaProperty:description>The actual version of the ZUGFeRD data</pdfaProperty:description>
- </rdf:li>
- <rdf:li rdf:parseType="Resource">
- <!-- ConformanceLevel: The actual conformance
- level of the ZUGFeRD standard,
- e.g. BASIC, COMFORT, EXTENDED -->
- <pdfaProperty:name>ConformanceLevel</pdfaProperty:name>
- <pdfaProperty:valueType>Text</pdfaProperty:valueType>
- <pdfaProperty:category>external</pdfaProperty:category>
- <pdfaProperty:description>The conformance level of the ZUGFeRD data</pdfaProperty:description>
- </rdf:li>
- </rdf:Seq>
- </pdfaSchema:property>
- </rdf:li>
- </rdf:Bag>
- </pdfaExtension:schemas>
- </rdf:Description>
-
- <rdf:Description rdf:about="" xmlns:zf="urn:ferd:pdfa:invoice:rc#">
- <zf:DocumentType>INVOICE</zf:DocumentType>
- <zf:DocumentFileName>ZUGFeRD-invoice.xml</zf:DocumentFileName>
- <zf:Version>RC</zf:Version>
- <zf:ConformanceLevel>BASIC</zf:ConformanceLevel>
- </rdf:Description>
-) /Ext_Metadata pdfmark
+ [ /XML ZUGFeRDMetadata /Ext_Metadata pdfmark
}
{
- % No ICC Profile definition on the command line; chide the user and give them an example
- %
- (\nERROR - ZUGFeRDProfile has not been supplied, you must supply an ICC profile\n) print
- ( Producing a potentially invalid PDF/A file!!\n) print
- (example usage - gs --permit-file-read=/usr/home/me/zugferd/ -sDEVICE=pdfwrite -dPDFA=3\\\n) print
- ( -sColorConversionStrategy=RGB -sZUGFeRDXMLFile=/usr/home/me/zugferd/invoice.xml\\\n) print
- ( -sZUGFeRDProfile=/usr/home/me/rgb.icc -o /usr/home/me/zugferd/zugferd.pdf\\\n) print
- ( /usr/home/me/zugferd/zugferd.ps /usr/home/me/zugferd/original.pdf\n\n) print flush
+ % No ICC Profile definition on the command line;
+ % chide the user and give them an example
+ (\nERROR - ZUGFeRDProfile has not been supplied, you must supply an ICC profile) print
+ (\n Producing a potentially INVALID PDF/A file. \n) print
+ Usage
} ifelse
}
{
- % No XML invoice definition on the command line; chide the user and give them an example
- %
- (\nERROR - ZUGFeRDXMLFile has not been supplied, you must supply an XML invoice file\n) print
- ( Producing a PDF/A file not a ZUGFeRD file.\n) print
- (example usage - gs --permit-file-read=/usr/home/me/zugferd/ -sDEVICE=pdfwrite -dPDFA=3\\\n) print
- ( -sColorConversionStrategy=RGB -sZUGFeRDXMLFile=/usr/home/me/zugferd/invoice.xml\\\n) print
- ( -sZUGFeRDProfile=/usr/home/me/rgb.icc -o /usr/home/me/zugferd/zugferd.pdf\\\n) print
- ( /usr/home/me/zugferd/zugferd.ps /usr/home/me/zugferd/original.pdf\n\n) print flush
+ % No XML invoice definition on the command line;
+ % chide the user and give them an example
+ (\nERROR - ZUGFeRDXMLFile has not been supplied, you must supply a XML invoice file) print
+ (\n Producing a PDF/A file, NOT a ZUGFeRD file. \n) print
+ Usage
} ifelse
-% That's all the ZUGFeRD and PDF/A-3 setup completed, all that remains now is to run the input file
+% That's all the ZUGFeRD and PDF/A-3 setup completed,
+% all that remains now is to run the input file
+
+%%EOF \ No newline at end of file