Keiron Liddle ([EMAIL PROTECTED]) wrote To FOP on Wed, May 22, 2002 at 10:30:45AM +0200:
> > Yes the several patches is good, thanks. > This way the appropriate ones can be applied to both code bases. > > I agree that 3 is probably better and should be done for the development > code. 1 is suitable for a quick solution for the maintenance branch. > > As for the extension, this is really for the development code. I don't > know exactly where you are getting your data etc. from but the new code > could handle this as an extension. The svg drawing itself is an > extension and it could be done in the same way. You supply a handler on > the user agent, this handler receives some xml data and has access to > the pdf document, streams etc. This could make it easier but I would > need more info. In brief, the algo is this: 1) before pdf generation, the client program sets up the on-the-fly snapshot objects - each is a subclass of OnTheFlyFopImage, supplying a paint(Graphics2D) routine. 2) the client then registers the images somewhere in the FOP api (in my current hack, with FopImageFactory directly) with a url like "onthefly:uniquename" 3) the client then runs the PDF generation 4) the PDFRenderer, when it encounters an external image reference with an "onthefly:uniquename" URL, looks up the correspondingly-named OnTheFlyFopImage in the registry 5) the PDFRenderer then sets up a PDFGraphics2D and runs OnTheFlyFopImage.paint on it. 6) at some point before or after pdf generation, the application can clear the registry, freeing up any memory used by the OnTheFlyFopImages. If you can describe in general what the algo would be for an extension I'll be glad to try and implement it. Incidentally, am I getting the development or maintenance branch when I just do a `cvs checkout`? Here are the actual examples from my current (outside of FOP) code. Incidentally, I really think there needs to be a library class with static methods like my convert() that allow a simple default embedding for folks - that's a lot of code to have to write just to run fop. ... snip .... public void createOnTheFly(MapViewPanel sourcePanel, File reportDir) { SystemLog.singleton().enter("Creating on-the-fly snapshots..."); try { FopImageFactory.clearCache(); FopImageFactory.clearOnTheFlyImages(); Iterator e = getSnapshots().iterator(); int i = 0; while (e.hasNext()) { RenderMold currentSnapshot = (RenderMold)e.next(); currentSnapshot.setMonochromeBackground(monochromeBackground); currentSnapshot.setInvertBackgroundColor(!noColorFiltering); currentSnapshot.setPrinting(true); SystemLog.singleton().enter("Rendering snapshot " + currentSnapshot + " to image"); this.setDrawFinerThanScale(currentSnapshot.getScale()); FopImageFactory.addOnTheFlyImage("Snapshot" + i, new OnTheFlySnapshot(sourcePanel, currentSnapshot)); i++; } // wrap up this.setDrawFinerThanScale(null); } catch ( Exception oopsie ) { System.out.println("problem creating image in Snapshot source"); Death.instant(oopsie); } } ... snip .... private class OnTheFlySnapshot extends OnTheFlyFopImage { private MapViewPanel sourcePanel; private RenderMold mold; public OnTheFlySnapshot(MapViewPanel sourcePanel, RenderMold mold) throws FopImageException { super("onthefly:Snapshot", viewFinder.getWidth(), viewFinder.getHeight()); this.sourcePanel = sourcePanel; this.mold = mold; } public void paint(Graphics2D graphics) { if (isNoColorFiltering()) GUILib.setRenderingHintsForPrinting(graphics); else GUILib.setRenderingHintsForInvertedPrinting(graphics); /* SystemLog.singleton().enter("Setting on-the-fly clip to: " + viewFinder.getWidth() + ", " + viewFinder.getHeight()); graphics.setClip(0, 0, viewFinder.getWidth(), viewFinder.getHeight()); */ graphics.setFont(sourcePanel.getFont()); if (noColorFiltering) { graphics.setColor(Color.black); graphics.fillRect(0, 0, viewFinder.getWidth(), viewFinder.getHeight()); } else { graphics.setColor(Color.white); graphics.fillRect(0, 0, viewFinder.getWidth(), viewFinder.getHeight()); } // iterate through layers and renderers to paint Iterator it = sourcePanel.layers(); while (it.hasNext()) { MapViewLayer currentLayer = (MapViewLayer)it.next(); SystemLog.singleton().enter("Rendering " + currentLayer + " to PDF"); Iterator nit = currentLayer.getRenderers().iterator(); while (nit.hasNext()) { MapDataRenderer currentRenderer = (MapDataRenderer)nit.next(); currentRenderer.render(mold, graphics, null); } } // graphics.dispose(); } } ... snip .... public static void convert(File xmlFile, File xslFile, File foFile, File pdfFile) { try { SystemLog.singleton().enter("Converting xml to pdf."); SystemLog.singleton().logMemoryUsage(); // clear annoying image cache KLUDGE FopImageFactory.clearCache(); Driver driverInstance = new Driver(); Hierarchy hierarchy = Hierarchy.getDefaultHierarchy(); PatternFormatter formatter = new PatternFormatter( "[%{priority}]: %{message}\n%{throwable}" ); LogTarget target = null; target = new StreamTarget(System.out, formatter); hierarchy.setDefaultLogTarget(target); Logger log = hierarchy.getLoggerFor("fop"); log.setPriority(Priority.INFO); driverInstance.setLogger(log); PDFRenderer rendererInstance = new PDFRenderer(); // set baseDir Configuration.put("baseDir", xmlFile.getParentFile().toURL().toExternalForm()); SystemLog.singleton().enter("Converting " + xmlFile + " to " + foFile + " using " + xslFile); TransformerFactory tFactory = TransformerFactory.newInstance(); Transformer transformer = tFactory.newTransformer(new StreamSource(xslFile)); FileOutputStream foOut = new FileOutputStream(foFile); transformer.transform(new StreamSource(xmlFile), new StreamResult(foOut) ); foOut.close(); SystemLog.singleton().enter("Converting " + foFile + " to " + pdfFile); InputHandler inputHandler = new FOInputHandler(IOLib.pathToURL(foFile.getCanonicalPath())); InputSource inputSource = inputHandler.getInputSource(); BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(pdfFile)); // reset driver and supply properties driverInstance.reset(); driverInstance.setRenderer(rendererInstance); driverInstance.setInputSource(inputSource); driverInstance.setOutputStream(out); driverInstance.run(); out.close(); } catch (IllegalArgumentException oopsie) { SystemLog.singleton().error(oopsie); SystemLog.singleton().enter("Probably demo, ignoring."); } catch (Exception oopsie) { SystemLog.singleton().error(oopsie); SystemLog.singleton().enter("Probably demo, ignoring."); } SystemLog.singleton().enter("Done converting xml to pdf."); SystemLog.singleton().logMemoryUsage(); } ... snip .... > > On Tue, 2002-05-21 at 16:00, Paul Reavis wrote: > > Agreed. Here are some possible solutions: > > 1) a boolean switch (in the api or system properties) > > 2) intelligence in the buffer itself, where it uses a tempfile after a > > certain size is reached > > 3) better overall architecture where buffers are immediately flushed > > to output rather than remaining in memory > > > > (3) seems best and is in line with the next-gen design documents I see > > on the fop site, but I don't know how far along y'all are with that. I > > have to use a similar architecture for my map translation software; > > GIS systems are hundreds of megabytes and scalability requires a flat > > memory usage model. All my buffers are strictly memory-limited. > > > > (1) is easy enough > > > > (2) would be fine but probably has pitfalls; the problem is that there > > are a _lot_ of these buffers and PDFStreams running around, and > > therefore it's a global problem - I counted dozens for one plot, 24MB > > total. > > > > I was planning on using a switch for the cvs patch, unless y'all have > > (3) figured out. > > > > > I don't see the need for an extra PDFStreamGraphics2D class. Modifying > > > the PDFGraphics2D should suffice. > > > > Agreed. I just didn't want to break the existing (the current patch > > uses PDFStreamGraphics2D just for my case). > > > > > An extension may work better in this situation with the development > > > code. If I understand the problem properly. > > > > ?? An extension to the code, or a file extension for the URL? I'm not > > sure what you mean. > > > > As far as my plans for the other features: > > > > I figure the drawImage hack is a no-brainer. It's just the right thing > > to do in that instance. The additional memory usage should be no big > > deal (it's a hash of image pointer to integer ID). > > > > I'll just modify PDFGraphics2D directly to use the underlying > > PDFStream. I think this is fine for all cases. > > > > Should I break it up into several patches? > > -> tempfile buffering > > -> drawImage hack > > -> PDFGraphics2D hack > > -> on-the-fly images > > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, email: [EMAIL PROTECTED] > -- Paul Reavis [EMAIL PROTECTED] Design Lead Partner Software, Inc. http://www.partnersoft.com --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, email: [EMAIL PROTECTED]