Page 9 of 10

Re: [Module] pbPDF-Module

Posted: Sun Nov 19, 2023 1:11 pm
by Jan2004
Thanks to normeus and Little_man for directing me, and many thanks to Thorsten1867 for creating such a great PDF library.
All varieties of the Lato fonts have Polish characters. I made a mistake in the previous post because I marked the font access incorrectly. It is best to place fonts in the same directory as pbPDFModule.pbi, and place my example where the example files are located, in the Examples directory. All fonts Lato also covers the Russian language (I studied Russian in secondary and high school) and the language of my wonderful Slovak neighbors (I live 20 km from the border).

In my opinion, the Lato font is probably the best font for content created in PDF. Lato can be included in commercial applications freely.

Code: Select all

XIncludeFile "..\pbPDFModule.pbi"

Define File$="multilingual_lato_fonts.pdf"
#PDF = 1
;  Create an instance of PDF
If PDF::Create(#PDF)
  ;  Always add a page to create a PDF or you'll get an error
  ;  Page size and orientation is optional, I like to add it because you can have multiple page sizes in a PDF   
  PDF::AddPage(#PDF,PDF::#Landscape,PDF::#format_letter)
  
  ;All Lato fonts has polish, russian, slovakian letters
  ; Lato-Italic.ttf
  ; Lato-Light.ttf
  ; Lato-LightItalic.ttf
  ; Lato-Medium.ttf
  ; Lato-MediumItalic.ttf
  ; Lato-Semibold.ttf
  ; Lato-SemiboldItalic.ttf
  ; Lato-Thin.ttf
  ; Lato-HeavyItalic.ttf
  ; Lato-ThinItalic.ttf
  ; Lato-Regular.ttf
  ; Lato-Black.ttf
  ; Lato-BlackItalic.ttf
  ; Lato-Bold.ttf
  ; Lato-BoldItalic.ttf
  ; Lato-Hairline.ttf
  ; Lato-HairlineItalic.ttf
  ; Lato-Heavy.ttf
  
  PDF::EMbedFont(#PDF, "..\Lato-Light.ttF","Lato","",PDF::#Unicode)
  PDF::SetFont(#PDF, "Lato", "", 13)
  PDF::PlaceText(#PDF, "In polish: Zażółć gęślą jaźń.", 10, 40)
  PDF::PlaceText(#PDF, "What means: Yellow the goose self.", 10, 45)
  
  PDF::EMbedFont(#PDF, "..\Lato-Semibold.ttf","Lato2","",PDF::#Unicode)
  PDF::SetFont(#PDF, "Lato2", "", 12)   
  PDF::PlaceText(#PDF, "In slovac: Orly lietajú najvyššie a prečo sú také chytré.", 10, 60)
  PDF::PlaceText(#PDF, "What means: Eagles fly the highest and why they are so smart.", 10, 65)
  
  PDF::EMbedFont(#PDF, "..\Lato-BoldItalic.ttf","Lato3","",PDF::#Unicode)
  PDF::SetFont(#PDF, "Lato3", "", 11)
  PDF::PlaceText(#PDF, "In russian: Пусть всегда будет солнце, Пусть всегда будет небо, Пусть всегда будет мама, Пусть всегда буду я. ", 10, 80)
  PDF::PlaceText(#PDF, "What means: May there always be the sun, May there always be the sky, May there always be my mum, May there always be me.", 10, 85)
  PDF::Close(#PDF, File$)
  
EndIf

RunProgram(File$)

Re: [Module] pbPDF-Module

Posted: Wed Feb 28, 2024 10:22 am
by matlab2
Dear all, I need your help again. With the great PDF module from Thorsten1867, I create serial letters/reports in many languages using templates. It works very well. When generating Ukrainian letters using Unicode fonts with Cyrillic characters (Lato Font familie or Paratype PT Sans), there are two glyphs [Ш Щ] - and only the two - that cause the PDF generation to be cancelled depending on the "environment". I have added examples to the code from Jan2004 (see above) so that you can see the strange behaviour. I would be very, very happy to receive ideas for a solution.

Code: Select all

; The example is based on code from Jan2004 (see above).

XIncludeFile "pbPDFModule.pbi"

Define File$="pbPDF-Example.pdf"
#PDF = 1
If PDF::Create(#PDF)
 
  PDF::AddPage(#PDF,PDF::#Landscape,PDF::#format_Letter)
  
  ; specialty unicode font, which contains the character you need  
  PDF::EMbedFont(#PDF, "Lato-Regular.ttf","Lato","",PDF::#Unicode) 
  PDF::SetFont(#PDF, "lato", "", 14)
  
  ; Here are a few examples with different outcomes
  #test = 1 ; 1-6
  
  Select #test
    Case 1
      ; works  
      PDF::PlaceText(#PDF, "Ш Щ", 10, 50)
    Case 2
      ; does not work  
      PDF::PlaceText(#PDF, "Ш", 10, 50)
    Case 3
      ; does not work 
      PDF::PlaceText(#PDF, "Щ", 10, 50)
    Case 4
      ; works
      PDF::PlaceText(#PDF, "Ц", 10, 50) 
    Case 5
      ; works in parts
      PDF::PlaceText(#PDF, "Ш Щ", 10, 50)
      PDF::PlaceText(#PDF, "Ш", 10, 70)
      PDF::PlaceText(#PDF, "Щ", 10, 90)
    Case 6
      ; works
      PDF::PlaceText(#PDF, "ЀЁЂЃЄЅІЇЈЉЊЋЌЍЎЏАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяѐёђѓєѕіїјљњћќѝўџѠѡѢѣѤѥѦѧѨѩѪѫѬѭѮѯѰѱѲѳѴѵѶѷѸѹѺѻѼѽѾѿҀҁ҂$", 10, 50) 
  EndSelect

  PDF::Close(#PDF, File$)
  
EndIf

RunProgram(File$)

Re: [Module] pbPDF-Module

Posted: Fri Mar 08, 2024 9:41 am
by Jan2004
Try using a different font, for example from here:
https://russianfonts.org

Re: [Module] pbPDF-Module

Posted: Sat Apr 06, 2024 9:15 am
by Jan2004
Dear Colleagues, could you show me the working code for inserting a PNG image into PDF using the ImageMemory function? The code on page 4 of this post does not work.
Thank you for your help. Kind regards.

Re: [Module] pbPDF-Module

Posted: Sat Apr 06, 2024 2:55 pm
by Paul
Jan2004 wrote: Sat Apr 06, 2024 9:15 am Dear Colleagues, could you show me the working code for inserting a PNG image into PDF using the ImageMemory function? The code on page 4 of this post does not work.
Thank you for your help. Kind regards.
You made it to page 4... you just had to go 2 more pages :)
https://www.purebasic.fr/english/viewto ... 36#p570236

Re: [Module] pbPDF-Module

Posted: Sun Apr 07, 2024 10:50 am
by Jan2004
Paul,
I was already wondering about the code you indicated (the one on page 6). This code also did not meet my expectations. Why? Because after compiling this code a PNG file outside the compiled code still will be needed. And I wanted to have a PNG file packaged in an EXE. However, I thank you for the inspiration, because I started thinking about this file again and added a few lines to the code you indicated. Now I have what I longed for.

Code: Select all

IncludeFile "..\pbPDFModule.pbi"

Define LinkID.i, File$ = "pbPDF_image_packed_in_PDF.pdf"
Define *pdf_1_mem,pdf_1_img,pdf_1_size
#PDF = 1

If PDF::Create(#PDF)
  
  PDF::AddPage(#PDF)
  
  LinkID = PDF::AddLinkURL(#PDF, "https://www.purebasic.com/")
  Debug LinkID
  
  ; "DataSection" and "CatchImage" will cause the PNG to be loaded into the EXE file.
  DataSection 
  clipart:
    IncludeBinary"MYFILE.PNG"
  EndDataSection 
  
  pdf_1_img = CatchImage(#PB_Any,?clipart)
  
  If pdf_1_img                                  ; if there was an image in that location
    *pdf_1_mem=EncodeImage(pdf_1_img,#PB_ImagePlugin_PNG);
    If *pdf_1_mem
      pdf_1_size= MemorySize(*pdf_1_mem)
      ;pdf::ImageMemory(ID.i, ImageName.s, *Memory, Size.i, Format.i, X.f=#PB_Default, Y.f=#PB_Default, Width.f=#PB_Default, Height.f=#PB_Default, Link.i=#NoLink)
      pdf::imagememory(#pdf,"MYFILE.PNG",*pdf_1_mem,pdf_1_size,pdf::#Image_PNG,20,20,60,20,LinkID)
    EndIf     
    FreeMemory(*pdf_1_mem)
    FreeImage(pdf_1_img)
  EndIf
  PDF::Close(#PDF, File$)
EndIf

RunProgram(File$)
Do you Paul and other colleagues have any additional comments on the current version of the PB file?
To check whether the concept is working correctly:
1. Create your own MYFILE.PNG file and know its dimensions.
2. Enter the MYFILE.PNG data into the code.
3. Create an EXE file from the code using the PureBasic "Compiler/Create Executable" function.
4. Rename the MYFILE.PNG file to, for example, MYFILE_XX.PNG.
5. Execute the EXE file created from the PB code.
If the image is visible in PDF, it means that we have achieved our intended goal.

Many thanks to Thorsten1867 for creating a wonderful PDF library, which works great in the PureBasic 5.73 version I use.

Re: [Module] pbPDF-Module

Posted: Tue Apr 30, 2024 1:29 pm
by dige
Many thanks for this PDF module!

There is currently only a limited selection of fonts available for SetFont, including those defined in the data section.
I would now like to use my own font, for example Calibri.
How can I use this font? What do I have to add, or how can I add the corresponding data in the data section?

Kind regards

Dige

Re: [Module] pbPDF-Module

Posted: Thu May 02, 2024 4:33 pm
by dige
When I use PDF::GetStringWidth(ID.i, String.s),
I often get the error that the map has no current element
@ PDF()\Fonts()\CharWidth(Char)

Is there a bullet proof function, to check if a map() have a valid element?


Code: Select all

  Procedure.d GetStringWidth_(String.s, Scale.i=#True)
    Define i.i, Width.i, Char.s, vReturn.d

    For i = 1 To Len(String)
      
      Char = Mid(String, i, 1)
      If Asc(Char) > 255
        Width + 600 ; for Unicode characters
      Else
      	; ERROR that the map has no current element
        Width + PDF()\Fonts()\CharWidth(Char)
      EndIf
      
    Next
    
    If Scale
      ProcedureReturn (Width * PDF()\Font\Size) / 1000
    Else
      ProcedureReturn Width
    EndIf

  EndProcedure   

Re: [Module] pbPDF-Module

Posted: Fri May 03, 2024 5:17 pm
by Thorsten1867
Bugfix: Unicode-Font

Re: [Module] pbPDF-Module

Posted: Tue May 07, 2024 1:26 am
by CDXbow
I want to make a printable calendar and I thought doing it as a PDF was probably the best approach. I used pdPDF and it all went smoothly - it's the first time I'd ever used pdPDF and it's a really great piece of work. Thanks Thor.

I ended up laying out a calendar like this, which was exactly as I wanted except for one thing.

Code: Select all

;printable calendar
XIncludeFile "..\pbPDFModule.pbi"
Define.s Options
Define File$="calendar.pdf"

#PDF = 1
If PDF::Create(#PDF)
 PDF::AddPage(#PDF, "L", PDF::#Format_A4)
 ; PDF::AddPage(#PDF)
  
  PDF::SetFont(#PDF, "Arial", "B", 36) 
  PDF::Cell(#PDF, "CALENDAR", #PB_Default, #PB_Default, #False, PDF::#NextLine); PDF::#CenterAlign)
  PDF::SetFont(#PDF, "Arial", "B", 24) 
  PDF::Cell(#PDF, "    Mon         Tue           Wed           Thu           Fri           Sat          Sun", #PB_Default, #PB_Default, #False, PDF::#NextLine)
 ; PDF::Ln(#PDF)
  
  PDF::SetFont(#PDF, "Arial", "B", 30)  
  PDF::Cell(#PDF, "1", 40, 30, #True)
  PDF::Cell(#PDF, "2", 40, 30, #True)
  PDF::Cell(#PDF, "3", 40, 30, #True)
  PDF::Cell(#PDF, "4", 40, 30, #True)
  PDF::Cell(#PDF, "5", 40, 30, #True)
  PDF::Cell(#PDF, "6", 40, 30, #True)
  PDF::Cell(#PDF, "7", 40, 30, #True, PDF::#NextLine)
  
  PDF::Cell(#PDF, "8", 40, 30, #True)
  PDF::Cell(#PDF, "9", 40, 30, #True)
  PDF::Cell(#PDF, "10", 40, 30, #True)
  PDF::Cell(#PDF, "11", 40, 30, #True)
  PDF::Cell(#PDF, "12", 40, 30, #True)
  PDF::Cell(#PDF, "13", 40, 30, #True)
  PDF::Cell(#PDF, "14", 40, 30, #True, PDF::#NextLine)
  
   PDF::SetFont(#PDF, "Arial", "B", 26)  
  PDF::Cell(#PDF, "15", 40, 30, #True)
  PDF::Cell(#PDF, "16", 40, 30, #True)
  PDF::Cell(#PDF, "17", 40, 30, #True)
  PDF::Cell(#PDF, "18", 40, 30, #True)
  PDF::Cell(#PDF, "19", 40, 30, #True)
  PDF::Cell(#PDF, "20", 40, 30, #True)
  PDF::Cell(#PDF, "21", 40, 30, #True, PDF::#NextLine)
  
  PDF::SetFont(#PDF, "Arial", "B", 26)  
  PDF::Cell(#PDF, "22", 40, 30, #True)
  PDF::Cell(#PDF, "23", 40, 30, #True)
  PDF::Cell(#PDF, "24", 40, 30, #True)
  PDF::Cell(#PDF, "25", 40, 30, #True)
  PDF::Cell(#PDF, "26", 40, 30, #True)
  PDF::Cell(#PDF, "27", 40, 30, #True)
  PDF::Cell(#PDF, "28", 40, 30, #True, PDF::#NextLine)
  
  PDF::Cell(#PDF, "29", 40, 30, #True)
  PDF::Cell(#PDF, "30", 40, 30, #True)
  PDF::Cell(#PDF, "31", 40, 30, #True)
  PDF::Cell(#PDF, "32", 40, 30, #True)
  PDF::Cell(#PDF, "33", 40, 30, #True)
  PDF::Cell(#PDF, "34", 40, 30, #True)
  PDF::Cell(#PDF, "35", 40, 30, #True, PDF::#NextLine)

  PDF::Close(#PDF, File$)
  
EndIf
RunProgram(File$)
If you run the example, you will see the pseudo dates are in the middle of the cell and not the top. I couldn't find a way to get them aligned to the top. Top right, top left or top centre, it doesn't matter, it just needs to be the top. I tried klutzy things like LF and CR but they didn't work. Am I just dumb and missing something obvious?

Re: [Module] pbPDF-Module

Posted: Tue May 07, 2024 8:23 pm
by normeus
CDXbow, you can draw the squares of the calendar first then use cells, no border of smaller size to draw the numbers, I do not have time to create an example, but:

Code: Select all

  PDF::SetFont(#PDF, "Arial", "B", 30)  
    pdf::DividingLine(#pdf)
  PDF::Cell(#PDF, "1", 40, 15) ; no border
  PDF::Cell(#PDF, "2", 40, 15)
  PDF::Cell(#PDF, "3", 40, 15)
  PDF::Cell(#PDF, "4", 40, 15)
  PDF::Cell(#PDF, "5", 40, 15)
  PDF::Cell(#PDF, "6", 40, 15)
  PDF::Cell(#PDF, "7", 40, 15, #False, PDF::#NextLine)
  PDF::Ln(#PDF)
  pdf::DividingLine(#pdf)
  PDF::Cell(#PDF, "8", 40, 15)
  PDF::Cell(#PDF, "9", 40, 15)
  PDF::Cell(#PDF, "10", 40, 15)
  PDF::Cell(#PDF, "11", 40, 15)
  PDF::Cell(#PDF, "12", 40, 15)
  PDF::Cell(#PDF, "13", 40, 15)
  PDF::Cell(#PDF, "14", 40, 15, #False, PDF::#NextLine)
    PDF::Ln(#PDF)
  pdf::DividingLine(#pdf)
;etc.... to get to 31
These would be the numbers at the right locations all you have to do is draw 8 vertical lines to create your grid

Norm.

Re: [Module] pbPDF-Module

Posted: Tue May 07, 2024 9:24 pm
by normeus
@Jan2004, Sorry I didnt reply sooner, I have not received updates to this topic in a while. Here is an example using includeBinary. I think "pdf::imagememory" can load the image from memory without using the extra steps I am taking, I just did not have time to look at the code:

Code: Select all

;image Memory
;save this file in the examples folder o
XIncludeFile "..\pbPDFModule.pbi"
Define.s Options
Define File$="image_from_exe.pdf"
Global img0 = CatchImage(#PB_Any, ?logostart)
Global *pdf_1_mem=EncodeImage(img0,#PB_ImagePlugin_PNG);
Global pdf_1_size= MemorySize(*pdf_1_mem)
#PDF = 1
If PDF::Create(#PDF)
   PDF::AddPage(#PDF, "L", PDF::#Format_A4)
   pdf::imagememory(#pdf,"PureBasic.png",*pdf_1_mem,pdf_1_size,pdf::#Image_PNG,20,20,60,20)
  PDF::Close(#PDF, File$)
EndIf
RunProgram(File$)
  
DataSection
  logoStart:
  IncludeBinary "purebasic.png"
  logoEnd:
EndDataSection



Norm

Re: [Module] pbPDF-Module

Posted: Wed May 08, 2024 1:48 am
by CDXbow
Thanks Norm,
I'll give it a go.

Re: [Module] pbPDF-Module

Posted: Wed May 08, 2024 3:00 am
by normeus
@CDXbow, I took a look, and that calendar could be a nice program, create a pdf of a month, you get to choose if first day of the week is Monday or it might be Sunday. display the last week of previous month, etc...
here is your code with a sample using "DrawRectangle" to create part of your grid:

Code: Select all

;printable calendar
XIncludeFile "..\pbPDFModule.pbi"
Define.s Options
Define File$="calendar.pdf"

#PDF = 1
If PDF::Create(#PDF)
 PDF::AddPage(#PDF, "L", PDF::#Format_A4)
 ; PDF::AddPage(#PDF)
  
  PDF::SetFont(#PDF, "Arial", "B", 36) 
  PDF::Cell(#PDF, "CALENDAR", #PB_Default, #PB_Default, #False, PDF::#NextLine); PDF::#CenterAlign)
  PDF::SetFont(#PDF, "Arial", "B", 24) 
  PDF::Cell(#PDF, "    Mon         Tue           Wed           Thu           Fri           Sat          Sun", #PB_Default, #PB_Default, #False, PDF::#NextLine)
 ; PDF::Ln(#PDF)
  
  PDF::SetFont(#PDF, "Arial", "B", 30)  
  pdf::DividingLine(#pdf)
   pdf::DrawRectangle(#pdf,10,22,40,160)
   pdf::DrawRectangle(#pdf,50,22,40,160)
   pdf::DrawRectangle(#pdf,90,22,40,160)
   pdf::DrawRectangle(#pdf,130,22,40,160)
   pdf::DrawRectangle(#pdf,170,22,40,160)
   pdf::DrawRectangle(#pdf,210,22,40,160)
   pdf::DrawRectangle(#pdf,250,22,37,160)
   
  PDF::Cell(#PDF, "1", 40, 15)
  PDF::Cell(#PDF, "2", 40, 15)
  PDF::Cell(#PDF, "3", 40, 15)
  PDF::Cell(#PDF, "4", 40, 15)
  PDF::Cell(#PDF, "5", 40, 15)
  PDF::Cell(#PDF, "6", 40, 15)
  PDF::Cell(#PDF, "7", 40, 15, #False, PDF::#NextLine)
  PDF::Ln(#PDF)
  pdf::DividingLine(#pdf)
  PDF::Cell(#PDF, "8", 40, 15)
  PDF::Cell(#PDF, "9", 40, 15)
  PDF::Cell(#PDF, "10", 40, 15)
  PDF::Cell(#PDF, "11", 40, 15)
  PDF::Cell(#PDF, "12", 40, 15)
  PDF::Cell(#PDF, "13", 40, 15)
  PDF::Cell(#PDF, "14", 40, 15, #False, PDF::#NextLine)
    PDF::Ln(#PDF)
  pdf::DividingLine(#pdf)
   PDF::SetFont(#PDF, "Arial", "B", 26)  
  PDF::Cell(#PDF, "15", 40, 15)
  PDF::Cell(#PDF, "16", 40, 15)
  PDF::Cell(#PDF, "17", 40, 15)
  PDF::Cell(#PDF, "18", 40, 15)
  PDF::Cell(#PDF, "19", 40, 15)
  PDF::Cell(#PDF, "20", 40, 15)
  PDF::Cell(#PDF, "21", 40, 15, #False, PDF::#NextLine)
    PDF::Ln(#PDF)
  pdf::DividingLine(#pdf)
  PDF::SetFont(#PDF, "Arial", "B", 26)  
  PDF::Cell(#PDF, "22", 40, 15)
  PDF::Cell(#PDF, "23", 40, 15)
  PDF::Cell(#PDF, "24", 40, 15)
  PDF::Cell(#PDF, "25", 40, 15)
  PDF::Cell(#PDF, "26", 40, 15)
  PDF::Cell(#PDF, "27", 40, 15)
  PDF::Cell(#PDF, "28", 40, 15, #False, PDF::#NextLine)
      PDF::Ln(#PDF)
  pdf::DividingLine(#pdf)
  PDF::Cell(#PDF, "29", 40, 15)
  PDF::Cell(#PDF, "30", 40, 15)
  PDF::Cell(#PDF, "31", 40, 15)
  PDF::Cell(#PDF, "32", 40, 15)
  PDF::Cell(#PDF, "33", 40, 15)
  PDF::Cell(#PDF, "34", 40, 15)
  PDF::Cell(#PDF, "35", 40, 15, #False, PDF::#NextLine)

  PDF::Close(#PDF, File$)
  
EndIf
RunProgram(File$)

Have fun!

Norm.

Re: [Module] pbPDF-Module

Posted: Wed May 08, 2024 4:40 am
by CDXbow
Thank you very much, Norm. I am in your debt.
You are right, it is a pretty useful routine, I think other folks will find it useful. I was a bit surprised that there wasn't something already like it.
I have a very simple need, to print a A4 sized calendar each month, starting at Monday and ending with the weekend, where God meant the it to be! Most online calendars split the weekend for some reason and I can't stand it.
Now the hard work begins, how do I populate it with the dates of the current month? Still, you've got me past the first hurdle, thanks again!!