PurePDF Version 2.0

Developed or developing a new product in PureBasic? Tell the world about it.
normeus
Enthusiast
Enthusiast
Posts: 414
Joined: Fri Apr 20, 2012 8:09 pm
Contact:

Re: PurePDF Version 2.0

Post by normeus »

[EDIT 10/11/2016]
Last edit on this one. I had a chance to work on this so it should now work Unicode, ASCII
and string replacement is functional (i.e. using {nb} ) I didn't change this post so that the chain of posts after it makes sense. For code see post:
http://www.purebasic.fr/english/viewtop ... 65#p495665

[EDIT 10/10/2016]
1. use Chr(14) instead of Chr(16)
2. I also changed the code on the HACK please download it again.
(This will work with Unicode ASCII Unicode font and ASCII font )
( I don't have the time to fix Unicode string compare and that's why a single char replacement string
is currently the workaround )
see edit 9/25/2016

[EDIT 9/25/2016]
For the footer to be displayed with any font you'll have to change the replacement string to a single char.

Add this to your pdf create page: ( I am using chr(14) as the replacement string

Code: Select all

pdf_AliasNbPages(Chr(14))
and the Footer procedure should be also changed to the same single char string:

Code: Select all

Procedure Footer()
  Protected ftext.s="Page "+Str(pdf_GetPageNo())+"/"+Chr(14)
  pdf_SetY(-15);
  pdf_SetFont("MS Sans Serif","I",10)
  pdf_Cell(0,10,ftext,0,0,#PDF_ALIGN_CENTER);
EndProcedure
@Lord's code works in mysterious ways.

[EDIT]
After reading all 28 pages of messages, I saw that unicode works.
You have to use a font which contains the characters you are going to use.
here is a fix ( more like a hack ) for footer numbers not printing right in unicode. Replace this procedure in "PurePDF.pb" which forces footer numbers to be ascii:
[EDIT CODE FROM 10/10/2016]

Code: Select all

Procedure MEM_DataReplace(*aData.MEM_DataStructure, aSource.s, aDest.s)
  Protected vSourceLen,vDestLen,vCurSize,vMaxSize,vCount,vFind,*tmp,vReturn,i,j,*vaSource
  Protected vLen,*vaDest,vaDestString ; Needed to HACK unicode to ASCII
  
  vSourceLen   = StringByteLength(aSource); changed to StringByteLength for unicode
  *vaSource    = AllocateMemory(vSourceLen); created a temp buffer for unicode
  PokeS(*vaSource,aSource,vSourceLen,#PB_String_NoZero|#PB_Ascii);saved string to mem to compare mem not string ; HACK - copy string to buffer IN ASCII because MEM_DataStructure is ASCII
  vLen = SizeOf(Character)   ; find out if unicode or ASCII to HACK code
  vSourceLen=vSourceLen/vlen ; HACK - if unicode cutdown size to ascii
                 
                 
  vDestLen     = StringByteLength(aDest) ; changed to StringByteLength
  *vaDest=AllocateMemory(vDestLen)     ; HACK - needed to change number to ASCII
  PokeS(*vaDest,aDest,vDestLen)

  vCurSize     = *aData\lCursize  
  vMaxSize     = *aData\lMaxsize  
  vFind        = 0
  vReturn      = #True


  If (vDestLen > vSourceLen)
    For i = vCurSize To 0 Step -1
      vCount= 0
      For j = 0 To vSourceLen-1
        If PeekB(*aData\pData + i - vSourceLen + j ) = PeekB(*vaSource+j)
          vCount = vCount + 1
        EndIf
      Next 
      If vCount = vSourceLen   
         vFind = vFind + 1   
      EndIf
    Next
    If (vFind > 0)
      vReturn = MEM_DataInit(*aData, vMaxSize + (vFind*(vDestLen - vSourceLen))) ; = #False
    EndIf  
  EndIf
  
  If vReturn = #True
    *tmp = AllocateMemory((vDestLen + vCurSize) - vSourceLen)
    If *tmp
      For i = vCurSize To 0 Step -1
        vCount= 0
        For j = 0 To vSourceLen-1
          If PeekB(*aData\pData + i - vSourceLen + j ) = PeekB(*vaSource+j)
            vCount = vCount + 1
          EndIf
        Next

        If vCount = vSourceLen
          CopyMemory(*aData\pData + i, *tmp, *aData\lCurSize - i)
          ; CopyMemory(@aDest, *aData\pData + i - vSourceLen , vDestLen) ; this one will work when the unicode issue gets solved
          CopyMemory(*vaDest, *aData\pData + i - vSourceLen , vDestLen ) ; HACK - using new ASCII sized location
          CopyMemory(*tmp, *aData\pData + (i-(vLen-1)) - vSourceLen + vDestLen, *aData\lCurSize - i) ; COPY according to ASCII or UNICODE
          *aData\lCurSize = *aData\lCurSize + (vDestLen-vSourceLen)
        EndIf
      Next
      FreeMemory(*tmp)
    Else
      vReturn = #False
    EndIf
  EndIf
  FreeMemory(*vaSource) ; used to search as memory and not string
  FreeMemory(*vaDest) ; HACK to change to ASCII
  ProcedureReturn vReturn
EndProcedure
Norm.
Last edited by normeus on Wed Oct 12, 2016 1:37 am, edited 4 times in total.
google Translate;Makes my jokes fall flat- Fait mes blagues tombent à plat- Machte meine Witze verpuffen- Eh cumpari ci vo sunari
normeus
Enthusiast
Enthusiast
Posts: 414
Joined: Fri Apr 20, 2012 8:09 pm
Contact:

Re: PurePDF Version 2.0

Post by normeus »

Tutorial07 Images.pdf which creates two links to same spot does not work because the link is kept in a LIST so there is only one link for each set link; anyway here is a fix until ABBKlaus comes back and takes care of this.
Replace this procedure which will allow you to have multiple links pointed to same spot. ( like a link which goes back to a line on the first page of a multiple page document and you use it like a back button)

Code: Select all

Procedure ipdf_Link(X.f, Y.f, W.f, H.f, Link.l)
  Protected PLType,PLDestPage,PLy,PL1$
  If Link>0
    SelectElement(PageLinks(), Link-1)
    ;If this link was used before copy data and create a new link
    ;This will work with pages and URLS only 
    If PageLinks()\Page>0
      PLType=PageLinks()\Type
      PLDestPage=PageLinks()\DestPage
      PLy=PageLinks()\y
      PL1$=PageLinks()\Option1$
      AddElement(pagelinks())
      PageLinks()\Type = PLType
      PageLinks()\DestPage = PLDestPage
      PageLinks()\Y = PLy
      PageLinks()\Option1$ = PL1$
    EndIf
    If pdfCurOrientation$="P"
      PageLinks()\fA0 = x*pdfK
      PageLinks()\fA1 = pdfFhPt - y*pdfK
      PageLinks()\fA2 = w*pdfK
      PageLinks()\fA3 = h*pdfK
      PageLinks()\Page = pdfPage
    Else
      PageLinks()\fA0 = x*pdfK
      PageLinks()\fA1 = pdfFwPt - y*pdfK
      PageLinks()\fA2 = w*pdfK
      PageLinks()\fA3 = h*pdfK
      PageLinks()\Page = pdfPage
    EndIf
  EndIf
EndProcedure
and this is a sample of linking back to top page which will work after you replace the previous procedure in "PurePDF.pb":

Code: Select all

#PurePDF_Include=1
XIncludeFile "PurePDF.pb"


pdf_Create()
pdf_AddPage()
pdf_SetFont("Arial","",20)
Define linkr = pdf_Addlink()
pdf_SetLink(linkr,-1,-1)

pdf_Write(5,"COME BACK HERE ",linkr)



Define file$="Tutorial07A Images links.pdf"
pdf_AddPage()
pdf_Image("PurePDFLogo.png",10,10,30,0,linkr)
pdf_AddPage()
pdf_Image("PurePDFLogo.jpg",10,10,190,0,linkr)
pdf_addpage()
pdf_Write(5,"BACK to top ",linkr)

pdf_Save(file$)
RunProgram(file$)
Thank you.
Norm
collectordave
Addict
Addict
Posts: 1309
Joined: Fri Aug 28, 2015 6:10 pm
Location: Portugal

Re: PurePDF Version 2.0

Post by collectordave »

Hi all just joined.

Is purepdf.pb still available with an example?

Gratefull for any help
Any intelligent fool can make things bigger and more complex. It takes a touch of genius — and a lot of courage to move in the opposite direction.
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Re: PurePDF Version 2.0

Post by ts-soft »

collectordave wrote:Is purepdf.pb still available with an example?
http://www.purebasicpower.de/?PurePDF
PureBasic 5.73 | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.
Image
collectordave
Addict
Addict
Posts: 1309
Joined: Fri Aug 28, 2015 6:10 pm
Location: Portugal

Re: PurePDF Version 2.0

Post by collectordave »

Brilliant

Thanks
Any intelligent fool can make things bigger and more complex. It takes a touch of genius — and a lot of courage to move in the opposite direction.
infratec
Always Here
Always Here
Posts: 6817
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: PurePDF Version 2.0

Post by infratec »

normeus
Enthusiast
Enthusiast
Posts: 414
Joined: Fri Apr 20, 2012 8:09 pm
Contact:

Re: PurePDF Version 2.0

Post by normeus »

error codes in the help file should read:

Code: Select all

Possible values are:
- 1 = 16-bit depth PNG not supported.
- 2 = Alpha channel PNG not supported.
- 3 = Unknown compression PNG method.
- 4 = Unknown filter PNG method.
- 5 = Interlacing PNG not supported.
- 6 = Missing palette in PNG.
- 7 = This JPEG file is not supported
- 8 = Can't open image file
- 9 = Problem reading image file in memory
-10 = JFIF marker is missing
-11 = Not a JPEG file.
-12 = Incorrect PNG file.
-13 = Incorrect WMF file
-14 = Not a JPEG or PNG file.
-15 = Filename is not correct.
-16 = Can't create the file. 
-17 = File open error.
-18 = Out of memory. 
-19 = Bookmark Error
Currently if you save a pdf and there is an error, memory gets cleared and you have to generate the pdf in memory again.
it would be nice to be notified of the error and be able to save the pdf you have in memory.

This is a 3 step hack but you can get away with just doing the 1st step

step 1. change the save procedure, it is around line 4300 of purePDF.pb

Code: Select all

Procedure ipdf_Save(FileName$)
  Protected File,cbBytes
  ipdf_Close()
  pdfState=3
  If Len(FileName$)>0 And pdfError<>#PDF_ERROR_OUT_OF_MEMORY
    If CheckFilename(GetFilePart(Filename$)) = 1
      File=CreateFile(#PB_Any, FileName$)
      If File
        WriteData(File,pdfBuffer\pData, pdfBuffer\lCurSize)
        CloseFile(File)
      Else
        pdfError = #PDF_ERROR_ERROR_CREATING_FILE
        ProcedureReturn #False
      EndIf      
    Else
      pdfError = #PDF_ERROR_FILENAME_IS_NOT_CORRECT
      ProcedureReturn #False 
    EndIf
  EndIf
  If pdfBuffer\pData
    FreeMemory(pdfBuffer\pData)
  EndIf
  pdfBuffer\pData=0
  pdfState=0
  pdferror=0
  ProcedureReturn #True
EndProcedure
This will avoid deleting the pdf in memory so all you have to do is check pdf_GetErrorCode() Thus:

Code: Select all

pdf_Save(file$)
if pdf_GetErrorCode() = 15 or pdf_GetErrorCode() =16   ;error codes I got from help file
   ;file couldn't be created. request a new file and do pdf_Save() with new file name. Disco
   File$ = SaveFileRequester("Please choose file to save", file$, "*.pdf", 0)
   pdf_Save(file$) ; test for error codes again etc...
endif
Step 2. lets clean up a bit, again; this is not needed if you are careful checking pdf_GetErrorCode() every time you
save a pdf. This is for people like me who would open an new pdf assuming the last one worked fine.

search for ipdf_Create and add an "if" statement testing to see if there is a pdf that failed to save and if so dont create
a new pdf

Code: Select all

Procedure ipdf_Create(Orientation$="", Unit$="", Format$="")
  Protected lfMargin.f,mode,vBias
  If pdfState=3
    ProcedureReturn #False
  EndIf
now when you create a new pdf make sure it was created

Code: Select all

if pdf_Create()
   ; add fonts and other stuff to your new pdf
else
   ; get the code from pdf_GetErrorCode()  and fix the problem 
endif
Ok so you want to see what step 3 is like ?
step 3. on step 1 we modified pdf_save() so it wouldn't delete our pdf in memory if there was an error. We also added code to return #True or #False, however; for this procedureReturn to work we need to do a few changes.
( not difficult ). search for pdf_Save in purePDF.pb and you'll change each procedure to return the results like so:

Code: Select all

Procedure pdf_Save(FileName$) ;Output PDF to filename.
   ProcedureReturn ipdf_Save(FileName$)
  EndProcedure
and

Code: Select all

  ProcedureDLL pdf_Save(FileName$) ;Output PDF to filename.
    ProcedureReturn ipdf_Save(FileName$)
  EndProcedure
so now we can test with #True or #False the result of pdf_Save

Code: Select all

While  Not(pdf_Save(file$))
  Debug pdf_GetErrorMessage()
  File$ = SaveFileRequester("Please choose file to save", file$, "*.pdf", 0)
Wend


Again, this is code that is useful to me so I figure it might be useful to someone else.
Not really needed but handy to have.

Norm.
google Translate;Makes my jokes fall flat- Fait mes blagues tombent à plat- Machte meine Witze verpuffen- Eh cumpari ci vo sunari
User avatar
oakvalley
User
User
Posts: 76
Joined: Sun Aug 08, 2004 6:34 pm
Location: Norway
Contact:

Re: PurePDF Version 2.0

Post by oakvalley »

In PurePDF 2.25, the file "PurePDF.pb", there is an error creating "page 0 of x" visible in the Document Properties/Initial View, causing the "Description" view to fail with "there is no page numbered 0 in this document" with a Acrobat PDF reader.

The code in:
Procedure ipdf_PutCatalog()

where "/OpenAction [1 0 " exists, replace 0 with 1

I tried it myself (4 places within the Procedure) and it works now.
Regards Stone Oakvalley
Currently @ PB 5.70
User avatar
DoubleDutch
Addict
Addict
Posts: 3219
Joined: Thu Aug 07, 2003 7:01 pm
Location: United Kingdom
Contact:

Re: PurePDF Version 2.0

Post by DoubleDutch »

Your fix kills bookmarks.
https://deluxepixel.com <- My Business website
https://reportcomplete.com <- School end of term reports system
loulou2522
Enthusiast
Enthusiast
Posts: 495
Joined: Tue Oct 14, 2014 12:09 pm

Re: PurePDF Version 2.0

Post by loulou2522 »

DoubleDutch wrote:Your fix kills bookmarks.
With PureBasic 5.50 PurePDF crash when saving file with a footer Procedure
Can someone Help me ?
Function PDF_SAVE
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: PurePDF Version 2.0

Post by IdeasVacuum »

loulou2522, post a snippet we can test.
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
loulou2522
Enthusiast
Enthusiast
Posts: 495
Joined: Tue Oct 14, 2014 12:09 pm

Re: PurePDF Version 2.0

Post by loulou2522 »

IdeasVacuum wrote:loulou2522, post a snippet we can test.

Code: Select all

#PurePDF_Include=0
;XIncludeFile "PurePDF.pb"

Define file$="Tutorial01 Hello World.pdf"

pdf_Create()
pdf_AddPage()
pdf_SetFont("Arial","B",16)
pdf_Cell(40,10,"Hello World!",1)
pdf_Save(file$)
RunProgram(file$)
Error Message with Purebasic 550 Beta1
Accés mémoire invalide erreur de lecture àl'adresse 843002431
Instruction ----> pdf_save(files$)
Marc56us
Addict
Addict
Posts: 1477
Joined: Sat Feb 08, 2014 3:26 pm

Re: PurePDF Version 2.0

Post by Marc56us »

Code: Select all

#PurePDF_Include=0
;XIncludeFile "PurePDF.pb"

Define file$="Tutorial01 Hello World.pdf"

pdf_Create()
pdf_AddPage()
pdf_SetFont("Arial","B",16)
pdf_Cell(40,10,"Hello World!",1)
pdf_Save(file$)
RunProgram(file$)
Error Message with Purebasic 550 Beta1
Accés mémoire invalide erreur de lecture àl'adresse 843002431
Instruction ----> pdf_save(files$)
With your snipet code as is, this does not work :|
Line 6: pdf_Create() is not a function, array, list, map or macro.

Without comment for XInclude, and
- Programm saved in a folder where it can write
- good path to acces to PurePDF.pb
- good path to acces to PurePDF_res.pb

It works :) PDF is generated and displayed.

My configuration: Windows 10 x64 / PB 5.50 B1 / PurePDF V2.25 (uncompress un PB install dir)

:!: work for PB x86 but not for PB x64 Message: 'Compressed libraries are not supported (PurePDF).' (when open PB 5.50 x64)

:wink:
loulou2522
Enthusiast
Enthusiast
Posts: 495
Joined: Tue Oct 14, 2014 12:09 pm

Re: PurePDF Version 2.0

Post by loulou2522 »

Hi all,
I solve my problem recompiling PurePDF V. 2.25 with Tailbite
After PurePDF works well in PB 5.50
Thanks
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: PurePDF Version 2.0

Post by IdeasVacuum »

Hmm, just noticed that, somehow, a metric (mm) PDF containing a png image is created slightly oversized.

Whilst checking this, I found a clue (or a red-herring). The margins default to 10mm. If a PDF is created without specifying the margins, they do indeed verify as 10mm. However, if margins are specified, they verify oversize. For example

Code: Select all

pdf_Create("P","mm",PDF_PAGE_FORMAT_A3)
pdf_SetMargins(10.00,10.00,10.00)
.....results in margins of 11.5mm

Images on the other hand are rendered approx 4% oversize.

When the image is a screen grab (e.g. a web page) this issue matters a lot, because the text is rendered slightly fuzzy compared to the original pixel-sharp image.

Edit:
Image
My memory needs replacing! Adobe Reader is not 'Screen DPI aware', but it does render an accurate printed page.
Reader can of course display the page scaled, so is it possible to set the display scale via RunProgram()?
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
Post Reply