
Just tested it by creating a 300 pages report.... and only 4mb of page file was consumed that was freed right after the end of the procedure!!!
Btw CPU usage has also improved, instead of 80% it dropped to 1% !!!
Hurray!
Excelent work Lucky !

Code: Select all
Procedure pdf_MultiCellBasic(w.f,h.f,txt.s,border.f,align.s,fill.f, indent.w)
Protected wMax.f, wMaxOther.f, wFirst.f, wOther.f, wMaxFirst.f
Protected s.s
Protected nb.l
Protected first.b
Protected savex.f
;Output text with automatic Or explicit line breaks
If(w=0)
w=pdf()\w - pdf()\fRightMargin - pdf()\x
EndIf
wFirst = w - indent
wOther = w
wmaxFirst = (wFirst-2*pdf()\fCellMargin)*1000/pdf()\fFontSize
wmaxOther = (wOther-2*pdf()\fCellMargin)*1000/pdf()\fFontSize
s = ReplaceString(txt, "\r","")
nb = Len(s)
If(nb>0 And Right(s,1) = Chr(13))
nb = nb - 1
EndIf
b = 0
If border <> 0
If(border=1)
border= #borderl + #borderr + #bordert + #borderb
b= #borderl + #borderr + #bordert
b2=#borderl + #borderr
Else
b2=0
If FindString("-1-4-6-9-11-14-16-19", Str(border),1) > 0
b2=b2+#borderl
EndIf
If FindString("-3-4-8-9-13-14-18-19", Str(border),1) > 0
b2=b2+#borderr
EndIf
If FindString("-5-6-8-9-15-16-18-19", Str(border),1) > 0
b2=b2+#bordert
EndIf
b=b2
EndIf
EndIf
sep=-1
i=1
j=0
l=0
ns=0
nl=1
c.s
first=#TRUE
While(i<nb)
;Get Next character
c = Mid(s,i,1)
If c = Chr(10)
;Explicit line Break
If(pdf()\ws>0)
pdf()\ws=0
_outstring("0 Tw")
EndIf
pdf_Cell7(w,h,Mid(s,j,i-j),b,2,align,fill)
i = i + 1
sep = -1
j=i
l=0
ns=0
nl= nl +1
If nl=2 And border <>0
b=b2
EndIf
Continue
EndIf
If(c=" ")
sep = i
ls = l
ns=ns+1
EndIf
l=l+fonts()\wCharWidth[Asc(c)]
If first = #TRUE
wmax = wmaxFirst
w = wFirst
Else
wmax = wmaxother
w = wother
EndIf
If l>wmax
;Automatic line Break
If(sep=-1)
If(i=j)
i = i +1
EndIf
If(pdf()\ws>0)
pdf()\ws=0
_outstring("0 Tw")
EndIf
savex = pdf()\x
If (first = #TRUE And indent >0)
pdf_SetX(pdf()\x + indent)
first = #FALSE
EndIf
pdf_Cell7(w,h,Mid(s,j,i-j),b,2,align,fill)
If (first = #FALSE)
pdf_SetX(savex)
EndIf
Else
If(align="J")
If (ns>1)
pdf()\ws = (wmax-ls)/1000*pdf()\ffontsize/(ns-1)
Else
pdf()\ws = 0
EndIf
_outstring(StrF(pdf()\ws*pdf()\k,3) + " Tw")
EndIf
savex = pdf()\x
If (first=#TRUE And indent > 0)
pdf_SetX(pdf()\x + indent)
first = #FALSE
EndIf
pdf_Cell7(w,h,Mid(s,j,sep-j),b,2,align,fill)
If (first = #FALSE)
pdf_SetX(savex)
EndIf
i=sep +1
EndIf
sep=-1;
j=i;
l=0;
ns=0;
nl = nl +1
If(border <> 0 And nl=2)
b=b2;
EndIf
Else
i=i+1
EndIf
Wend
;Last chunk
If(pdf()\ws>0)
pdf()\ws=0
_outstring("0 Tw");
EndIf
If FindString("-10-11-13-14-15-16-18-19", Str(border),1) > 0 And border <> 0
b=b+#borderb
EndIf
pdf_Cell7(w,h,Mid(s,j,i-j + 1),b,2,align,fill)
pdf()\x=pdf()\fLeftMargin;
EndProcedure
Code: Select all
Global encrypted.b
Global *padding.l
Global Ovalue$
Global Uvalue$
Global Pvalue.b
Global enc_obj_id.l
Global encryption_key$
Global pCompress.l
Code: Select all
Procedure _PutTrailer()
_outstring("/Size " + Str(pdf()\wObjNum + 1))
_outstring("/Root " + Str(pdf()\wObjNum) + " 0 R")
_outstring("/Info " + Str(pdf()\wObjNum - 1) + " 0 R")
If encrypted
;$this->_out('/Encrypt '.$this->enc_obj_id.' 0 R');
_outstring("/Encrypt " + Str(enc_obj_id) + " 0 R")
;$this->_out('/ID [()()]');
_outstring("/ID [()()]")
EndIf
EndProcedure
Procedure _PutStream(*aData.strData)
tmpSize=*aData\lCurSize
If encrypted
_RC4(*aData\pData, tmpSize, _objectkey(pdf()\wObjNum))
EndIf
_outstring("stream")
_OutStream(*aData)
_outstring("endstream")
EndProcedure
Procedure.s _TextString(as.s)
Protected lsResult.s
If encrypted
_RC4(@as,Len(as),_objectkey(pdf()\wObjNum))
EndIf
; Format a text string
lsResult = "(" + _escape(as) + ")"
ProcedureReturn lsResult
EndProcedure
Procedure _PutResources()
_PutFonts()
_PutImages()
;Resource dictionary
SelectElement(Offsets(),1)
Offsets() = sBuffer\lCurSize
_outstring("2 0 obj")
_outstring("<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]")
_outstring("/Font <<")
ForEach Fonts()
_outstring("/F" + Str(Fonts()\bFontNum) + " " + Str(Fonts()\wObjNum) + " 0 R")
Next
_outstring(">>")
If (CountList(Images()) > 0)
_outstring("/XObject <<")
ForEach Images()
_outstring("/I" + Str(Images()\bImageNum) + " " + Str(Images()\wObjNum) + " 0 R")
_outstring(">>")
Next
EndIf
_outstring(">>")
_outstring("endobj")
_putBookMarks()
If pdf()\sJavaScript <> ""
_PutJavascript()
EndIf
If encrypted
_NewObj()
enc_obj_id = pdf()\wObjNum
_outstring("<<")
_putencryption()
;_outstring(">>")
EndIf
EndProcedure
Code: Select all
Procedure _putencryption()
_outstring("/Filter /Standard")
_outstring("/V 1");
_outstring("/Length 40");
_outstring("/R 2");
_outstring("/O (" + _escape(Ovalue$) + ")")
_outstring("/U (" + _escape(Uvalue$) + ")")
_outstring("/P " + Str(Pvalue))
_outstring(">>")
_outstring("endobj")
EndProcedure
Procedure.l _RC4(Mem.l, memLen.l, key.s)
;RC4Mem(*MemoryBuffer.l, MomeryLength.l, Key.s)
Dim S.l(255)
Dim K.l(255)
i.l=0: j.l=0: t.l=0: x.l=0
temp.l=0: y.l=0
j = 1
l.l =Len(key)
*Sp.LONG = @S()
*keyP.BYTE = @key
For i = 0 To 255
*Sp\l = i
*Sp + 4
If *keyP\b = 0
*keyP = @key
EndIf
K(i) = *keyP\b
*keyP+1
Next i
j = 0
For i = 0 To 255
j = (j + S(i) + K(i)) & 255
temp = S(i)
S(i) = S(j)
S(j) = temp
Next i
i = 0
j = 0
*Memm.BYTE = Mem
For x = 0 To memLen-1
i = (i+1) & 255
j = (j + S(i)) & 255
temp = S(i)
S(i) = S(j)
S(j) = temp
t = (S(i) + (S(j) & 255)) & 255
y = S(t)
*Memm\b ! y
*Memm + 1
Next
ProcedureReturn Mem
EndProcedure
Procedure.l hexdec(h$)
; h$ can be 0-FFFFFFF.
;chars=Len(h$)
h$=UCase(h$)
For r=1 To 2;chars
d<<4 : a$=Mid(h$,r,1)
If Asc(a$)>60
d+Asc(a$)-55
Else
d+Asc(a$)-48
EndIf
Next
ProcedureReturn d
EndProcedure
Procedure.s _md5_16(*txt,txt_len)
Shared ret$
tmp$ = MD5Fingerprint(*txt,txt_len)
ret$=""
For i = 1 To 32 Step 2
;$out.=chr(hexdec(substr($tmp,$i,2)))
ret$ + Chr(hexdec(Mid(tmp$,i,2)))
Next
ProcedureReturn ret$
EndProcedure
Procedure.s _OValue(*U, *O)
*tmpU=AllocateMemory(32)
CopyMemory(*U,*tmpU,32)
tmp$ = _md5_16(*O, 32)
owner_RC4_key$ = Mid(tmp$,1,5)
ProcedureReturn PeekS(_RC4(*tmpU, 32, owner_RC4_key$),32)
EndProcedure
Procedure _generateencryptionkey(user_pass$, owner_pass$, protection)
*UPass.l = AllocateMemory(33)
*OPass.l = AllocateMemory(33)
LenUPass= Len(user_pass$)
If LenUPass < 32
CopyMemory(@user_pass$,*UPass,LenUPass)
CopyMemory(*padding,*UPass+LenUPass,32-LenUPass)
Else
CopyMemory(@user_pass$,*UPass,32)
EndIf
LenOPass= Len(owner_pass$)
If LenOPass < 32
CopyMemory(@owner_pass$,*OPass,LenOPass)
CopyMemory(*padding,*OPass+LenOPass,32-LenOPass)
Else
CopyMemory(@owner_pass$,*OPass,32)
EndIf
; Compute O value
Ovalue$ = _OValue(*UPass, *OPass)
*tmp = AllocateMemory(32+32+4+1)
tmp$ = Chr(protection) + Chr(255) + Chr(255) + Chr(255)
CopyMemory(*UPass,*tmp,32):CopyMemory(@Ovalue$,*tmp+32,32):PokeS(*tmp+64,tmp$,Len(tmp$))
tmp$ = _md5_16(*tmp,68)
encryption_key$ = Mid(tmp$,1,5)
; Compute U value
Uvalue$ = Space(32)
tmpmem = AllocateMemory(32)
CopyMemory(*padding, tmpmem, 32)
tmpmem = _RC4(tmpmem, 32, encryption_key$)
CopyMemory(tmpmem, @Uvalue$, 32)
Pvalue = protection ; -((protection ! 255)+1)
EndProcedure
Procedure _SetProtection(permission, user_pass$ ,owner_pass$);$permissions=array(),
; Procedure to set permissions as well as user and owner passwords
;
; - permissions is an array with values taken from the following list:
; copy, print, modify, annot-forms
; If a value is present it means that the permission is granted
; - If a user password is set, user will be prompted before document is opened
; - If an owner password is set, document can be opened in privilege mode with no
; restriction if that password is entered
;$options = array('print' => 4, 'modify' => 8, 'copy' => 16, 'annot-forms' => 32 );
protection.l = permission
encrypted = #True
_generateencryptionkey(user_pass$, owner_pass$, protection)
EndProcedure
Procedure.s _objectkey(n)
encKeyLen=Len(encryption_key$)
Debug "encKeyLen= " + Str(encKeyLen)
*tmp=AllocateMemory(encKeyLen+5)
CopyMemory(@encryption_key$,*tmp,encKeyLen)
PokeL(*tmp+encKeyLen,n)
PokeW(*tmp+encKeyLen+3,0)
ProcedureReturn Mid(_md5_16(*tmp,encKeyLen+5),1,10)
EndProcedure
Procedure pdf_Protection()
encrypted=#False;
last_rc4_key$="";
*padding = ?PaddingString
EndProcedure
Code: Select all
DataSection
PaddingString:
Data.b 40, 191, 78, 94, 78, 117, 138, 65, 100, 0, 78, 86, 255, 250, 1, 8
Data.b 46, 46, 0, 182, 208, 104, 62, 128, 47, 12, 169, 254, 100, 83, 105,122
Code: Select all
;#########################################
;Example with compression and protection #
;#########################################
txt$="01234456789 01234456789 01234456789 01234456789 01234456789 01234456789 01234456789 "
pdf_Init()
pdf_Protection()
; Info from PDFReference for permissions bit setting
; 1–2 Reserved; must be 0.
; 3 (Revision 2) Print the document.
; (Revision 3) Print the document (possibly not at the highest quality
; level, depending on whether bit 12 is also set).
; 4 Modify the contents of the document by operations other than
; those controlled by bits 6, 9, and 11.
; 5 (Revision 2) Copy or otherwise extract text and graphics from the
; document, including extracting text and graphics (in support of accessibility
; to disabled users or for other purposes).
; (Revision 3) Copy or otherwise extract text and graphics from the
; document by operations other than that controlled by bit 10.
; 6 Add or modify text annotations, fill in interactive form fields, and,
; if bit 4 is also set, create or modify interactive form fields (including
; signature fields).
; 7–8 Reserved; must be 1.
; 9 (Revision 3 only) Fill in existing interactive form fields (including
; signature fields), even if bit 6 is clear.
; 10 (Revision 3 only) Extract text and graphics (in support of accessibility
; to disabled users or for other purposes).
; 11 (Revision 3 only) Assemble the document (insert, rotate, or delete
; pages and create bookmarks or thumbnail images), even if bit 4 is
; clear.
; 12 (Revision 3 only) Print the document to a representation from
; which a faithful digital copy of the PDF content could be generated.
; When this bit is clear (and bit 3 is set), printing is limited to a lowlevel
; representation of the appearance, possibly of degraded quality.
; (See implementation note 20 in Appendix H.)
; 13–32 (Revision 3 only) Reserved; must be 1.
;Bit No 21 987654321 987654321 987654321
permission.l=%11111111111111111111000011000000
_SetProtection(permission,"","xyz0815")
pdf_OpenBasic("P","mm","a4")
_ZlibInit()
pdf_SetCompression(@_GzCompress())
pdf_AddPage()
pdf_SetFont3("Arial","",12)
For i = 1 To 8000
pdf_Cell3(40,10,txt$)
pdf_Ln()
Next
pdf_Close()
pdf_Save("c:\test\Tutorial1.pdf")
New version of PurePDF available.If you need to do initialization operations at program start whenever your library is used, or clean/shutdown operations, you must use two special prefixes in two functions: _Init and _End. These functions can take no arguments, nor can they any values. Use only one _Init function and/or one _End function per library.
Sorry, should be "suffixes", not "prefixes", of course. Changed.From the Tailbite help file :
Quote:
If you need to do initialization operations at program start whenever your library is used, or clean/shutdown operations, you must use two special prefixes in two functions: _Init and _End. These functions can take no arguments, nor can they any values. Use only one _Init function and/or one _End function per library.
Fixed the problem with the Polink error.has someone a working userlibrary "zlib" for PB3.91 ?
My is reporting "POLINK: error: Unresolved external symbol '_errno'."
Code: Select all
Procedure.b _GzCompress(*aData.strData)
Protected zerr.b
Protected CompMem.l
Protected SourceLen.l
Protected SourceMem.l
Protected CompLen.l
Protected lbError.b
lbError = #False
SourceLen = *aData\lCurSize
SourceMem = *aData\pData
CompLen.l = SourceLen + SourceLen/1000 + 16
CompMem=AllocateMemory(CompLen)
If CompMem
zerr=Zcompress2(CompMem, @CompLen, SourceMem, SourceLen,#Z_DEFAULT_COMPRESSION)
If zerr = #Z_OK
*aData\pData = CompMem
*aData\lMaxSize = CompLen
*aData\lCurSize = CompLen
;FreeMemory(SourceMem)
lbError = #True
EndIf
EndIf
ProcedureReturn lbError
EndProcedure