Re: speed up print(Graphics g, PageFormat pf, int pageIndex)
In article <e4c099$lq8$1@ss408.t-com.hr>, "Dado" <mario_zupan@inet.hr>
wrote:
"Steve W. Jackson" <stevewjackson@charter.net> je napisao u poruci
interesnoj grupi:stevewjackson-E87424.13263915052006@individual.net...
In article <e46pkj$q0g$1@ss408.t-com.hr>, "Dado" <mario_zupan@inet.hr>
wrote:
I
In a Printable/Pageable class print(Graphics g, PageFormat pf, int
pageIndex) is calling x times as is needed to send graphics to a
printer.
It is pretty slow. What I need to change in a print method to get better
printing perforamnce?
There's not anything at all you can do about the fact that this method
will be called some number of times. So your focus is probably best
applied to making sure that the work the method does is as fast as
possible.
In our app, we have an object that implements those two interfaces.
When instantiated (which we do in a thread), it goes through our
Do you mean that you put creating printable class:
Print print = new Print();
in a thread, or only job.print() ?
We create a Thread, which instantiates the object that implements
Printable and Pageable, creates a PrinterJob, and then creates a modal
dialog. The dialog executes job.print() in yet another thread,
monitoring until it's completed and displaying a progress indicator.
This lets the spooling process complete while the user watches, or has a
chance to cancel if desired. If they were to terminate the app while
spooling, then the access to our internal structures needed to render
pages would be lost.
underlying data to map the pages to page numbers. Because of the nature
of what we're printing, we can't render each page in advance to a
BufferedImage without having memory issues. Instead, each call to the
print method is used to find the appropriate references and render it at
that time, making it slower than we'd like.
But that's the key area to focus on for improved speed. If your data to
print is not going to break the bank, as it were, in terms of memory
needs, you can keep it handy, much like a double-buffering approach for
a Swing component, and simply draw each page on request to the Graphics
item provided in this method. At the very least, however, you could
render a page and keep it around so that the next call for the same page
number won't have to repeat the work and you could simply draw the same
thing the next time around.
= Steve =
--
Steve W. Jackson
Montgomery, Alabama
I have to print a chart (gantt) that can grow on a dozen pages. So I think
that keeping every page in a BufferedImage will cause an OutOfMemory. So,
probably I don't have any chance to speed my printing.
This is my Printable class (print method):
public class Print extends JPanel implements ActionListener, Printable{
...
public int print(Graphics pg, PageFormat pageFormat,
int pageIndex) throws PrinterException {
Graphics2D g2d = (Graphics2D) pg;
int m_maxNumPage = 7;
if (pageIndex >= m_maxNumPage)
return NO_SUCH_PAGE;
pg.translate((int)pageFormat.getImageableX(),
(int)pageFormat.getImageableY());
int wPage = (int)pageFormat.getImageableWidth();
int hPage = (int)pageFormat.getImageableHeight();
int w = poX.intValue();
int h = poY.intValue();
if (w == 0 || h == 0)
return NO_SUCH_PAGE;
int nCol = Math.max((int)Math.ceil((double)w/wPage), 1);
int nRow = Math.max((int)Math.ceil((double)h/hPage), 1);
m_maxNumPage = nCol*nRow;
int iCol = pageIndex % nCol;
int iRow = pageIndex / nCol;
int x = iCol*wPage;
int y = iRow*hPage;
int wImage = Math.min(wPage, w-x);
int hImage = Math.min(hPage, h-y);
drawGantt(g2d);
System.gc();
return PAGE_EXISTS;
}
...
}
You should not rely on the System.gc() call to do much for you.
The key to your problem's solution probably lies in the drawGantt method
you don't show. It has no information about what page it's being asked
to print, or at least none that's apparent to me in this example. But
given that printing in Java uses a banded approach, where the above
method could get called more than once for the same value of pageIndex,
your opportunity for savings of memory and time lies there.
My printing code uses the pageIndex value to look up a particular page
from pre-built maps, where it finds out the title and other information.
It also uses that to get a reference to another data structure that has
to be rendered onto the provided Graphics2D. I've now got code that
remembers the pageIndex value immediately before returning PAGE_EXISTS,
and checks against it on a subsequent call. If it's a match, I know
that the BufferedImage where I drew the current page's image before is
still good, so I simply draw it onto the provided g2d. If not, I clear
the BufferedImage and draw to it. The savings are relatively minor for
me, but it depends on how your code draws that image.
= Steve =
--
Steve W. Jackson
Montgomery, Alabama