BlitzMax Printing

BlitzMax Forums/BlitzMax Programming/BlitzMax Printing

Scaremonger(Posted 2014) [#1]
I have put together a very early beta for a Blitzmax printing system which is currently Windows only.

Download from here

Would this be something the community would be interested in seeing as a module? If so then I'd like to integrate with Max2D, does anyone have any experience in doing this?

Under Linux/MAC should I look at Bruceys Cairo module to create a PDF file and then use the CUPS API to print the file, or is there a better way to achieve this?


degac(Posted 2014) [#2]
Nice, something I need to try asap!
To be honest at the moment I'm using Brucey's solution (Cairo) to create PDF.
I discovered that - at the end of the story... - I need in the 95% of the situations a digital copy to keep/send/save... so PDF is mandatory.


Henri(Posted 2014) [#3]
I'm sure there is always room for a printing module as there isn't any solely for this purpose. I now there was a time I could have used one.

-Henri


xlsior(Posted 2014) [#4]
Likewise, definitely could come in handy from time to time.


Scaremonger(Posted 2014) [#5]
Cool. In that case I'll develop it for release as a module.

I've been looking at integrating into Max2d and using CreateGraphics() for the printer page.

If I use this approach I need to return the system state when I'm done printing so I need a way to SetGraphics() to the Printer Page and then SetGraphics() back to the screen when I'm done. brl.graphics contains a private variable _graphics containing this information but not a getGraphics() method to obtain it.

For the moment I'll create a set of page drawing functions..


Scaremonger(Posted 2014) [#6]
Version 0.0.2 BETA available on Sourceforge

Changelog:
* Converted into a module (Win32 Only)
* Added 12 new methods to TPrintPage
* Dimensions can be pixels, inches, centimeters or millimeters
* Amended arguments on drawText()
* Minor internal changes and bug fixes.

Additional methods include:
setColor(), width(), height(), xDPI(), yDPI(), drawRect(), Drawline(), moveTo(), LineTo(), drawImage(), drawPixmap() and setDimensions()


xlsior(Posted 2014) [#7]
FYI, winspool.a appears to be missing from the win32 folder on the module download version.

I copied it from the other download, that let me compile the module.. The example (mostly) works on my PC, great work!

Couple of questions/observations:

1) Am I correct in that while it defaults to drawing coordinates in centimeters, you can also use pixels or inches?

2) noticed something odd: When I print to my real printer (Brother laserjet) it looks as expected, but when I print to a virtual printer (CutePDF, free download) which turns it into a PDF file, there's an extra line: It draws a black line with some aliasing artifacts from the upper left corner all the way down & across the page at a 45 degree angle. It does not draw on top of the grey bar, so it's probably generated before that drawing command happens. I haven't seen those kind of artifacts happen with any other prints before.

3) Is there any way to do a "quick print" and go directly to your default printer instead of popping up the dialog box asking you what printer to use each time?

4) Is there any way to read the dimensions of a standard page before actually sending the print job to a device?


Scaremonger(Posted 2014) [#8]
@xlsior

Many thanks; I've added winspool.a to the archive and uploaded version 0.0.2.1 to sourceforge.

Am I correct in that while it defaults to drawing coordinates in centimeters, you can also use pixels or inches?

The X,Y values within the drawing functions, except Plot(), are based on the current Dimension (pixels, mm, cm or inches). You set the scaling factor you want through setDimensions(). It defaults to pixels.

It draws a black line with some aliasing artifacts from the upper left corner all the way down & across the page at a 45 degree angle.

This is generated by the following code, but I suspect the colour $001234 may be too feint to be printed. I've been using CutePDF too so I'll test it with my printer later.
	For Local x%=0 To page.width( DIM_PIXEL )
		page.Plot( x, x, $1234 )
	Next

Is there any way to do a "quick print" and go directly to your default printer instead of popping up the dialog box asking you what printer to use each time?

I can get the default printer so it should be possible. Added to my to-do list

Is there any way to read the dimensions of a standard page before actually sending the print job to a device?

The paper size is available immediately after the printer is selected, I currently expose this within the page as width() and height(). I will need to split up the printer selection and the actual page rendering. Added to my to-do list

Incidentally width() and height() by default return the size in pixels which along with XDPI() and YDPI() can be used to identify the page size; however width() and height() also take an optional parameter to do this calculation for you. Just pass DIM_MM, DIM_CM or DIM_INCH and it will return the actual page size.


Scaremonger(Posted 2014) [#9]
Version 0.03 available on Sourceforge.

@xlsior
Is there any way to do a "quick print" and go directly to your default printer instead of popping up the dialog box asking you what printer to use each time?

I have re-worked the library to include a constructor SelectDefaultPrinter() and added a new example to show it working.

Is there any way to read the dimensions of a standard page before actually sending the print job to a device?

The page object is now available as long as the user has selected a printer (or the default printer has been used).

For example:

Local prn:TPrinter = New TPrinter.selectDefaultPrinter()

If prn.selected() Then
	Local paper:TPrintPage = prn.page()
	Print "PRINTER:    "+ prn.printerName()
	Print "SIZE:       "+ paper.width( DIM_CM ) + " x " + paper.height( DIM_CM ) + " cm"
	Print "RESOLUTION: "+ paper.xdpi() + " x " + paper.ydpi() + " dpi"
	
	If prn.Print( "My First Print Job", PageRender ) Then Print "Success..."
End If



Chalky(Posted 2015) [#10]
Apologies for bumping a 9 month old thread, but this is really great - do you plan on developing it any further?


Scaremonger(Posted 2015) [#11]
Not with my current workload, was there anything in particular you were looking for?


Chalky(Posted 2015) [#12]
I have been trying to add more text functionality (change font; font size; text colour etc.) to your mod but have so far failed as your code is too clever for me and I am struggling to understand how it all fits together.

A while ago I wrote (and still have) a VB6 DLL which had the following:
DrawArc, DrawCircle, DrawImage, DrawLine, DrawPoint, DrawRect, DrawText, EndDoc, FreeImage, GetCurrentX, GetCurrentY, GetDeviceName, GetDriverName, GetFonts,
GetImageHeight, GetImageWidth, GetPageHeight, GetPageWidth, GetPrinters, GetPort, LoadImage, NewPage, ShowPrinter, SetColorMode, SetCopies, SetDrawMode,
SetDrawStyle, SetDuplex, SetFillColor, SetFillStyle, SetFontBold, SetFontItalic, SetFontName, SetFontSize, SetFontStrikethru, SetFontTransparent, SetFontUnderline,
SetForeColor, SetOrientation, SetPaperSize, SetPrinter, SetPrintQuality, SetScaleMode, TextHeight, TextWidth

Unfortunately I never got the "ShowPrinter" method (which was meant to call/display PrintDlg) to work from within BlitzMax (programs MAV'd whenever it was invoked) due to VB6 needing to pass it a valid HDC, and I couldn't work out how to supply one since neither retrieving the desktop HDC or my program's window HDC solved the issue.

Your mod is much neater than my DLL as: a) PrintDlg actually works!; and b) no external DLL is required. However I totally understand about spare time vs workloads. What you've given us is great - I simply need to try harder when fathoming how you did it so that one day I might be able to expand it with my DLL functionality.


Fielder(Posted 2015) [#13]
I'm using right now the latest release (i think) the V0.03, it's working fine but when i print a page the spool size become 75 Mbytes (???) i'm printing on a a4 paper.. and this enormous file needs 30 seconds to be processed...

there is a way to decrease DPIs or to speed up the rendering/spool ?

thank you to everyone that can help me :)

P.S. is the "SetPrintQuality"-similar command that i need? (i'm talking about "It's Printing")


Scaremonger(Posted 2015) [#14]
Version 0.04 available on Sourceforge.

I have Partially integrated Max2D functions into the page functionality, so you now have to call SetGraphics( Printer ) before using the drawing functions. When you have finished, you need to restore it back to your screen. I'm not sure if this is really an improvement or makes it more complex, so please let me know what you think.

Features:
* setcolor() - Now using MAX2D
* plot() - Now using MAX2D
* drawline() - Now using MAX2D
* drawrect() - Now using MAX2D

NEW in Version 0.04:
* setgraphics( Printer )
* drawoval( x, y, w, h )
* page.selectfont( face$, points, bold?, italic?, underline?, strikeout? )

@Fielder
when i print a page the spool size become 75 Mbytes (???) i'm printing on a a4 paper.. and this enormous file needs 30 seconds to be processed

The Page Size and DPI used by the module are taken from the printer capabilities that you select when the dialog box appears. These are configured in your printer options, but they can be changed in the dialog box too (Click Properties | Advanced | Print-Quality to change DPI).

Looking through the API I can change these values, but the current structure of the module will need changing so that there is an extra function call between printer selection and the page print routine. I'll have a look over the next few days.


Fielder(Posted 2015) [#15]
Thank you very much Scaremonger for your great MOD!

for the DPIs... the issue is that laser printers have 600 or 1200 dpi resolutions... and i've not the choice of value lower than 600 (i've tried 2 HP printers) and at 600 the spool is 75mb...


Fielder(Posted 2015) [#16]
Found my issue for long times and large Spool....

IMAGES

if i place a 600x800 image (that is just 2.5x3.5 cm on paper) the rendering time become very huge...

and on images the coords on floating points doesn't works.. all rounded to INTs

for example:

page.DrawImage( image, 2, 1 )

is equal that

page.DrawImage( image, 2.3 , 1.5 )


by the way , great work Scaremonger!


Scaremonger(Posted 2015) [#17]
Hi,

Thanks for identifying the issue, I had noticed in the examples that the Cactus size changed depending on what resolution I selected and I've added it to my bug-list, however I didn't associate the two until now.

INT's on the methods has been added to the buglist.

I'm working on several improvements to the module too. Watch this space...


Takis76(Posted 2015) [#18]
I like it very much.
I would like to ask , if is it possible to print unicode fonts? or fonts in other languages.


Fielder(Posted 2015) [#19]

I'm working on several improvements to the module too. Watch this space...


Thank you again!


Chalky(Posted 2015) [#20]
Thank you Scaremonger - your continued work on this is much appreciated.


Fielder(Posted 2015) [#21]
when i use a d3d9 graphics mode:
					SetGraphicsDriver D3D9Max2DDriver()
					Graphics 300,200


i need to remove this :
SetGraphics( Printer )

from the printing code...
when print is done.. i can't have again the window refresh... (image freezed)
i need to reinitialize the d3d9 driver again.. using again the code
					SetGraphicsDriver D3D9Max2DDriver()
					Graphics 300,200


to do a multiple print is this the correct way?
Global Printer:TPrinter = New TPrinter

If Printer.Print( "My First Print Job", PageRender ) Then Print "Success..."

Printer:TPrinter = New TPrinter     'reinit the Printer? whitout closing it? removing this line the 2nd print doesn't starts

If Printer.Print( "My second Print Job", PageRender ) Then Print "Success..."

Printer.close()	'# Cleans up Printer, Page and Fonts.



And also... seems that the "font name" is not working.. iif i select the Tahoma.. or Courier new , the font is the Arial.


_PJ_(Posted 2015) [#22]
This is very well done, Scaremonger!

The whole arrangement of Printer communication in Windows is unnecessarily complicated because it has been added to and built up over the years and of course, printers have been with computers for a long time.

I am curious as to whether it is capable to Print non-graphics windows, GUI objects (gadgets) / Canvases or Panels? Using this library?


Scaremonger(Posted 2015) [#23]
@Fielder:
If you save the TGraphics object when you create the graphics...
global Screen:TGraphics = Graphics 300,200
You can then return to the screen again without re-initialising graphics like this:
SetGraphics( Screen )
However; I am personally unhappy with some of the restrictions I have found when extending Max2D and I'm considering backtracking these methods to a previous Non-Max2D version.

You shouldn't need to re-initialise the printer; I've added this to my bug-list for the next release along with improvements to the Fonts library.

@_PJ_
At the moment printing is limited to Text, lines, rectangles, oval/circles, TImages and TPixmaps and there is basic functionality for Fonts and Colour.
I've added your request to the (rather long) list of things to do.


Fielder(Posted 2015) [#24]
Thank you (again)