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.

  1. //the movieclip to print
  2. var clipToPrint:MovieClip = .......;
  3. //the bounds of clipToPrint, eg {x:clipToPrint._x, ...}
  4. var bounds:Rectangle = .......;
  5. //reference to an offscreen clip to create print content in, eg _root.createEmptyMovieClip ...
  6. var printLayer:MovieClip = .......;
  7.  
  8. if (System.capabilities.hasPrinting) {
  9. var my_pj:PrintJob = new PrintJob();
  10.  
  11. var pages:Number = 0;
  12. if (my_pj.start()) {
  13. //if factor 1, we are printing at screenresolution, if factor is 3, its 3*screenresolution
  14. var factor:Number = 3;
  15.  
  16. //start with a bitmap image the size of our screen
  17. var bmpContent:BitmapData = new BitmapData(bounds.width*factor, bounds.height*factor);
  18. //and populate the bitmap with our contentpane
  19. var matrix:Matrix = new Matrix();
  20. matrix.scale(factor,factor);
  21. bmpContent.draw(clipToPrint, matrix, null, null, null, true);
  22.  
  23. //create two containers, a parent and a child container. This allows us to move and scale
  24. //the subcontainer within its parent to allow for easier placement.
  25. var printContainer:MovieClip = printLayer.createEmptyMovieClip("printContainer", 0);
  26. var printSubContainer:MovieClip = printContainer.createEmptyMovieClip("sub", 1);
  27.  
  28. //create a white background on the printContainer (white paper)
  29. //use unfactored bounds since we are scaling the sub container and not the main container
  30. var bg:TextField = printContainer.createTextField("background", 0,0,0, bounds.width, bounds.height);
  31. bg.background = true;
  32. bg.border = false;
  33. bg.backgroundColor = 0xffffff;
  34. bg.selectable = false;
  35. bg.tabEnabled = false;
  36.  
  37. printContainer._visible = false; //hide it from the screen
  38. printSubContainer.attachBitmap(bmpContent, 0); //attach the bitmap to our child
  39.  
  40. var landscape:Boolean = (my_pj.orientation == "landscape");
  41. //to correctly size our content, we can use the PrintJob.paperWidth/paperHeight properties
  42. //these are in points however, not pixels, and only available after starting the printjob
  43. //in order to relate points to pixels, we need to know two things:
  44. //1: 1 point = 1/72 inch
  45. //2: the screen resolution is dpi, where the dots are pixels
  46. //So 1 point = 1/72 inch * screenDPI = x pixels
  47. //We see if the screenDPI = 72, the conversion ratio is 1:1
  48.  
  49. //get values needed for pixel to point conversion
  50. var screenDPI:Number = System.capabilities.screenDPI;
  51. var point2Pixel:Number = (1/72)*screenDPI;
  52.  
  53. //declare x and y scales, since we are going to calculate
  54. //how much we need to scale the clip to fit to the page
  55. var xs:Number;
  56. var ys:Number;
  57.  
  58. //there are two options (we use option 2)
  59.  
  60. //OPTION 1: rotate with the page (no matter whether we use landscape or portrait, the print is the same)
  61. //printSubContainer._rotation = (landscape?0:-90);
  62. //if we are landscape, we need to compare paperwidth with bounds width.
  63. //if we are portrait, we will have rotated and need to compare paperwidth with bounds height
  64. //xs = (landscape?bounds.width:bounds.height) / (my_pj.paperWidth * point2Pixel);
  65. //ys = (landscape?bounds.height:bounds.width) / (my_pj.pageHeight * point2Pixel);
  66.  
  67. //OPTION 2: do not rotate with the page (a landscape sized screen will print bigger and better on a landscape paper)
  68. //easier, compare clip width with paper width and same for height
  69. xs = bounds.width / (my_pj.paperWidth * point2Pixel);
  70. ys = bounds.height / (my_pj.pageHeight * point2Pixel);
  71.  
  72. //we want to keep the aspect ratio intact, so get the one we need to scale the most
  73. //and use that value for both x and y scaling
  74. var scale:Number = Math.max (xs, ys);
  75.  
  76. //instead of using this factor, use 90% of it, so we have some margins around the paper
  77. printSubContainer._xscale = (1/scale)*90/factor;
  78. printSubContainer._yscale = (1/scale)*90/factor;
  79. //now get the size based on 100 percent and divide it in order to center the image
  80. printSubContainer._x = (bounds.width/scale-printSubContainer._width)/2;
  81. printSubContainer._y = (bounds.height/scale-printSubContainer._height)/2;
  82.  
  83. //refer to docs for addPage parameters
  84. if (my_pj.addPage(printContainer, {xMin:0,xMax:bounds.width/scale,yMin:0,yMax:bounds.height/scale}, {printAsBitmap:true},1)) pages++;
  85.  
  86. if (pages == 0) {
  87. trace("Flash could not start the printjob.");
  88. } else {
  89. my_pj.send();
  90. trace("Document sent to printer.");
  91. }
  92.  
  93. bmpContent.dispose();
  94. bmpContent = null;
  95. bg.removeTextField();
  96. bg = null;
  97. printSubContainer.removeMovieClip();
  98. printSubContainer = null;
  99. printContainer.removeMovieClip();
  100. printContainer = null;
  101. } else{
  102. //printjob cancelled
  103. }
  104. } else {
  105. trace("Flash cannot find your printer.");
  106. }
  107.  

4 Responses to “Flash Bitmap & Printing API”

  1. Leandro Amano Says:

    You have some example with localToGlobal method without param target in PrintJob class?

    regards

  2. Hans Wichman Says:

    Hi Leandro, could you be more specific about what you are trying to achieve?

  3. Alok Says:

    Please try this your self first that’s not working…..
    I have a solution if you need?????
    LOL

  4. Hans Wichman Says:

    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

Leave a Reply