Flash Bitmap & Printing API
To follow up on the first bitmap post, I’m posting some code I wrote a few weeks ago to print a movieclip. The Flash Print API is pretty mind-boggling at times I think. Although this code is in no way a general print-problemsolving formula, it does show how to use the bitmap and the print API’s combined to print a movieclip (for example a screen) sized to fit on whatever paper you are providing.
It is not a utility class, and it can certainly be improved, nevertheless it provides a good starting point. It will probably be refactored and become part of our framework. Note that it does not provide page-breaking and other formatting, its purpose is to implement a PrintScreen kind of mechanism.
//the movieclip to printvar clipToPrint:MovieClip = .......;//the bounds of clipToPrint, eg {x:clipToPrint._x, ...}var bounds:Rectangle = .......;//reference to an offscreen clip to create print content in, eg _root.createEmptyMovieClip ...var printLayer:MovieClip = .......;if (System.capabilities.hasPrinting) {var my_pj:PrintJob = new PrintJob();var pages:Number = 0;if (my_pj.start()) {//if factor 1, we are printing at screenresolution, if factor is 3, its 3*screenresolutionvar factor:Number = 3;//start with a bitmap image the size of our screenvar bmpContent:BitmapData = new BitmapData(bounds.width*factor, bounds.height*factor);//and populate the bitmap with our contentpanevar matrix:Matrix = new Matrix();matrix.scale(factor,factor);bmpContent.draw(clipToPrint, matrix, null, null, null, true);//create two containers, a parent and a child container. This allows us to move and scale//the subcontainer within its parent to allow for easier placement.var printContainer:MovieClip = printLayer.createEmptyMovieClip("printContainer", 0);var printSubContainer:MovieClip = printContainer.createEmptyMovieClip("sub", 1);//create a white background on the printContainer (white paper)//use unfactored bounds since we are scaling the sub container and not the main containervar bg:TextField = printContainer.createTextField("background", 0,0,0, bounds.width, bounds.height);bg.background = true;bg.border = false;bg.backgroundColor = 0xffffff;bg.selectable = false;bg.tabEnabled = false;printContainer._visible = false; //hide it from the screenprintSubContainer.attachBitmap(bmpContent, 0); //attach the bitmap to our childvar landscape:Boolean = (my_pj.orientation == "landscape");//to correctly size our content, we can use the PrintJob.paperWidth/paperHeight properties//these are in points however, not pixels, and only available after starting the printjob//in order to relate points to pixels, we need to know two things://1: 1 point = 1/72 inch//2: the screen resolution is dpi, where the dots are pixels//So 1 point = 1/72 inch * screenDPI = x pixels//We see if the screenDPI = 72, the conversion ratio is 1:1//get values needed for pixel to point conversionvar screenDPI:Number = System.capabilities.screenDPI;var point2Pixel:Number = (1/72)*screenDPI;//declare x and y scales, since we are going to calculate//how much we need to scale the clip to fit to the pagevar xs:Number;var ys:Number;//there are two options (we use option 2)//OPTION 1: rotate with the page (no matter whether we use landscape or portrait, the print is the same)//printSubContainer._rotation = (landscape?0:-90);//if we are landscape, we need to compare paperwidth with bounds width.//if we are portrait, we will have rotated and need to compare paperwidth with bounds height//xs = (landscape?bounds.width:bounds.height) / (my_pj.paperWidth * point2Pixel);//ys = (landscape?bounds.height:bounds.width) / (my_pj.pageHeight * point2Pixel);//OPTION 2: do not rotate with the page (a landscape sized screen will print bigger and better on a landscape paper)//easier, compare clip width with paper width and same for heightxs = bounds.width / (my_pj.paperWidth * point2Pixel);ys = bounds.height / (my_pj.pageHeight * point2Pixel);//we want to keep the aspect ratio intact, so get the one we need to scale the most//and use that value for both x and y scalingvar scale:Number = Math.max (xs, ys);//instead of using this factor, use 90% of it, so we have some margins around the paperprintSubContainer._xscale = (1/scale)*90/factor;printSubContainer._yscale = (1/scale)*90/factor;//now get the size based on 100 percent and divide it in order to center the imageprintSubContainer._x = (bounds.width/scale-printSubContainer._width)/2;printSubContainer._y = (bounds.height/scale-printSubContainer._height)/2;//refer to docs for addPage parametersif (my_pj.addPage(printContainer, {xMin:0,xMax:bounds.width/scale,yMin:0,yMax:bounds.height/scale}, {printAsBitmap:true},1)) pages++;if (pages == 0) {trace("Flash could not start the printjob.");} else {my_pj.send();trace("Document sent to printer.");}bmpContent.dispose();bmpContent = null;bg.removeTextField();bg = null;printSubContainer.removeMovieClip();printSubContainer = null;printContainer.removeMovieClip();printContainer = null;} else{//printjob cancelled}} else {trace("Flash cannot find your printer.");}- Download this code: printMovieclip.txt
May 2nd, 2007 at 4:22 pm
You have some example with localToGlobal method without param target in PrintJob class?
regards
May 2nd, 2007 at 6:04 pm
Hi Leandro, could you be more specific about what you are trying to achieve?
May 15th, 2008 at 2:57 pm
Please try this your self first that’s not working…..
I have a solution if you need?????
LOL
May 15th, 2008 at 3:02 pm
Hi Alok,
no thanks I have been using this solution for quite some time now, and I’m very happy with it:). Don’t forget to replace the …. with actual references ofcourse :).
Greetz
JC