Code: Select all
;
; ------------------------------------------------------------
;
; PureBasic - Print/Preview Module
;
; FileName PurePrint.pb
;
; http://purebasic.fr/english/viewtopic.php?f=13&t=63022
;
;
; ------------------------------------------------------------
;
;UseJPEGImageDecoder()
UseSQLiteDatabase()
DeclareModule PurePrint
Preview.i
PageHeight.i ;mm To work out Graphic scale factor
PageWidth.i ;mm To work out Graphic scale factor
Orientation.i;Portrait or Landscape for print routines
;TPageHeight.i ;Points To work out Text scale factor
;TPageWidth.i ;Points To work out Text scale factor
Declare PurePrintEvents(Event)
Declare.l open(JobName.s)
Declare ShowPage(PageID)
Declare AddPage()
Declare Finished()
Declare PrintLine(Startx,Starty,Endx,Endy,LineWidth)
Declare PrintBox(Topx,Topy,Bottomx,Bottomy,LineWidth)
Declare PrintText(Startx,Starty,Font.s,Size.i,Text.s)
Declare PrintImage(Image.l,Topx.i,Topy.i,Width.i,Height.i)
Declare.f GettextWidthmm(text.s,FName.s,FSize.f)
Declare.f GettextHeightmm(text.s,FName.s,FSize.f)
Declare PrintShape(Shape_ID.i,Topx.i,Topy.i,Width.i,Height.i)
EndDeclareModule
Module PurePrint
Global PreviewWindow.l
Global Dim PageNos.i(1)
Global PageNo.i
Global GraphicScale.f
Global TextScale.f
Global Result
Global ShapesDB.l
Procedure.l OpenShapesDB()
;DatabaseFile$ = GetCurrentDirectory() +"Shapes.spb"
;OpenDB.l = OpenDatabase(#PB_Any, DatabaseFile$, "", "")
;If OpenDB.l > 0
; ProcedureReturn OpenDB.l
;Else
; ProcedureReturn 0
;EndIf
EndProcedure
Procedure.f GettextWidthmm(text.s,FName.s,FSize.f)
LoadFont(0,FName.s, FSize.f) ;Load Font In Points
ASize.f = FSize.f * 0.352777778 ;Convert Font Points To mm
VectorFont(FontID(0), ASize.f ) ;Use Font In mm Size
ProcedureReturn VectorTextWidth(text.s,#PB_VectorText_Visible) ;Width of text In mm
EndProcedure
Procedure.f GettextHeightmm(text.s,FName.s,FSize.f)
LoadFont(0,FName.s, FSize.f) ;Load Font In Points
ASize.f = FSize.f * 0.352777778 ;Convert Font Points To mm
VectorFont(FontID(0), ASize.f) ;Use Font In mm Size
ProcedureReturn VectorTextHeight(text.s,#PB_VectorText_Visible) ;Height of text In mm
EndProcedure
Procedure ShowPage(PageID)
If pureprint::Preview.i = 1
SetGadgetState(66,PageID + 1)
SetGadgetState(34, ImageID(PageNos.i(PageID)))
;Centre image gadget in window area
If GadgetHeight(34) > GadgetWidth(34)
Left = (500 - GadgetWidth(34)) /2
Top = 25
Else
Left = 0
Top = ((500-GadgetHeight(34)) /2 ) + 25
EndIf
ResizeGadget(34,Left,Top,#PB_Ignore,#PB_Ignore)
EndIf
EndProcedure
Procedure.l Open(JobName.s)
;ShapesDB.l = OpenShapesDB()
; If ShapesDB.l = 0
; "Shapes Not Initialised"
; EndIf
;Use largest side to get scale
If PurePrint::PageHeight > PurePrint::PageWidth.i
GraphicScale.f = 500/PurePrint::PageHeight
Else
GraphicScale.f = 500/PurePrint::PageWidth
EndIf
If pureprint::Preview.i = 1 ;If preview mode open Preview Window
PreviewWindow.l = OpenWindow(#PB_Any, #PB_Ignore,#PB_Ignore, 500, 535, "Print Preview - " + JobName.s)
If PreviewWindow.l > 0
SpinGadget (66, 450, 0, 50, 25, 0, 1000,#PB_Spin_Numeric)
SetGadgetState (66, 1)
ImageGadget(34, 5, 5, 50, 50, 0,#PB_Image_Raised)
;Set Page Counter To Zero And Create first Page Image
PageNo.i = 0
ProcedureReturn PreviewWindow.l
Else
;Tell The User We Failed
ProcedureReturn 0
EndIf
Else
;Start Printing
PrintRequester()
result = StartPrinting(JobName.s)
;Check Printer Paper Size and Orientation
StartVectorDrawing(PrinterVectorOutput(#PB_Unit_Millimeter))
;If PurePrint::Orientation = 0
; RotateCoordinates(0,0,-90)
; TranslateCoordinates(-297, 0)
;EndIf
ProcedureReturn result
EndIf
EndProcedure
Procedure AddPage()
If PurePrint::Preview.i = 1
;Increase Handle Array by one
ReDim PageNos.i(PageNo.i)
;Show new page number in spin gadget
SetGadgetState(66,PageNo.i + 1)
SetGadgetText(66, Str(PageNo.i + 1))
;Portrait or Landscape
If PurePrint::Orientation = 0
Temp.i = pureprint::PageHeight
pureprint::PageHeight = PurePrint::PageWidth
PurePrint::PageWidth = Temp.i
EndIf
;Create the image for the page and store handle in array
PageNos.i(PageNo.i) = CreateImage(#PB_Any, PurePrint::PageWidth * GraphicScale.f,pureprint::PageHeight * GraphicScale.f, 32,RGB(255,255,255))
ShowPage(PageNo.i)
StartVectorDrawing(ImageVectorOutput(PageNos.i(PageNo.i) ))
;Get ready for next page
PageNo.i = PageNo.i + 1
Else
;Printer New Page
NewPrinterPage()
If PurePrint::Orientation = 0
RotateCoordinates(0,0,-90) ;Rotate 90 based on top corner
TranslateCoordinates(-PurePrint::PageHeight, 0) ;Drop coordinates to new page
EndIf
EndIf
EndProcedure
Procedure PrintLine(Startx,Starty,Endx,Endy,LineWidth)
If PurePrint::Preview.i = 1
;Scaled To Fit Preview Window
MovePathCursor(Startx * GraphicScale.f, Starty * GraphicScale.f)
AddPathLine(Endx * GraphicScale.f, Endy * GraphicScale.f, #PB_Path_Default)
VectorSourceColor(RGBA(0, 0, 0, 255))
StrokePath(LineWidth * GraphicScale.f, #PB_Path_RoundCorner)
Else
;Print Routine No Scaling
MovePathCursor(Startx, Starty)
AddPathLine(Endx, Endy, #PB_Path_Default)
VectorSourceColor(RGBA(0, 0, 0, 255))
StrokePath(LineWidth,#PB_Path_RoundCorner)
EndIf
EndProcedure
Procedure PrintBox(Topx,Topy,Bottomx,Bottomy,LineWidth)
If PurePrint::Preview.i = 1
;Scaled To Fit Preview Image
AddPathBox(Topx * GraphicScale.f, Topy * GraphicScale.f, (Bottomx - Topx) * GraphicScale.f, (Bottomy - Topy) * GraphicScale.f)
VectorSourceColor(RGBA(255, 0, 0, 255))
StrokePath(LineWidth * GraphicScale.f)
Else
;Print Routine. No Scaling
AddPathBox(Topx, Topy , (Bottomx - Topx), (Bottomy - Topy))
VectorSourceColor(RGBA(255, 0, 0, 255))
StrokePath(LineWidth)
EndIf
EndProcedure
Procedure PrintText(Startx,Starty,Font.s,Size.i,Text.s)
;Scaled To Fit Preview Image
If PurePrint::Preview.i = 1
LoadFont(0, Font.s , Size.i )
ASize.f = Size.i * 0.352777778 ;Convert Font Points To mm
MovePathCursor(Startx * GraphicScale.f, Starty * GraphicScale.f)
VectorFont(FontID(0), ASize.f * GraphicScale.f)
VectorSourceColor(RGBA(0, 0, 0, 255))
DrawVectorText(Text.s)
Else
;Print Routine. No Scaling
LoadFont(0, Font.s , Size.i )
ASize.f = Size.i * 0.352777778 ;Convert Font Points To mm
VectorFont(FontID(0), ASize.f)
VectorSourceColor(RGBA(0, 0, 0, 255))
MovePathCursor(Startx, Starty)
DrawVectorText(Text.s)
EndIf
EndProcedure
Procedure PrintImage(Image.l,Topx.i,Topy.i,Width.i,Height.i)
If PurePrint::Preview.i = 1
MovePathCursor(Topx.i * GraphicScale.f, Topy.i * GraphicScale.f)
DrawVectorImage(ImageID(Image.l),100,Width.i * GraphicScale.f,Height.i * GraphicScale.f)
Else
;Print Routine
MovePathCursor(Topx.i, Topy.i)
DrawVectorImage(ImageID(Image.l),255,Width.i,Height.i)
EndIf
EndProcedure
Procedure PrintShape(Shape_ID.i,Topx.i,Topy.i,Width.i,Height.i)
;Testing purposes only!!!
;Standard shapes library under construction do not call this function as yet
;
;Scaled To Fit Preview Window
MovePathCursor(Topx.i * GraphicScale.f, Topy.i * GraphicScale.f)
If DatabaseQuery(ShapesDB.l, "SELECT * FROM DrawPoints WHERE Shape_ID = " + Str(Shape_ID) + ";")
While NextDatabaseRow(ShapesDB.l)
StartX.i = (Topx.i + (Val(GetDatabaseString(ShapesDB.l, 2))* Width.i/100 )) * GraphicScale.f
StartY.i = (Topy.i + (Val(GetDatabaseString(ShapesDB.l, 3))* Height.i/100 )) * GraphicScale.f
EndX.i = (Topx.i + (Val(GetDatabaseString(ShapesDB.l, 4)) * Width.i/100)) * GraphicScale.f
EndY.i = (Topy.i + (Val(GetDatabaseString(ShapesDB.l, 5)) * Height.i/100)) * GraphicScale.f
MovePathCursor(StartX.i, StartY.i,#PB_Path_Default)
AddPathLine(EndX.i,EndY.i, #PB_Path_Default)
Wend
FinishDatabaseQuery(ShapesDB.l)
StrokePath(1)
EndIf
EndProcedure
Procedure Finished()
If PurePrint::Preview.i = 0
StopVectorDrawing()
StopPrinting()
Else
StopVectorDrawing()
ShowPage(0)
EndIf
; CloseDatabase(ShapesDB.l)
EndProcedure
Procedure PurePrintEvents(Event)
If event = #PB_Event_CloseWindow
CloseWindow(PreviewWindow.l)
EndIf
If Event = #PB_Event_Gadget
Select EventGadget()
Case 66
SetGadgetText(66, Str(GetGadgetState(66)))
If GetGadgetState(66) > 0 And GetGadgetState(66) -1 <= ArraySize(PageNos())
ShowPage(GetGadgetState(66) -1)
ElseIf GetGadgetState(66) < 1
;Show Last Page No or first page Number in gadget
SetGadgetState(66,1)
Else
SetGadgetState(66,ArraySize(PageNos()) + 1 )
EndIf
EndSelect
EndIf
EndProcedure
EndModule
;-- DEMO ----------------------------------------------------------------------------------
CompilerIf #PB_Compiler_IsMainFile
;***********************************************************************
;Simple testing programme for PurePrint module
;Only an example
;
;PureBasic 5.4 Beta 1
;
;***********************************************************************
;Only uses .jpg images
UseJPEGImageDecoder()
;Ensure these are included
;XIncludeFile "AppGlobal.pb"
;XIncludeFile "PageSetupfrm.pb" ;Testing page setup
;Page structure and array
Structure Page
Height.i
Width.i
Orientation.i
TopMargin.i
LeftMargin.i
BottomMargin.i
RightMargin.i
EndStructure
Global Dim Pages.Page(1)
;
;Normaly define structure and array for each object the page contains
;Including Page Number!
;
Global Window_0
Global PageHeight
Global PageWidth
Global TopMargin
Global LeftMargin
Global BottomMargin
Global RightMargin
Global PageSetup
Global image.l
Global btnPreview,btnPrint
Global Print.l
Global btnPageSetup, txt_PageHeight, txt_PageWidth, str_TopMargin, str_LeftMargin, str_BottomMargin, str_PageWidth, str_RightMargin, str_PageHeight, txt_TopMargin, txt_LeftMargin, txt_BottomMargin, txt_RightMargin, btn_Exit
;Open the test window
Window_0 = OpenWindow(#PB_Any, x, y, 250, 340, "", #PB_Window_SystemMenu)
btnPageSetup = ButtonGadget(#PB_Any, 20, 10, 100, 30, "Page Setup")
DisableGadget(btnPageSetup, 1) ;Testing page setup
btnPreview = ButtonGadget(#PB_Any, 130, 10, 50, 30, "Preview")
;DisableGadget(btnPreview, 1)
btnPrint = ButtonGadget(#PB_Any, 190, 10, 50, 30, "Print")
;DisableGadget(btnPrint, 1)
btn_Exit = ButtonGadget(#PB_Any, 65, 280, 120, 40, "Quit")
txt_PageHeight = TextGadget(#PB_Any, 50, 60, 80, 20, "Page Height", #PB_Text_Right)
txt_PageWidth = TextGadget(#PB_Any, 60, 90, 70, 20, "Page Width", #PB_Text_Right)
str_TopMargin = StringGadget(#PB_Any, 140, 120, 60, 20, "")
str_LeftMargin = StringGadget(#PB_Any, 140, 150, 60, 20, "")
str_BottomMargin = StringGadget(#PB_Any, 140, 180, 60, 20, "")
str_PageWidth = StringGadget(#PB_Any, 140, 90, 60, 20, "")
str_RightMargin = StringGadget(#PB_Any, 140, 210, 60, 20, "")
str_PageHeight = StringGadget(#PB_Any, 140, 60, 60, 20, "")
txt_TopMargin = TextGadget(#PB_Any, 60, 120, 70, 20, "Top Margin", #PB_Text_Right)
txt_LeftMargin = TextGadget(#PB_Any, 50, 150, 80, 20, "Left Margin", #PB_Text_Right)
txt_BottomMargin = TextGadget(#PB_Any, 40, 180, 90, 20, "Bottom Margin", #PB_Text_Right)
txt_RightMargin = TextGadget(#PB_Any, 50, 210, 80, 20, "Right Margin", #PB_Text_Right)
str_Orientation = StringGadget(#PB_Any, 140, 240, 60, 20, "")
;**********************************************************************************************
;
;Code only for test
;Note:- Pageheight and width change here for orientation.
;Application programmer must keep track of changes to layout page correctly.
;Leaving them as portrait will print the images etc in landscape but at the potrait settings
;so all will be twisted 90 degrees
;
;**********************************************************************************************
;Test Purposes Only
ReDim Pages(2)
Pages(0)\Height = 297 ;A4 Page Height
Pages(0)\Width = 210 ;A4 Page Width
Pages(0)\Orientation = 1 ;Portrait
Pages(0)\TopMargin = 15
Pages(0)\LeftMargin = 15
Pages(0)\BottomMargin = 15
Pages(0)\RightMargin = 15
Pages(1)\Height = 210 ;A4 Page Height landscape
Pages(1)\Width = 297 ;A4 Page Width landscape
Pages(1)\Orientation = 0 ;Landscape
Pages(1)\TopMargin = 15
Pages(1)\LeftMargin = 35
Pages(1)\BottomMargin = 15
Pages(1)\RightMargin = 15
Procedure PrintPages()
;****************************************************
;Procedure just to test print a couple of pages
;Replace with your own procedure
;Normally is a loop through all document commands
;Checking height of page left etc
;Allways check as landscape has a smaller height
;
;Looking to add a Print which pages dialog at some
;point To allow users To choose which pages To print
;This is where the call to that dialog will go
;
;****************************************************
FontName.s = "Arial"
FontSize.i = 14
Result = FontRequester(FontName.s, FontSize.i, #PB_FontRequester_Effects)
FontName.s = SelectedFontName()
FontSize.i = SelectedFontSize()
;Select image to print for this page
;Remember to add decoders needed for image type
ImgFile.s = OpenFileRequester("SELECT IMAGE","","All supported formats|*.bmp;*.jpg; *.jpeg; *.wmf; *.emf; *.png;*.tif;*.tiff;*.tga|TGA image (*.tga)|*.tga|TIF image (*.tif)|*.tif|TIFF image (*.tiff)|*.tiff|PNG image (*.png)|*.png|BMP image (*.bmp)|*.bmp|JPEG image (*.jpg;*.jpeg)|*.jpg;*.jpeg|GIF image (*.gif)|*.gif",0)
;Set the page height and width assuming these are not changed during a print run!!!
;Do not change these for orientation!
PurePrint::PageHeight = 297 ;Pages(i)\Height
PurePrint::PageWidth = 210 ;Pages(i)\Width
For i = 0 To 1 ;Just two pages to test
;Set Page Orientation for each page
PurePrint::Orientation = Pages(i)\Orientation
;Check if Print Started If Not Start The Print Job
If Print.l = 0
Print.l = PurePrint::open("Test")
EndIf
;Add this page to the job
PurePrint::AddPage()
;Print A Border around the margins
PurePrint::PrintBox(Pages(i)\LeftMargin,Pages(i)\RightMargin ,Pages(i)\Width - Pages(i)\RightMargin ,Pages(i)\Height - Pages(i)\BottomMargin,2)
;Print A Line 3mm Thick
PurePrint::PrintLine(Pages(i)\LeftMargin + 5,50,Pages(i)\Width -Pages(i)\RightMargin -5,50,3)
;Print a Hexagon
;
;Testing Only Shapes library under construction Do not call this procedure
;Will post on forum as beta test
;
; PurePrint::PrintShape(8,130,60,40,40)
;Print some text
PurePrint::PrintText(50,100,FontName.s,FontSize.i,"Just Testing Page "+ Str(i + 1))
;Print some Centered Text
text$ = "Just Testing Centered"
widthtext.i = pureprint::GettextWidthmm(text$,SelectedFontName(),SelectedFontSize())
x.i = (Pages(i)\Width - Pages(i)\LeftMargin - Pages(i)\RightMargin - widthtext.i)/2
PurePrint::PrintText(x.i + Pages(i)\LeftMargin,130,FontName.s,FontSize.i,"Just Testing Centered")
If ImgFile.s <> ""
Image.l=LoadImage(#PB_Any, ImgFile.s)
EndIf
If Image.l > 0
; Remember ImageVectorOutput automatically scales the image so maintain aspect ratio
If ImageHeight(image.l) > ImageWidth(image.l)
adjustedheight = 50 * (ImageHeight(image.l)/ImageWidth(image.l))
adjustedwidth = adjustedheight * ImageWidth(image.l) / ImageHeight(image.l)
Else
adjustedwidth = 40 * (ImageWidth(image.l)/ImageHeight(image.l))
adjustedheight = adjustedwidth * ImageHeight(image.l)/ImageWidth(image.l)
EndIf
;Depending on the image you may have to use the adjusted height in page calculations
;The image is allways drawn starting from top left so the position of an adjusted image may need to be changed
;to provide bottom aligned image printing
PurePrint::PrintImage(Image.l,Pages(i)\LeftMargin + 5,130,adjustedwidth,adjustedheight)
EndIf
Next i
;Finish The Print Job
PurePrint::Finished()
EndProcedure
Repeat
Event = WaitWindowEvent()
If EventWindow() = Print.l
pureprint::PurePrintEvents(event)
EndIf
;Added ready for page setup dialogue just testing at the moment
;If EventWindow() = PageSetup
;If event = #PB_Event_DeactivateWindow
;SetGadgetText(str_PageHeight,PSetup::GetPageHeight())
;SetGadgetText(str_PageWidth,PSetup::GetPageWidth())
;SetGadgetText(str_TopMargin,PSetup::GetTopMargin())
;SetGadgetText(str_LeftMargin,PSetup::GetLeftMargin())
;SetGadgetText(str_BottomMargin,PSetup::GetBottomMargin())
;SetGadgetText(str_RightMargin,PSetup::GetRightMargin())
;If PSetup::GetOrientation() = 1
; SetGadgetText(str_Orientation,"Portrait")
; Else
; SetGadgetText(str_Orientation,"Landscape")
;EndIf
; DisableGadget(btnPreview, 0)
; DisableGadget(btnPrint, 0)
;EndIf
;PSetup::PSetupEvents(event)
;EndIf
Select event
Case #PB_Event_Gadget
Select EventGadget()
;Case btnPageSetup ;ready for page setup dialog
; If PageSetup = 0
; PageSetup = PSetup::OpenPageSetup(Window_0)
; Else
; HideWindow(PageSetup,#False)
; EndIf
Case btnPreview
pureprint::Preview.i = 1 ; Set to preview document
PrintPages()
Case btnPrint
pureprint::Preview.i = 0 ; Set to print document
PrintPages()
Case btn_Exit
End
EndSelect
EndSelect
Until EventWindow() = 0 And Event = #PB_Event_CloseWindow ; If the user has pressed on the window close button
End
CompilerEndIf