Flash Printing AS 3.0
Printing in Flash can be extremely simple, but also has the potential to get quite complex as your needs become more involved. Fortunately, ActionScript 3.0 makes it easier, and in some cases you will not be able to get a good print in earlier versions of ActionScript. So let’s get started with some of the printing basics.
Print Classes
In ActionScript 3.0 you have three classes used for printing. You can include all three of them in your project with the following line:
import flash.printing.*;
That import will give you access to the following classes:
- flash.printing.PrintJob: This is the workhorse for printing. This class gives you the means to pull up the print dialogue, and then add your content before actually executing the print command. The PrintJob also has information about the width and height of a printed page as determined by how the user sets up their print options. These values can vary dramatically even with the same paper size across different printers.
- flash.printing.PrintJobOrientation: This is the class used to determine the print settings the user selected. It is important to note that you cannot force page orientation to be what you want. It is completely defined by what the user sets up in their print dialogue. This class exists mainly to detect if the user chose landscape or portrait layout when they printed.
- flash.printing.PrintJobOptions: This class feels kind of strange to me because it basically extends the Object class and adds a single boolean property. It is used when you add pages to a print job to indicate whether or not you want to print as a bitmap. I am guessing that future updates will extend this object to include more options and tools, but at this point, it seems kind of strange to have to pass a specific object as your parameter when a Boolean would suffice. We will discuss why you will want to print as bitmap, and also reasons why you may not want to.
Basic Printing
Doing really basic printing is very quick and easy. The following is code that will print a red square to your page:
var pj:PrintJob = new PrintJob();
if(pj.start)
{
var tSprite:Sprite = new Sprite();
tSprite.graphics.beginFill(0xFF0000,1);
tSprite.graphics.drawRect(0,0,100,100);
pj.addPage(tSprite);
pj.send();
}
Page Orientation
Printing a red square is not all that exciting. Even printing an existing Sprite or MovieClip can be difficult. You may need to do something as follows (assume printSprite is the sprite we want to print and it is already defined and created):
var pj:PrintJob = new PrintJob();
if(pj.start())
{
if(pj.orientation == PrintJobOrientation.LANDSCAPE)
{
if(printSprite.width<printSprite.height)
{//we just detected that our printed sprite is actually
portrait in it's layout.
printSprite.rotation=90;
}
}
else if(printSprite.height<printSprite.width)
{//we just detected that our printed sprite is landscape
in nature but our page is portrait
printSprite.rotation=90;
}
pj.addPage(printSprite);
pj.send();
printSprite.rotation=0;//reset just in case it is also
displayed on screen.
}
Rather than try to force the user to use a selected page layout, you may want to just intelligently modify your printed object to work best with what they chose. Of course, you will want to consider usability when doing this because it could prove frustrating to a user if they actually want to print the flash in a way you are now prohibiting. The above example does however demonstrate some of the basics to work with page orientation.
Multi Page Printing
Printing becomes most useful when you can handle a dynamic number of items to print, and work out all the paging accordingly. Say for example you have an array of custom objects that may be part of a shopping cart or something of that nature. If you want to print a shopping cart that could have any number of items, you will have to understand how to print multiple pages. The following example assumes that a utility function has been defined and that it creates a Sprite to display a single instance of a class CartItem, and that we have an array of CartItem objects called cartItems. It is also not going to worry about page orientation for this example.
var pj:PrintJob();
var curPage:Sprite = new Sprite();
if(pj.start())
{
for(var i=0; i<cartItems.length;i++)
{
var cItem:CartItem = cartItems[i] as CartItem;
var printSprite = buildPrintCartItem(pj.width,cItem);
if(curPage.height+printSprite.height <pj.pageHeight)
{
curPage.addChild(printSprite);
}
else
{//go with our current page then start a new page with
the latest cart item in it.
pj.addPage(curPage); curPage = new Sprite(); curPage.addChild(printSprite); }
} pj.send();
}
Important: It is very important to note that anything that happens in the buildPrintCartItem function must finish it’s visual creation without any asynchronous behavior. If for example, your buildPrintCartItem were to load an image from a url, you would print before the image load completes. It is not very safe to try and wait for those load events to complete because you have a finite time in which to call pj.send. If you need to have external images printing, you will hopefully be printing images that are already somewhere in your display tree. If that is the case you have to actually pull the image from your already loaded DisplayObject. It is then up to you to make sure that you keep a copy of the displayed item on screen while using the already created one in print.
Printing as Bitmap
For most printing needs, you can get what you need with variations of the code above. However, there will be times when you will need to set up a PrintJobOptions object and pass it into the pj.addPage function.
var pjo:PrintJobOptions = new PrintJobOptions(true); ... ... pj.addPage(curPage,null,pjo);
The second parameter takes a Rectangle object you can create from the flash.geom package. It can be used to define a specific portion of the Sprite that will be printed. I am sure that can be useful, but I haven’t had much cause to use it so far.
Why use printAsBitmap?
- Transparency Support: If you have transparency in the content you are printing out, you will need to use printAsBitmap. Otherwise all areas that have less than an opacity of 100% will print as white. Gradients are supported so long as every color in the gradient has full opacity on it. If you have gradients with transparency in them you cannot print them correctly without printAsBitmap.
- Blend mode support: Any blend mode other than normal will not print correctly without using printAsBitmap.
Why not to use printAsBitmap
- Font quality: When you print it as a bitmap it basically converts the displayed information to a 72dpi raster image. Printers usually can work with font files to give you quality printed text. When you convert to raster, you lose the font information and your fonts will look pixilated.
Advanced Bitmap Printing
It is possible to essentially do a hybrid of the two methods, but it can be more work. There is a way to make a bitmap copy of an existing DisplayObject and use that for your printing. So you could write code that finds a target DisplayObject that won’t print without being printed as bitmap. This code can basically make a raster representation of that DisplayObject and return it to be used in your print. If you do this, you won’t have to use printAsBitmap because you have essentially done the work on your own. The following code will give you a raster representation of a Sprite:
//make sure to import flash.display.BitmapData and flash.display.Bitmap private function makeBitmapCopy(sp:Sprite):Sprite {var bmd:BitmapData = new BitmapData(sp.width,sp.height); bmd.draw(sp); var bmp:Bitmap = new Bitmap(bmd); var returner:Sprite = new Sprite(); returner.addChild(bmp); return returner;}
From here it will be up to your code structure and architecture to be built in a way that allows you to easily make the bitmap copies as you are building each printed page.
Final Thoughts
This tutorial should give you all the tools you will need to understand the capabilities of printing in Flash. I do recommend that you install a print driver that will print to PDF or something along those lines. That way you can print and debug your printing process without plowing through reams of paper. Make sure however to test on actual paper, preferably on a wide variety of printers to make sure you properly account for differing page sizes etc.












