KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > fop > render > awt > AWTRenderer


1 /*
2  * $Id: AWTRenderer.java,v 1.38.2.12 2003/03/02 16:55:17 pietsch Exp $
3  * ============================================================================
4  * The Apache Software License, Version 1.1
5  * ============================================================================
6  *
7  * Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without modifica-
10  * tion, are permitted provided that the following conditions are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright notice,
16  * this list of conditions and the following disclaimer in the documentation
17  * and/or other materials provided with the distribution.
18  *
19  * 3. The end-user documentation included with the redistribution, if any, must
20  * include the following acknowledgment: "This product includes software
21  * developed by the Apache Software Foundation (http://www.apache.org/)."
22  * Alternately, this acknowledgment may appear in the software itself, if
23  * and wherever such third-party acknowledgments normally appear.
24  *
25  * 4. The names "FOP" and "Apache Software Foundation" must not be used to
26  * endorse or promote products derived from this software without prior
27  * written permission. For written permission, please contact
28  * apache@apache.org.
29  *
30  * 5. Products derived from this software may not be called "Apache", nor may
31  * "Apache" appear in their name, without prior written permission of the
32  * Apache Software Foundation.
33  *
34  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
35  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
36  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
37  * APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
38  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
39  * DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
40  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
41  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
42  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
43  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44  * ============================================================================
45  *
46  * This software consists of voluntary contributions made by many individuals
47  * on behalf of the Apache Software Foundation and was originally created by
48  * James Tauber <jtauber@jtauber.com>. For more information on the Apache
49  * Software Foundation, please see <http://www.apache.org/>.
50  */

51 package org.apache.fop.render.awt;
52
53 import org.apache.fop.apps.*;
54 import org.apache.fop.datatypes.*;
55 import org.apache.fop.image.*;
56 import org.apache.fop.layout.*;
57 import org.apache.fop.layout.inline.*;
58 import org.apache.fop.render.AbstractRenderer;
59 import org.apache.fop.svg.*;
60 import org.apache.fop.viewer.*;
61
62 import org.w3c.dom.svg.*;
63 import org.w3c.dom.Document JavaDoc;
64
65 import org.apache.batik.bridge.*;
66 import org.apache.batik.gvt.*;
67 import org.apache.batik.gvt.event.*;
68
69 import java.awt.*;
70 import java.awt.Image JavaDoc;
71 import java.awt.font.*;
72 import java.awt.geom.*;
73 import java.awt.image.BufferedImage JavaDoc;
74 import java.awt.print.*;
75 import java.io.*;
76 import java.net.MalformedURLException JavaDoc;
77 import java.net.URL JavaDoc;
78 import java.util.*;
79 import javax.swing.*;
80
81 /**
82  * @author <a HREF="mailto:Juergen.Verwohlt@jCatalog.com">Juergen Verwohlt</a>
83  * @author <a HREF="mailto:Rainer.Steinkuhle@jCatalog.com">Rainer Steinkuhle</a>
84  * @author <a HREF="mailto:Stanislav.Gorkhover@jCatalog.com">Stanislav
85  * Gorkhover</a>
86  * @author <a HREF="mailto:mark-fop@inomial.com">Mark Lillywhite</a>
87  */

88
89 /*
90  * Mark Lillywhite(?) made the following comment: Did lots of
91  * cleaning up and made the class implement the new Renderer
92  * interface. This class could also do with a general audit,
93  * and I suspect it's not swing-thread-safe either.
94 */

95 public class AWTRenderer extends AbstractRenderer implements Printable, Pageable {
96
97     protected int pageWidth = 0;
98     protected int pageHeight = 0;
99     protected double scaleFactor = 100.0;
100     protected int pageNumber = 0;
101     protected Vector pageList = new Vector();
102     protected ProgressListener progressListener = null;
103     protected Translator res = null;
104
105     protected Map fontNames = new java.util.HashMap JavaDoc();
106     protected Map fontStyles = new java.util.HashMap JavaDoc();
107     protected Color saveColor = null;
108
109     /**
110      * Image Object and Graphics Object. The Graphics Object is the Graphics
111      * object that is contained withing the Image Object.
112      */

113     private BufferedImage JavaDoc pageImage = null;
114     protected Graphics2D graphics = null;
115
116     /**
117      * The current (internal) font name
118      */

119     protected String JavaDoc currentFontName;
120
121     /**
122      * The current font size in millipoints
123      */

124     protected int currentFontSize;
125
126     /**
127      * The current colour's red, green and blue component
128      */

129     protected float currentRed = 0;
130     protected float currentGreen = 0;
131     protected float currentBlue = 0;
132
133     /**
134      * Used to make the last font and color available to
135      * renderInlineSpace() to render text decorations.
136      */

137     protected java.awt.Font JavaDoc lastFont = null;
138     protected Color lastColor = null;
139
140     /**
141      * The parent component, used to set up the font.
142      * This is needed as FontSetup needs a live AWT component
143      * in order to generate valid font measures.
144      */

145     protected Component parent;
146
147     /**
148      * options
149      */

150     protected java.util.Map JavaDoc options;
151
152     /**
153      * set up renderer options
154      */

155     public void setOptions(java.util.Map JavaDoc options) {
156         this.options = options;
157     }
158
159     public AWTRenderer(Translator aRes) {
160         res = aRes;
161     }
162
163     /**
164      * Sets parent component which is used to set up the font.
165      * This is needed as FontSetup needs a live AWT component
166      * in order to generate valid font measures.
167      * @param parent the live AWT component reference
168      */

169     public void setComponent(Component parent) {
170         this.parent = parent;
171     }
172
173     public int getPageNumber() {
174         return pageNumber;
175     }
176
177     public void setPageNumber(int aValue) {
178         pageNumber = aValue;
179     }
180
181     public void setScaleFactor(double newScaleFactor) {
182         scaleFactor = newScaleFactor;
183     }
184
185     public double getScaleFactor() {
186         return scaleFactor;
187     }
188
189     public BufferedImage JavaDoc getLastRenderedPage() {
190         return pageImage;
191     }
192
193     /**
194      * add a line to the current stream
195      *
196      * @param x1 the start x location in millipoints
197      * @param y1 the start y location in millipoints
198      * @param x2 the end x location in millipoints
199      * @param y2 the end y location in millipoints
200      * @param th the thickness in millipoints
201      * @param r the red component
202      * @param g the green component
203      * @param b the blue component
204      */

205
206     // corrected 7/13/01 aml,rlc to properly handle thickness
207
//
208
protected void addLine(int x1, int y1, int x2, int y2, int th, float r,
209                            float g, float b) {
210         graphics.setColor(new Color(r, g, b));
211         int x = x1;
212         int y = y1;
213         int height, width;
214         if (x1 == x2) // vertical line
215
{
216             height = y2 - y1;
217             if (height > 0) // y coordinates are reversed between fo and AWT
218
{
219                 height = -height;
220                 y = y2;
221             }
222             width = th;
223             if (width < 0) {
224                 width = -width;
225                 x -= width;
226             }
227         } else // horizontal line
228
{
229             width = x2 - x1;
230             if (width < 0) {
231                 width = -width;
232                 x = x2;
233             }
234             height = th;
235             if (height > 0) // y coordinates are reversed between fo and AWT
236
{
237                 height = -height;
238                 y -= height;
239             }
240         }
241         addRect(x, y, width, height, false);
242
243         // // graphics.setColor(Color.red);
244
// graphics.drawLine((int)(x1 / 1000f),
245
// pageHeight - (int)(y1 / 1000f), (int)(x2 / 1000f),
246
// pageHeight - (int)(y2 / 1000f));
247
}
248
249
250     /**
251      * draw a rectangle
252      *
253      * @param x the x position of left edge in millipoints
254      * @param y the y position of top edge in millipoints
255      * @param w the width in millipoints
256      * @param h the height in millipoints
257      * @param r the red component
258      * @param g the green component
259      * @param b the blue component
260      */

261     // changed by aml/rlc to use helper function that
262
// corrects for integer roundoff, and to remove 3D effect
263
protected void addRect(int x, int y, int w, int h, float r, float g,
264                            float b) {
265         graphics.setColor(new Color(r, g, b));
266         // graphics.setColor(Color.green);
267
addRect(x, y, w, h, true);
268     }
269
270     /**
271      * draw a filled rectangle
272      *
273      * @param x the x position of left edge in millipoints
274      * @param y the y position of top edge in millipoints
275      * @param w the width in millipoints
276      * @param h the height in millipoints
277      * @param r the red component of edges
278      * @param g the green component of edges
279      * @param b the blue component of edges
280      * @param fr the red component of the fill
281      * @param fg the green component of the fill
282      * @param fb the blue component of the fill
283      */

284
285     // changed by aml/rlc to use helper function that
286
// corrects for integer roundoff
287
protected void addRect(int x, int y, int w, int h, float r, float g,
288                            float b, float fr, float fg, float fb) {
289         graphics.setColor(new Color(r, g, b));
290         addRect(x, y, w, h, true);
291         graphics.setColor(new Color(fr, fg, fb));
292         addRect(x, y, w, h, false);
293     }
294
295     /**
296      * draw a filled rectangle in the current color
297      *
298      * @param x the x position of left edge in millipoints
299      * @param y the y position of top edge in millipoints
300      * @param w the width in millipoints
301      * @param h the height in millipoints
302      * @param drawAsOutline true for draw, false for fill
303      */

304
305     // helper function by aml/rlc to correct integer roundoff problems
306
//
307
protected void addRect(int x, int y, int w, int h,
308                            boolean drawAsOutline) {
309         int startx = (x + 500) / 1000;
310         int starty = pageHeight - ((y + 500) / 1000);
311         int endx = (x + w + 500) / 1000;
312         int endy = pageHeight - ((y + h + 500) / 1000);
313         if (drawAsOutline) {
314             graphics.drawRect(startx, starty, endx - startx, endy - starty);
315         } else {
316             //don't round down to zero
317
if (w != 0 && endx == startx) endx++;
318             if (h != 0 && endy == starty) endy++;
319             graphics.fillRect(startx, starty, endx - startx, endy - starty);
320         }
321     }
322
323     protected void addFilledRect(int x, int y, int w, int h,
324                                  ColorType col) {
325         float r = col.red();
326         float g = col.green();
327         float b = col.blue();
328         addRect(x, y, w, h, r, g, b, r, g, b);
329     }
330
331     /**
332      * To configure before print.
333      *
334      * Choose pages
335      * Zoom factor
336      * Page format / Landscape or Portrait
337      */

338     public void transform(Graphics2D g2d, double zoomPercent, double angle) {
339         AffineTransform at = g2d.getTransform();
340         at.rotate(angle);
341         at.scale(zoomPercent / 100.0, zoomPercent / 100.0);
342         g2d.setTransform(at);
343     }
344
345     protected void drawFrame() {
346
347         int width = pageWidth;
348         int height = pageHeight;
349
350         graphics.setColor(Color.white);
351         graphics.fillRect(0, 0, width, height);
352         graphics.setColor(Color.black);
353         graphics.drawRect(-1, -1, width + 2, height + 2);
354         graphics.drawLine(width + 2, 0, width + 2, height + 2);
355         graphics.drawLine(width + 3, 1, width + 3, height + 3);
356
357         graphics.drawLine(0, height + 2, width + 2, height + 2);
358         graphics.drawLine(1, height + 3, width + 3, height + 3);
359     }
360
361     /**
362      * Retrieve the number of pages in this document.
363      *
364      * @return the number of pages
365      */

366     public int getPageCount() {
367         return pageList.size();
368     }
369
370     public void removePage(int page) {
371         pageList.removeElementAt(page);
372     }
373
374     public void render(int aPageNumber) {
375         if(aPageNumber >= pageList.size())
376             return;
377
378         try {
379             render((Page) pageList.get(aPageNumber));
380         } catch(IOException e) {
381             e.printStackTrace();
382             // This exception can't occur because we are not dealing with
383
// any files
384
}
385
386     }
387
388     public void render(Page page, OutputStream stream)
389     throws IOException {
390         pageList.add(page);
391     }
392
393     public void render(Page page)
394     throws IOException {
395         idReferences = page.getIDReferences();
396
397         pageWidth = (int)((float)page.getWidth() / 1000f + .5);
398         pageHeight = (int)((float)page.getHeight() / 1000f + .5);
399
400
401         pageImage =
402             new BufferedImage JavaDoc((int)((pageWidth * (int)scaleFactor) / 100),
403                               (int)((pageHeight * (int)scaleFactor) / 100),
404                               BufferedImage.TYPE_INT_RGB);
405
406         graphics = pageImage.createGraphics();
407
408         // Nov 18, 2002 - [aml/rlc] eliminates layout problems at various scaling
409

410         graphics.setRenderingHint (RenderingHints.KEY_FRACTIONALMETRICS,
411                                    RenderingHints.VALUE_FRACTIONALMETRICS_ON);
412
413         transform(graphics, scaleFactor, 0);
414         drawFrame();
415
416         renderPage(page);
417     }
418
419     public void renderPage(Page page) {
420
421         this.currentFontName = "";
422         this.currentFontSize = 0;
423
424         renderRegions(page);
425         // SG: Wollen wir Links abbilden?
426
/*
427          * if (page.hasLinks()) {
428          * ....
429          * }
430          */

431     }
432
433     protected void doFrame(org.apache.fop.layout.Area area) {
434         int w, h;
435         int rx = this.currentAreaContainerXPosition;
436         w = area.getContentWidth();
437
438         if (area instanceof BlockArea) {
439             rx += ((BlockArea)area).getStartIndent();
440         }
441
442         h = area.getContentHeight();
443         int ry = this.currentYPosition;
444
445         rx = rx - area.getPaddingLeft();
446         ry = ry + area.getPaddingTop();
447         w = w + area.getPaddingLeft() + area.getPaddingRight();
448         h = h + area.getPaddingTop() + area.getPaddingBottom();
449
450     doBackground(area, rx, ry, w, h);
451
452         rx = rx - area.getBorderLeftWidth();
453         ry = ry + area.getBorderTopWidth();
454         w = w + area.getBorderLeftWidth() + area.getBorderRightWidth();
455         h = h + area.getBorderTopWidth() + area.getBorderBottomWidth();
456
457         BorderAndPadding bp = area.getBorderAndPadding();
458         ColorType borderColor;
459
460         if (area.getBorderTopWidth() != 0) {
461             borderColor = bp.getBorderColor(BorderAndPadding.TOP);
462             // addLine(rx, ry, rx + w, ry, area.getBorderTopWidth(), // corrected aml/rlc
463
addLine(rx, ry, rx + w, ry, -area.getBorderTopWidth(),
464                     borderColor.red(), borderColor.green(),
465                     borderColor.blue());
466         }
467
468         if (area.getBorderLeftWidth() != 0) {
469             borderColor = bp.getBorderColor(BorderAndPadding.LEFT);
470             addLine(rx, ry, rx, ry - h, area.getBorderLeftWidth(),
471                     borderColor.red(), borderColor.green(),
472                     borderColor.blue());
473         }
474
475         if (area.getBorderRightWidth() != 0) {
476             borderColor = bp.getBorderColor(BorderAndPadding.RIGHT);
477             addLine(rx + w, ry, rx + w, ry - h,
478                     // area.getBorderRightWidth(), borderColor.red(), // corrected aml/rlc
479
-area.getBorderRightWidth(), borderColor.red(),
480                     borderColor.green(),
481                     borderColor.blue());
482         }
483
484         if (area.getBorderBottomWidth() != 0) {
485             borderColor = bp.getBorderColor(BorderAndPadding.BOTTOM);
486             addLine(rx, ry - h, rx + w, ry - h, area.getBorderBottomWidth(),
487                     borderColor.red(), borderColor.green(),
488                     borderColor.blue());
489         }
490     }
491
492
493
494     protected Rectangle2D getBounds(org.apache.fop.layout.Area a) {
495         return new Rectangle2D.Double(currentAreaContainerXPosition,
496                                       currentYPosition,
497                                       a.getAllocationWidth(), a.getHeight());
498     }
499
500     public void setupFontInfo(FontInfo fontInfo)
501         throws FOPException {
502         // create a temp Image to test font metrics on
503
BufferedImage JavaDoc fontImage =
504             new BufferedImage JavaDoc(100, 100, BufferedImage.TYPE_INT_RGB);
505         FontSetup.setup(fontInfo, fontImage.createGraphics());
506     }
507
508     public void renderDisplaySpace(DisplaySpace space) {
509         int d = space.getSize();
510         this.currentYPosition -= d;
511     }
512
513     /**
514      * Renders an image, scaling it to the given width and height.
515      * If the scaled width and height is the same intrinsic size
516      * of the image, the image is not scaled.
517      *
518      * @param x the x position of left edge in millipoints
519      * @param y the y position of top edge in millipoints
520      * @param w the width in millipoints
521      * @param h the height in millipoints
522      * @param image the image to be rendered
523      * @param fs the font state to use when rendering text
524      * in non-bitmapped images.
525      */

526     protected void drawImageScaled(int x, int y, int w, int h,
527                    FopImage image,
528                    FontState fs) {
529     // XXX: implement this
530
}
531
532     /**
533      * Renders an image, clipping it as specified.
534      *
535      * @param x the x position of left edge in millipoints.
536      * @param y the y position of top edge in millipoints.
537      * @param clipX the left edge of the clip in millipoints
538      * @param clipY the top edge of the clip in millipoints
539      * @param clipW the clip width in millipoints
540      * @param clipH the clip height in millipoints
541      * @param fill the image to be rendered
542      * @param fs the font state to use when rendering text
543      * in non-bitmapped images.
544      */

545     protected void drawImageClipped(int x, int y,
546                     int clipX, int clipY,
547                     int clipW, int clipH,
548                     FopImage image,
549                     FontState fs) {
550     // XXX: implement this
551
}
552
553     // correct integer roundoff (aml/rlc)
554

555     public void renderImageArea(ImageArea area) {
556
557         int x = currentXPosition + area.getXOffset();
558         int y = currentYPosition;
559         int w = area.getContentWidth();
560         int h = area.getHeight();
561         this.currentYPosition -= h;
562
563         FopImage img = area.getImage();
564
565         if (img == null) {
566             log.error("Error while loading image : area.getImage() is null");
567
568             // correct integer roundoff
569
// graphics.drawRect(x / 1000, pageHeight - y / 1000,
570
// w / 1000, h / 1000);
571
addRect(x, y, w, h, true); // use helper function
572

573
574             java.awt.Font JavaDoc f = graphics.getFont();
575             java.awt.Font JavaDoc smallFont = new java.awt.Font JavaDoc(f.getFontName(),
576                                       f.getStyle(), 8);
577
578             graphics.setFont(smallFont);
579
580             // correct integer roundoff // aml/rlc
581
// graphics.drawString("area.getImage() is null", x / 1000,
582
// pageHeight - y / 1000);
583

584             graphics.drawString("area.getImage() is null", (x + 500) / 1000,
585                                 pageHeight - (y + 500) / 1000);
586
587
588             graphics.setFont(f);
589         } else {
590             if (img instanceof SVGImage) {
591                 try {
592                     SVGDocument svg = ((SVGImage)img).getSVGDocument();
593                     renderSVGDocument(svg, (int)x, (int)y);
594                 } catch (FopImageException e) {}
595
596             } else {
597
598                 String JavaDoc urlString = img.getURL();
599                 try {
600                     URL JavaDoc url = new URL JavaDoc(urlString);
601
602                     ImageIcon icon = new ImageIcon(url);
603                     Image JavaDoc image = icon.getImage();
604
605                     // correct integer roundoff aml/rlc
606
// graphics.drawImage(image, x / 1000,
607
// pageHeight - y / 1000, w / 1000, h / 1000,
608
// null);
609

610                     int startx = (x + 500) / 1000;
611                     int starty = pageHeight - ((y + 500) / 1000);
612                     int endx = (x + w + 500) / 1000;
613                     int endy = pageHeight - ((y + h + 500) / 1000);
614
615                     // reverse start and end y because h is positive
616
graphics.drawImage(image, startx, starty, endx - startx,
617                                        starty - endy, null);
618
619                 } catch (MalformedURLException JavaDoc mue) {
620                     // cannot normally occur because, if URL is wrong, constructing FopImage
621
// will already have failed earlier on
622
}
623
624             }
625         }
626
627         this.currentXPosition += area.getContentWidth();
628     }
629
630
631     public void renderWordArea(WordArea area) {
632         char ch;
633         StringBuffer JavaDoc pdf = new StringBuffer JavaDoc();
634
635         String JavaDoc fontname = area.getFontState().getFontName();
636         int size = area.getFontState().getFontSize();
637
638         float red = area.getRed();
639         float green = area.getGreen();
640         float blue = area.getBlue();
641
642         FontMetricsMapper mapper;
643         try {
644             mapper =
645                 (FontMetricsMapper)area.getFontState().getFontInfo().getMetricsFor(fontname);
646         } catch (FOPException iox) {
647             mapper = new FontMetricsMapper("MonoSpaced", java.awt.Font.PLAIN,
648                                            graphics);
649         }
650
651         if ((!fontname.equals(this.currentFontName))
652                 || (size != this.currentFontSize)) {
653             this.currentFontName = fontname;
654             this.currentFontSize = size;
655         }
656
657         if ((red != this.currentRed) || (green != this.currentGreen)
658                 || (blue != this.currentBlue)) {
659             this.currentRed = red;
660             this.currentGreen = green;
661             this.currentBlue = blue;
662         }
663
664         int rx = this.currentXPosition;
665         int bl = this.currentYPosition;
666
667
668         String JavaDoc s = area.getText();
669
670         Color oldColor = graphics.getColor();
671         java.awt.Font JavaDoc oldFont = graphics.getFont();
672         java.awt.Font JavaDoc f = mapper.getFont(size);
673
674         if (saveColor != null) {
675             if (saveColor.getRed() != red || saveColor.getGreen() != green
676                     || saveColor.getBlue() != blue) {
677                 saveColor = new Color(red, green, blue);
678             }
679         } else {
680             saveColor = new Color(red, green, blue);
681         }
682         graphics.setColor(saveColor);
683
684         // Ralph LaChance (May 16, 2002)
685
// AttributedString mechanism removed because of
686
// rendering bug in both jdk 1.3.0_x and 1.4.
687
// see bug parade 4650042 and others
688
//
689
graphics.setFont(f);
690
691         // correct starting location for integer roundoff
692
int newx = (int)(rx + 500) / 1000;
693         int newy = (int)(pageHeight - (bl + 500) / 1000);
694
695         // draw text, corrected for integer roundoff
696
graphics.drawString(s, newx, newy);
697
698         FontMetrics fm = graphics.getFontMetrics(f);
699         int tdwidth = (int)fm.getStringBounds(s, graphics).getWidth();
700
701         // text decorations
702
renderTextDecoration(rx, bl, tdwidth, f, " ",
703                 area.getUnderlined(),
704                 area.getOverlined(),
705                 area.getLineThrough());
706
707         // remember last font and color for possible inline spaces
708
// (especially for text decorations)
709
this.lastFont = graphics.getFont();
710         this.lastColor = graphics.getColor();
711
712         graphics.setFont(oldFont);
713         graphics.setColor(oldColor);
714
715         this.currentXPosition += area.getContentWidth();
716     }
717
718
719     public void renderInlineSpace(InlineSpace space) {
720         if (space.getUnderlined() || space.getOverlined() || space.getLineThrough()) {
721             int rx = this.currentXPosition;
722             int bl = this.currentYPosition;
723
724             java.awt.Font JavaDoc oldFont = graphics.getFont();
725             if (this.lastFont != null) {
726                 graphics.setFont(this.lastFont);
727             }
728             Color oldColor = graphics.getColor();
729             if (this.lastColor != null) {
730                 graphics.setColor(this.lastColor);
731             }
732
733             int width = (int)(space.getSize() + 500) / 1000;
734             renderTextDecoration(rx, bl, width, graphics.getFont(), " ",
735                     space.getUnderlined(),
736                     space.getOverlined(),
737                     space.getLineThrough());
738
739             graphics.setFont(oldFont);
740             graphics.setColor(oldColor);
741         }
742
743         this.currentXPosition += space.getSize();
744     }
745
746
747     protected void renderTextDecoration(int x, int bl, int width,
748                     java.awt.Font JavaDoc font, String JavaDoc text,
749                     boolean underline,
750                     boolean overline,
751                     boolean linethrough) {
752         if (!(underline || overline || linethrough)) return;
753         int newx = (int)(x + 500) / 1000;
754         int newy = (int)(pageHeight - (bl + 500) / 1000);
755
756         // text decorations
757
FontMetrics fm = graphics.getFontMetrics(font);
758         LineMetrics lm = fm.getLineMetrics(text, graphics);
759
760         int ulthick = (int)lm.getUnderlineThickness();
761         if (ulthick < 1)
762             ulthick = 1; // don't allow it to disappear
763
if (underline) {
764             // nothing in awt specifies underline location,
765
// descent/2 seems to match my word processor
766
int deltay = fm.getDescent() / 2;
767             graphics.fillRect(newx, newy + deltay, width, ulthick);
768         }
769         if (overline) {
770             // todo: maybe improve positioning of overline
771
int deltay = -(int)(lm.getAscent() * 0.8);
772             graphics.fillRect(newx, newy + deltay, width, ulthick);
773         }
774         if (linethrough) {
775             int ltthick = (int)lm.getStrikethroughThickness();
776             if (ltthick < 1)
777                 ltthick = 1; // don't allow it to disappear
778
int deltay = (int)lm.getStrikethroughOffset();
779             graphics.fillRect(newx, newy + deltay, width, ltthick);
780         }
781     }
782
783
784     /**
785      * render leader area into AWT
786      *
787      * @param area area to render
788      */

789
790     // call to addRect corrected by aml/rlc
791

792     public void renderLeaderArea(LeaderArea area) {
793
794         int rx = this.currentXPosition;
795         int ry = this.currentYPosition;
796         int w = area.getLeaderLength();
797         int h = area.getHeight();
798         int th = area.getRuleThickness();
799         int st = area.getRuleStyle(); // not used at the moment
800
float r = area.getRed();
801         float g = area.getGreen();
802         float b = area.getBlue();
803         Color oldColor = graphics.getColor();
804
805         graphics.setColor(new Color(r, g, b));
806
807         // use helper function to correct integer roundoff - aml/rlc
808
// graphics.fillRect((int)(rx / 1000f),
809
// (int)(pageHeight - ry / 1000f), (int)(w / 1000f),
810
// (int)(th / 1000f));
811

812         addRect(rx, ry, w, -th, false); // NB addRect expects negative height
813

814         graphics.setColor(oldColor);
815         this.currentXPosition += area.getContentWidth();
816     }
817
818     public void renderSVGArea(SVGArea area) {
819
820         int x = this.currentXPosition;
821         int y = this.currentYPosition;
822         int w = area.getContentWidth();
823         int h = area.getHeight();
824
825         Document JavaDoc doc = area.getSVGDocument();
826         renderSVGDocument(doc, x, y);
827         this.currentXPosition += area.getContentWidth();
828     }
829
830     protected void renderSVGDocument(Document JavaDoc doc, int x, int y) {
831         MUserAgent userAgent = new MUserAgent(new AffineTransform());
832         userAgent.setLogger(log);
833
834         GVTBuilder builder = new GVTBuilder();
835         BridgeContext ctx = new BridgeContext(userAgent);
836         GraphicsNode root;
837         try {
838             root = builder.build(ctx, doc);
839         } catch (Exception JavaDoc e) {
840             log.error("svg graphic could not be built: "
841                                    + e.getMessage(), e);
842             return;
843         }
844         float w = (float)ctx.getDocumentSize().getWidth() * 1000f;
845         float h = (float)ctx.getDocumentSize().getHeight() * 1000f;
846
847         // correct integer roundoff aml/rlc
848
// graphics.translate(x / 1000f, pageHeight - y / 1000f);
849
graphics.translate((x + 500) / 1000, pageHeight - (y + 500) / 1000);
850
851         SVGSVGElement svg = ((SVGDocument)doc).getRootElement();
852         AffineTransform at = ViewBox.getPreserveAspectRatioTransform(svg, w / 1000f, h / 1000f);
853         AffineTransform inverse = null;
854         try {
855             inverse = at.createInverse();
856         } catch(NoninvertibleTransformException e) {
857         }
858         if(!at.isIdentity()) {
859             graphics.transform(at);
860         }
861
862         try {
863             root.paint(graphics);
864         } catch (Exception JavaDoc e) {
865             e.printStackTrace();
866         }
867
868         if(inverse != null && !inverse.isIdentity()) {
869             graphics.transform(inverse);
870         }
871         // correct integer roundoff aml/rlc
872
// graphics.translate(-x / 1000f, y / 1000f - pageHeight);
873
graphics.translate(-(x + 500) / 1000, (y + 500) / 1000 - pageHeight);
874
875     }
876
877     public void setProducer(String JavaDoc producer) {
878         // defined in Renderer Interface
879
}
880
881     public int print(Graphics g, PageFormat pageFormat,
882                      int pageIndex) throws PrinterException {
883         if (pageIndex >= pageList.size())
884             return NO_SUCH_PAGE;
885
886         Graphics2D oldGraphics = graphics;
887         int oldPageNumber = pageNumber;
888
889         graphics = (Graphics2D)g;
890         
891         // Nov 18, 2002 - [aml/rlc] eliminates layout problems at various scaling
892

893         graphics.setRenderingHint (RenderingHints.KEY_FRACTIONALMETRICS,
894                                    RenderingHints.VALUE_FRACTIONALMETRICS_ON);
895
896         Page aPage = (Page)pageList.get(pageIndex);
897         renderPage(aPage);
898         graphics = oldGraphics;
899
900         return PAGE_EXISTS;
901     }
902
903     public int getNumberOfPages() {
904         return pageList.size();
905     }
906
907     public PageFormat getPageFormat(int pageIndex)
908     throws IndexOutOfBoundsException JavaDoc {
909         if (pageIndex >= pageList.size())
910             return null;
911
912         Page page = (Page)pageList.get(pageIndex);
913         PageFormat pageFormat = new PageFormat();
914         Paper paper = new Paper();
915
916         double width = page.getWidth();
917         double height = page.getHeight();
918
919         // if the width is greater than the height assume lanscape mode
920
// and swap the width and height values in the paper format
921
if (width > height) {
922             paper.setImageableArea(0, 0, height / 1000d, width / 1000d);
923             paper.setSize(height / 1000d, width / 1000d);
924             pageFormat.setOrientation(PageFormat.LANDSCAPE);
925         } else {
926             paper.setImageableArea(0, 0, width / 1000d, height / 1000d);
927             paper.setSize(width / 1000d, height / 1000d);
928             pageFormat.setOrientation(PageFormat.PORTRAIT);
929         }
930         pageFormat.setPaper(paper);
931         return pageFormat;
932     }
933
934     public Printable getPrintable(int pageIndex)
935     throws IndexOutOfBoundsException JavaDoc {
936         return this;
937     }
938
939     public void setProgressListener(ProgressListener l) {
940         progressListener = l;
941     }
942
943     public static Color colorType2Color(ColorType ct) {
944         if (ct == null) {
945             return null;
946         }
947         return new Color(ct.red(), ct.green(), ct.blue());
948     }
949
950
951
952     /**
953      * Draws an image.
954      * TODO: protect other image formats (JIMI)
955      */

956     /*
957      * public void renderImage(String href, float x, float y, float width,
958      * float height, Vector transform) {
959      * // What is with transformations?
960      * try {
961      * URL url = new URL(href);
962      * ImageIcon imageIcon = new ImageIcon(url);
963      * AffineTransform fullTransform = new AffineTransform();
964      * AffineTransform aTransform;
965      * transform = (transform == null) ? new Vector() : transform;
966      * for (int i = 0; i < transform.size(); i++) {
967      * org.w3c.dom.svg.SVGTransform t =
968      * (org.w3c.dom.svg.SVGTransform)
969      * transform.get(i);
970      * SVGMatrix matrix = t.getMatrix();
971      * aTransform = new AffineTransform(matrix.getA(),
972      * matrix.getB(), matrix.getC(), matrix.getD(),
973      * matrix.getE(), matrix.getF());
974      * fullTransform.concatenate(aTransform);
975      * }
976      * BufferedImage bi = new BufferedImage((int) width, (int) height,
977      * BufferedImage.TYPE_INT_RGB);
978      * Graphics2D g2d = bi.createGraphics();
979      * BufferedImageOp bop = new AffineTransformOp(fullTransform,
980      * AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
981      * g2d.drawImage(imageIcon.getImage(), 0, 0, (int) width,
982      * (int) height, imageIcon.getImageObserver());
983      * graphics.drawImage(bi, bop, (int) x, (int) y);
984      * } catch (Exception ex) {
985      * log.error("AWTRenderer: renderImage(): " +
986      * ex.getMessage(), ex);
987      * }
988      * }
989      */

990
991     public void renderForeignObjectArea(ForeignObjectArea area) {
992         area.getObject().render(this);
993     }
994
995
996     protected class MUserAgent extends org.apache.fop.svg.SVGUserAgent {
997
998         /**
999          * Creates a new SVGUserAgent.
1000         */

1001        protected MUserAgent(AffineTransform at) {
1002            super(at);
1003        }
1004
1005        /**
1006         * Opens a link in a new component.
1007         * @param doc The current document.
1008         * @param uri The document URI.
1009         */

1010        public void openLink(SVGAElement elt) {
1011            // application.openLink(uri);
1012
}
1013
1014
1015        public Point getClientAreaLocationOnScreen() {
1016            return new Point(0, 0);
1017        }
1018
1019        public void setSVGCursor(java.awt.Cursor JavaDoc cursor) {}
1020
1021
1022        public Dimension2D getViewportSize() {
1023            return new Dimension(100, 100);
1024        }
1025
1026        public EventDispatcher getEventDispatcher() {
1027            return null;
1028        }
1029    }
1030
1031    public void startRenderer(OutputStream outputStream)
1032    throws IOException {}
1033
1034
1035    public void stopRenderer(OutputStream outputStream)
1036    throws IOException {
1037        render(0);
1038    }
1039
1040}
1041
Popular Tags