While developing the print functionality within a framework I got stuck on the behaviour of the Flash Player print implementation.
I couldn't solve the following steps:
- Start the PrintJob and display the print dialog
- Procceed the following tasks for every print page:
- Load dynamic data into view templates (images, text, video...)
- Wait for the onLoadComplete event and add the displayed contents using PrintJob.addPage()
- Repeat for next page...
- Call PrintJob.send()
I really thought this would be an easy task but now I think it's not possible. Several attempts later I figured out that after calling PrintJob.start() there is no way to use the flash event model! This means loading contents after calling PrintJob.start() is impossible!
WOW!
So I used a workaround: I create all the print pages like I mentioned before, but without calls on the PrintJob-API. I simply store every print page as BitmapData and afterwards I create the PrintJob within a loop.
Now I have multiple other problems:
- Hundreds of pages use a huge amount of RAM and often crash the application.
- The bitmap resolution sucks so printout text quality is unsatisfying and due to point 1 I have no chance to work with higher quality.
- I must avoid skript timeouts because after preparing all the bitmaps it takes much more that 15 seconds to add all these pages to a PrintJob.
Did I slip something?
Finally I created a small example to show you the disfunctionality (PrintJobProblem.as):
-
package
-
{
-
import flash.display.Sprite;
-
import flash.events.Event;
-
import flash.geom.Rectangle;
-
import flash.printing.PrintJob;
-
import flash.text.TextField;
-
import flash.text.TextFieldAutoSize;
-
import flash.utils.getTimer;
-
-
/**
-
* @author Markus Raab - derRaab.com / superclass.de
-
*/
-
public class PrintJobProblem extends Sprite
-
{
-
private var _numPrintOuts : int;
-
private var _printOutIndex : int;
-
private var _printJob : PrintJob;
-
-
/**
-
* Starts a event based printout test after a loop based
-
* test has successfully finished.
-
*/
-
public function PrintJobProblem()
-
{
-
_numPrintOuts = 2;
-
-
runLoopBasedTest( );
-
runEventBasedTest( );
-
}
-
-
/**
-
* Demonstrates and ensures the functionality.
-
*/
-
private function runLoopBasedTest() : void
-
{
-
_printJob = new PrintJob();
-
-
if ( _printJob.start() )
-
{
-
for ( var i : int = 0; i <_numPrintOuts; i++ )
-
{
-
addPage( i );
-
}
-
-
_printJob.send();
-
}
-
}
-
-
/**
-
* Demonstrates that after calling PrintJob.start() the internal
-
* eventmodel doesn't dispatch any events at all. Everything is blocked
-
* until the script times out.
-
*/
-
private function runEventBasedTest() : void
-
{
-
_printJob = new PrintJob();
-
-
if ( _printJob.start() )
-
{
-
trace( getTimer(), "PrintJob.start() called" );
-
_printOutIndex = 0;
-
-
startAddPagesOnEnterFrame();
-
}
-
}
-
-
private function startAddPagesOnEnterFrame() : void
-
{
-
addEventListener( Event.ENTER_FRAME, onAddPagesOnEnterFrameEvent );
-
}
-
-
private function onAddPagesOnEnterFrameEvent(event : Event) : void
-
{
-
if ( _printOutIndex == _numPrintOuts )
-
{
-
stopAddPagesOnEnterFrame();
-
-
_printJob.send();
-
trace( getTimer(), "PrintJob.send()" );
-
}
-
else
-
{
-
addPage( _printOutIndex++ );
-
}
-
}
-
-
private function stopAddPagesOnEnterFrame() : void
-
{
-
removeEventListener( Event.ENTER_FRAME, onAddPagesOnEnterFrameEvent );
-
}
-
-
private function addPage( pageIndex : int ) : void
-
{
-
var page : Sprite = createPrintPage( pageIndex );
-
-
stage.addChild( page );
-
-
var viewWidth : Number = page.width;
-
var viewHeight : Number = page.height;
-
-
var scaleX : Number = _printJob.pageWidth / viewWidth;
-
var scaleY : Number = _printJob.pageHeight / viewHeight;
-
var scale : Number = Math.min( scaleX, scaleY );
-
-
page.scaleX = page.scaleY = scale;
-
-
var printRect : Rectangle = new Rectangle( 0, 0, viewWidth, viewHeight );
-
-
try
-
{
-
_printJob.addPage( page, printRect );
-
}
-
catch( e: Error )
-
{
-
trace( getTimer(), "PrintJob.addPage() failed" );
-
}
-
-
stage.removeChild( page );
-
}
-
-
private function createPrintPage( pageIndex : int) : Sprite
-
{
-
var page : Sprite = new Sprite();
-
-
var textField : TextField = new TextField();
-
textField.autoSize = TextFieldAutoSize.LEFT;
-
textField.text = "Page " + pageIndex;
-
-
page.addChild( textField );
-
-
return page;
-
}
-
}
-
}
