Archive for December, 2006

Flash Bitmap & Printing API

Saturday, December 30th, 2006

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.  

WordPress Code Inclusion (look for things to improve)

Saturday, December 30th, 2006

I think one of the things that slows some of us down most now and then, is the drive to improve on the way things are done. That’s probably why starting something new is tiresome, since there is so much to improve upon, in turn slowing progress itself. If you do not carefully state priorities, this kind of backtrack improvement can quickly lead you off track, and you’ll be improving things you never knew needed improvement in the first place, and you probably can’t remember why you are doing what you are doing anyway. Luckily “look for things to improve” is not our only mantra :), “don’t do things yourself, others can do better” is another one of my favourites, and not only because I liked the Dragon Prince series.

But look here, I’m getting side-tracked myself, the point is that looking at my earlier post, I could see straight away that I was going to need to improve on source code postings. I wanted a few things from my source-code-post-mechanism:

  1. provide source code in a readable format (keep the pretty printing)
  2. provide linenumbers that will disappear when you copy & paste the code
  3. not necessarily break formatting (wrap lines etc)
  4. provide long listings inline, with scrollbars if needed
  5. allow sources to be downloaded

Armed with my checklist I set out in the World of Wordpress plugins (it’s a pun only understood by Warcraft players). Which reminds me, if you see me reverting back to some kind of awfull shorthand, such as kk hf m8, cu l8r (okay have fun mate, see you later) it is because I play too much online games :).

(more…)

Flash Bitmap API Basics pt I

Thursday, December 28th, 2006

I’ve been delving into the new (at least it is for me) Flash bitmap API. First off, lets take a quick look at this API in general terms. Basically it allows you to convert movieclips to bitmaps, wrap bitmaps in movieclips, and operate on these bitmaps at the pixel level. At the pixel level means, that you can retrieve and set pixel values, apply bitmap filters and do a whole lot more.

For example to create a bitmap, you’d do:

var bitmapData1:BitmapData =
new BitmapData(200, 200, false, 0x000000);
bitmapData1.draw(myMC,new Matrix());

Line 1 creates a bitmap 200×200 pixels, tells it to be opaque, and the last parameter specificies the color of the opaqueness. In effect a black square.
Using line 2 you could draw another clip or bitmap into the newly created bitmap.

To show the bitmap you could do:

_root.attachBitmap(bitmapData1, _root.getNextHighestDepth());

(more…)

Welcome

Thursday, December 28th, 2006

First post, w00t! Took me some time to get the theme and system itself configured correctly, but now that I have, everything is good to go. I’ve been working on a lot of flash stuff lately, and I’ll be posting info on that the coming few weeks. Be sure to check back soon!