Affects Version/s: Adobe Flex SDK 3.2 (Release)
Fix Version/s: None
Component/s: Print Management
Environment:Affected OS(s): All OS Platforms
Affected OS(s): All OS Platforms
Language Found: English
Let me start by saying that this problem seems to occur randomly between machines, but is consistent within each machine. What I mean is that if breaks on machine A using Flash 10 and print driver X, it will always break using that combination. However, if you go to another machine, it may not break with those settings. Though, you will find on another machine it may break when you use Flash 9 and print driver Z.
Luckily, I was able to find a repeatable condition on my development machine and was able to debug it into the framework, FlexPrintJob, specifically.
So here's what's happening. When my app prints, I take full control over the paging. That is, I create a UIComponent of each individual page. Internally, in FlexPrintJob there is code to determine if your page can fit on a printed page and if it can't it creates extra pages. Since I am sizing my pages to be exactly the size of the printed page, in theory, this extra paging code inside FlexPrintJob should never become active, but it is in a bad way and I'll explain why.
Some background. When dealing with floating point calcuations everyone knows that you can't depend on a value exactly equaling another value. Depending on how the number was calculated is may be off by a tiny epsilon, as is the case here. So, imagine you do some complex calculation and expect to get 10.0, but in reality you get 10.000000000000001. Then you have another calcuation where you do a Math.ceil on this. We'll you should have gotten 10, but you wind up getting 11, and it's unexpected. Likewise, if you use the mod (%) function and do x % 10 where x is 10.000000000000001, the result is 0.000000000000001, when 0 was expected.
Well, in FlexPrintJob, this is what's happening. When calculating the number of pages in the horizontal and vertical directions, the code divides the passed in UICompoent size by the page size. In my case they should be equal giving one page. However, because some scaling had been involved in the calcuation, under some conditions, the values are "almost" equal. In my case, they were off by about 1e-14 or so. This minor amount messed up the ceiling calculation and subsequent modulo operation and caused the number of pages algorithm to be 2 instead of one, which is what caused the blank pages in between.
Anyway, I addressed the problem by making a copy of FlexPrintJob and storing it locally with my code. I modified the ceiling calculation to substract a small epsilon prior to performing the ceiling. Likewise, when comparing the lastPageWidth and lastPageHeigth to zero, which comes from the modulo, instead of comparing it against zero, I take it's absolute value and make sure it's greater than epsilon.
In my experience, I've found that this should be standard practice when dealing with floating points. I can't tell you how many times I used this same trick in other apps when performing ceiling and floor and modulo. Basically, you substract a small epsilon prior to calling ceil and you add a small epsilon prior to calling floor.
I'm attaching my updated code if anyone one is interested. Please don't ask for me to attach repeating test case, since it's very device specific. The bottom line if anyone cares is that ceil on Number is bound to fail at some point if you don't do this, so I think my fix is sound.
Hope this helps someone.