Printing Content Within Flash

Recently, I was given the challenge to make Flash in an eCard printable in all browsers through the HTML. The thing about printing an HTML page with Flash is that the default on all browsers is to suppress printout on background images as well as Flash Objects. The challenge was that both content from the HTML page and Flash content needed to print. The solution I came up with was to push all desired printed content into Flash and utilize Flash’s PrintJob Object.

Passing the Parameters to Flash

In my last post I already went into “Using JavaScript to Communicate With Flash”, so I will not go into detail here. Basically, the HTML data/content can be passed into the Flash by calling a Flash method with JavaScript with the desired parameters passed through. Once the desired content is passed into the Flash through the Flash method call, all the print setup work done through the Flash.

Printing With Flash

Printing within Flash is pretty straight forward. First, create a Sprite that will hold your printed content with the desired dimensions, design, and layout. I find that I typically don’t want to mess with the he original Flash content if it must keep its display on the screen the way it is currently displaying. However, the content may need to display slightly differently on the printed page that it does on the screen. I have found that either the original Flash movie must be cloned, reloaded, or captured as a Bitmap and passed into a printPage sprite.

Capturing the Flash content as a bitmap is one way to get the current state of the animation without having to reload any of the animation or other content if your movie is complex. However, by using a bitmap, you will lose the vector qualities Flash can bring and will pixelate your final print output. One way I found to increase the quality of a vector-to-bitmap graphic is to double the size of the vector movieclip before capturing the bitmap of the displayObject, and then reducing the size of the bitmap, will give you more pixels to print from, thus increasing your print quality. Capturing a bitmap may not be necessary; If the display object is simple enough to add straight to the print sheet, then do it as it will retain all vectors that will print much more cleanly.

Once you have the content for your print-job laid out the way you want, pass that Sprite into your PrintJob object. The PrintJob object will handle all the work for you. The challenging part is handling the page if it goes beyond the printable space. Either you must truncate the content or loop through the content to create new Sprites for each new page that needs to print. With my example, the content was intended for a single page, but at times the content stretched beyond the printable area, I was then forced to truncate some of the text if it went beyond the limits of the page. The other option was to decrease the font size until it fit, but we decided on the former solution for this project to keep all text sizes consistent.

Another consideration when printing is accounting for landscape vs vertical layout the user can select when printing. You may need additional logic to change the layout to fit the content differently according to what gets selected:

if (myPrintJob.start()) {
	var mw:Number;
	var mh:Number;
	if (myPrintJob.orientation=="portrait"){
		mw=MAX_WIDTH //
		// do something
	}else if (myPrintJob.orientation=="landscape"){
		mh=MAX_WIDTH; // mh becomes the MAX_WIDTH;
		mw=MAX_HEIGHT // mw becomes the MAX_HEIGHT;
		// do something else
	}
}

Handling Multiple Pages

Perhaps you need to print multiple pages. Lets say you have a Flash gallery that you want to print every item and description in a format that is suitable for viewing on a printed page. This may mean that the format for the print-job is different from what is seen on the screen. The best way I have found to do this is to loop through all the items and basically recreate the pages for print. This means reloading images and adding them to a new page. If the content goes beyond the maxHeight of the page, then you create a new sprite to push that content to. Here is some sample code that does this:

...
// within loop
if (image_mc.y + image_mc.height>MAX_HEIGHT-image_mc.height){
	_sheetIndex++;
	startY= 25;
	_sheet = new Sprite();
	addChild(_sheet)
	_pagesToPrint_array.push(_sheet)
}
_sheet.addChild(image_mc);
if (curIndex>=imagesLength){
	printSheet()
}
private function printSheet():void{
	var pl:int = _pagesToPrint_array.length;
	if (myPrintJob.start()) {
		for (var v=0; v<pl; v++){
			myPrintJob.addPage(_pagesToPrint_array[v], null, null, 1);
		}
		myPrintJob = null;
		removeAll() // clear all _sheet(s) once printed
	}
}

If you have quite a bit of content that needs created for the printed sheets, it will take a bit of time to compile the job. It is a good idea to have a dialogue to tell the user it is compiling the print. I have found it useful when printing multiple pages with many images that need loaded.

Below is a good example of a gallery I developed that prints the items. Note that the print button is in HTML that passes to the Flash with JavaScript. All the images are reloaded into holder sprites when printed and then disposed of once the print is complete.

Printing a Flash Gallery

Conclusion

There may be other solutions that could work, but this customized solution gave me the control that I needed to output the content in the desired fashion with direct control over the elements. Printing a page within the Flash environment works well and gives you greater control than simply printing through the browser.