How to make a
PDF file with RPG
These files are demonstrators. They shows what kind of PDF files can be made
with RPG from scratch, only by calling typical PDF procedures. The RPG is
based on the PDF
1.4
reference book (9Mo) (2001-11-29)
Versionning
- 2006-06-11 first publication
- 2008-09-01 Many ehancements
- procedures are now externalized into a service program : JP4PDFS.
This service program is a blender. It is tailored to match your
usual programming architecture It contains only the H specs and
/includes. All the effective code is into three included source
members that may not need update when you will load next version :
- JP4PDFSC : the Code of the procedures
- JP4PDFSD : the private prototypes and Data descriptions
- JP4PDFSP : the Public prototypes and fields
- JP4PDFS offers the availability of PDF ciphering
- JP4PDF1 is obsolete, replaced by JP4PDFS*
- The PdfFile structure is updated : the number of objects is close
to the maxi 64k: >15000 obj
- The deprecated procedures remains in the SRVPGM,
inaccessible, they are there the time to be sure they don't
serve
- The management of the pictures is completely rebuilt :
The PdfPreloadBMP24 and PdfPreloadJpeg procs must be called only one
time per program, and before the first PdfNewFile. it is here
that one gives the name of the file picture
The PdfMemLoadBMP24 and pdfMemLoadJpeg procs replace the
former proc PdfLoadBMP24 and PdfLoadJpeg.
If the PDF is not encrypted, the picture can pass the 64kb
limit.
- The cryptage stumble very brutally on the 64k limit.
It is not a problem for the text but for the pictures.
Lower the quality of JPEG logo bottom to 64kb/5*4 (/5*4 because of
base85 encryption) with PC tools like MS Photo Editor. Got quality
quite acceptable.
- I didn't made a proc to calculate the permissions. A permission is
stupidly the sum of the elementary permissions .
Example: (the required constants are defined int JP4PDFSP) to grant
the right to nothing but the accessibility,
permission = Pdf_Allow_Reset + Pdf_Allow_Extract
- PdfNewFile also has another parameter: Title, to set the
properties of the PDF.
- I had a lot of problem with drag&drop between iNavigator and
explorer of vista.
* repetitive errors with explorer
* Copy mistakes, with errors at Adobe reader file opening
* unattended convertions in Unicode, whereas I didn't ask for
anything
Since I FTP them from the IBMi toward my disk, that goes well
better.
but I always have some mistakes when opening of the pdf . Take care
when transferring PDF files from IFS to elsewhere. a PDF file is a
binary file, not a text file.
- PdfTexStrLen calculate the length of a string : this permits to
make PdfTextRight and PdfTextCenter.
Works only with Helvet font. To do for Courier and Times.
- PdfNewLine returns to the beginning of the following line.
Before it remained aligned on the beginning of the previous
line
Perhaps a bad idea. Remaining aligned to previous line is a pretty
feature.
I will add a procedure something like PdfTextToLeftMargin
- PdfCloseRoot has a parameter: Pagemode. To specify if it is
necessary to display or not the bookmarks (band on left).
by default: none (before, the value was frozen on
UseOutLines)
- PdfNewPage has 4 new parameters, to fix the margins of page,
- that's all for today.
- 2008-10-15 Signature handling
- JP4PDFS has now it's binder to handle the *SRVPGM signature
- RPG code to blend all the includes is now JP4PDFS_M
- I've restored PdfTextNewLine to it's previous pretty feature : stay
vertically aligned to previous line.
- So there is a new proc : PdfTextToLeft to provide the missing
feature : going back to left margin.
- 2009-10-14 .
- PdfPalette a wide range of color, native PDF colors
- new functions to handle colors :PdfSetColorRGB, PdfSetColorCMYK,
PdfSetColorHTML, PdfStrmFillingColorHTML, PdfStrmStrokingColorHTML.
- 2009-11-01.
- new function PdfPie. This function permits to draw PieCharts. This
function is a fondation function, and need to be embedded in a
function of higher level of abstraction.
- PdfTextStrLen now compute string size under Helvet, Time, Courier
ans Zapf fonts. The demonstrator program PDFCHARSET shows the name and
the size of each character under each reader's font.
- 2010-05-02.
- A bunch of new functions to draw charts :
- PDFCALCARC
- PDFCALCCONCAVE
- PDFCALCCONVEXE
- PDFCALCULATETICKS
- PDFCHARTFREE
- PDFCHARTINIT
- PDFDRAWADDARC
- PDFDRAWADDCONCAVE
- PDFDRAWADDCONVEXE
- PDFDRAWADDCORONA
- PDFDRAWADDDAISY
- PDFDRAWCHART
- PDFEDIT
- PDFELEMENTADD
- PDFSERIECLOSE
- PDFSERIEOPEN
- PDFSERIESINIT
- PDFSTYLE
- They permit to draw these kind of charts : PdfChart (don't
focus
on colors, they are choosed randomly. Not ugly; but not artistic)
- 2010-10-22
- correction on PdfTextStrLen. The embbeded %trim has undesired side
effects, such as returning zero for a string full of space. Space
(in chars) need space (in pixels). PdfTextStrLen is splitted in
two functions :
- first, PdfTextSTrLen, does not do the %trim so it does the
computation on the full transmitted string, space included
- second, PdfTextFStrLen trims the transmetted string and return the
length of the trimmed string.
- 2010-11-11
- correction on PdfLoadJpeg for image bigger than 64K
- 2012-04-01
- Barcode for code128, 2
of
5 and code39, RPG code by Martin Lorang
Chart sample (needs version 2010-05-22) :
last version : The SaveFiles
PdfPalette.pdf, the PDF color palette, under
different presentations.
PdfPaletteCMYK.pdf same, but using CMYK
device.
PdfCharacterSet.pdf Character name and
size, for each internal font of the PDF Reader.
Before compiling JP4PDFD* programs, update the target PDF file names. They are currently located to /home/lamontre: change these 7 lines:
Jpl =pdfpreloadjpeg ('/Home/Lamontre/jpl.jpg');
Logo =pdfpreloadjpeg ('/Home/Lamontre/logo.jpg');
bmp = pdfpreloadbmp24('/Home/Lamontre/rgb.bmp' );
IfsName='/Home/Lamontre/Pdf5a.pdf';
IfsName='/Home/Lamontre/Pdf5b.pdf';
IfsName='/Home/Lamontre/Pdf5c.pdf';
IfsName='/Home/Lamontre/Pdf5d.pdf';
the thee pictures are here:
jpl.jpg
logo.jpg
rgb.bmp
The JP4PDFD* rpg progs are demonstrators. They shows how to make PDF
files in RPG from scratch, only by calling typical PDF procedures. These
tools have been made based on the PDF
1.4
reference book (9Mo) (2001-11-29) Compressed version available
at Adobe
site
Nota : read the chapter 1.4 Intellectual Property. As I have
understoud, (i'm not fluent in english) anyone can build a PDF file with
general Adobe permission. Anyone who uses the copyrighted list of data
structures and operators, as stated above [in the Intellectual
property chapter], must include an appropriate copyright notice.
Produced file :
Pdf5 is made by JP4PDFD. Password is "user" (without
the quotes). This PDF uses most of the directives proposed by JP4PDFS.
The demonstrator shows most tools to work with text and
transformation, and also show mixing pictures and text.
Questions I have received
Rotation
Question received 2009-03-27
This question comes from the SystemINetwork forum : http://forums.systeminetwork.com/isnetforums/showthread.php?t=53991
Hi
I've been writing PDFs from within RPG for some time now using the
excellent examples from JPL as a basis. I've just tried to introduce the
rotation function and I'd really appreciate a bit of help as to why I
cannot get it to work properly. The code below is an extract from my code
which successfully prints Rotate 1 correctly at an angle, but totally
ignores the instruction to print Rotate 2. It then goes on to happily
print further text without rotation.
Any help would be greatly appreciated, as always.
Regards
Paul
myDraw='';
myText='';
myText = myText +
PdfTextOpen();
//
test
MyText+=PdfStrmSaveGraphicState();
myText+=PdfStrmRotate(330);
MyText+=PdfTextGoTo(020:400);
MyText+=PdfTextFont(PdfCourier:60);
MyText+=PdfTextadd('Rotate
1');
myText+=PdfStrmRotate(180);
MyText+=PdfTextGoTo(022:420);
MyText+=PdfTextFont(PdfCourier:60);
MyText+=PdfTextadd('Rotate
2');
MyText+=PdfStrmRestoreGraphicState();
Answer
There are many things to say to comment the PdfReader's issues.
Note : FoxitReader is less sensitive to errors than AdobeReader
You should test your programs with these two readers.
So, what happens ?
There is a physical error
If this PDF has a page after this test page, when you try to read this
next page, Adobe send a message saying that there is an error on the page.
What does that means ?
This means Adobe is completely lost, so it has ignored some dirty code.
Why is it lost ?
Because there are page instruction into text instruction.
Page instructions are generated by PdfStrm* functions
Text instruction are generated by PdfText* functions
In the resulting stream
(MyStream=mydraw+mytext;)
Text instruction always starts with a PdfTextOpen() and are closed by a
PdfTextClose().
Opposite, Draw instructions are more tolerant.
You can mix PdfStrm* with PdfDraw* instructions with far less issues.
But issues are not excluded.
When you start using PdfDrawAdd* instructions, take care of using a
PdfDrawClose*
There is also a logical error
The origin of each page is, just after PdfNewPage(), at bottom left.
You can PdfDrawGoto or PdfTextGoto as much as you want, this does not
change the coordinates of the point of origin
Rotate is in the PdfStrm instruction group.
Rotate is applied on the whole page.
This means that, in your test,
the things you do are
* NewPage
- stick a tack at (0,0) IE at the bottom left of the page
- set your pencil at (0,0)
* Rotate 300
- set your pencil up
- rotate the page, depending on the tack, to the left of 30 degrees
- set your pencil down
* goto 20 : 400
* add "Rotate 1"
- write "Rotate 1"
As you can see in your PDF, the text is visible but probably not at
the place you was waiting it.
* Rotate 180
- set your pencil at (0,0)
- set your pencil up
- rotate the page, depending on the tack, to the right of 180 degrees
Try it youself with a true paper sheet : you have your pencil out
of the paper
- set your pencil down
* add "Rotate 2"
- write "Rotate 2"
You write out of the paper
Try this
myDraw='';
myText='';
// avoid mixing PdfText* and
PdfDraw* in the same stream,
// this too much times results in a
dirty PDF file
MyText+=PdfStrmTranslate(200:500);
MyText+=PdfDrawAddrectangle(000:000:400:100);
MyText+=PdfDrawClosePath(pdf_stroke);
myText+=PdfTextOpen();
MyText+=PdfTextGoTo(020:040);
MyText+=PdfTextFont(PdfCourier:12);
MyText+=PdfTextadd('123');
MyText+=PdfTextClose();
myText+=PdfStrmRotate(330);
MyText+=PdfDrawAddrectangle(000:000:400:100);
MyText+=PdfDrawClosePath(pdf_stroke);
myText+=PdfTextOpen();
MyText+=PdfTextGoTo(020:040);
MyText+=PdfTextFont(PdfCourier:12);
MyText+=PdfTextadd('456');
MyText+=PdfTextClose();
myText+=PdfStrmRotate(180);
MyText+=PdfDrawAddrectangle(000:000:400:100);
MyText+=PdfDrawClosePath(pdf_stroke);
myText+=PdfTextOpen();
MyText+=PdfTextGoTo(020:040);
MyText+=PdfTextFont(PdfCourier:12);
MyText+=PdfTextadd('789');
MyText+=PdfTextClose();
MyStream=PdfStrmSaveGraphicState()
+
mydraw+mytext
+
PdfStrmRestoreGraphicState();
Blank text
I've set the text with PdfTextAdd, I can select it under Adobe reader,
but it shows blank text.
I can see the text correctly with Foxit
There is a missing PdfTextClose after the PdfTextAdd.