diff options
author | Jeremias Maerki <jeremias@apache.org> | 2005-06-09 08:49:27 +0000 |
---|---|---|
committer | Jeremias Maerki <jeremias@apache.org> | 2005-06-09 08:49:27 +0000 |
commit | 4aa0eca9779c3baf8ed3a21d6fd9e06fa2d71af9 (patch) | |
tree | e573b7bc321d90ea2d40719ec0e855557c56180e /src/java/org/apache/fop/render/awt | |
parent | dd08f131b250a44f7b900b895deadf70981114fa (diff) | |
download | xmlgraphics-fop-4aa0eca9779c3baf8ed3a21d6fd9e06fa2d71af9.tar.gz xmlgraphics-fop-4aa0eca9779c3baf8ed3a21d6fd9e06fa2d71af9.zip |
Bugzilla: #33760
Resurrected Java2D/AWT Renderer (including bitmap output to PNG and TIFF using the Batik codecs and print capability).
Submitted by: Renaud Richardet <renaud.richardet.at.gmail.com>
Changes on the original patch:
- PageViewport: isResolved() caused a NPE which I fixed.
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@198725 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/java/org/apache/fop/render/awt')
11 files changed, 343 insertions, 2376 deletions
diff --git a/src/java/org/apache/fop/render/awt/AWTFontMetrics.java b/src/java/org/apache/fop/render/awt/AWTFontMetrics.java deleted file mode 100644 index fdfd8b826..000000000 --- a/src/java/org/apache/fop/render/awt/AWTFontMetrics.java +++ /dev/null @@ -1,300 +0,0 @@ -/* - * Copyright 1999-2004 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.render.awt; - -// Java -import java.awt.Font; -import java.awt.Graphics2D; -import java.awt.geom.Rectangle2D; -import java.awt.FontMetrics; -import java.awt.font.TextLayout; - -/** - * This is a FontMetrics to be used for AWT rendering. - * It instanciates a font, depening on family and style - * values. The java.awt.FontMetrics for this font is then - * created to be used for the actual measurement. - * Since layout is word by word and since it is expected that - * two subsequent words often share the same style, the - * Font and FontMetrics is buffered and only changed if needed. - * <p> - * Since FontState and FontInfo multiply all factors by - * size, we assume a "standard" font of FONT_SIZE. - */ -public class AWTFontMetrics { - - /** - * Font size standard used for metric measurements - */ - public static final int FONT_SIZE = 1; - - /** - * This factor multiplies the calculated values to scale - * to FOP internal measurements - */ - public static final int FONT_FACTOR = (1000 * 1000) / FONT_SIZE; - - /** - * The width of all 256 character, if requested - */ - private int width[] = null; - - /** - * The typical height of a small cap latter - */ - private int xHeight = 0; - - /** - * Buffered font. - * f1 is bufferd for metric measurements during layout. - * fSized is buffered for display purposes - */ - private Font f1 = null; // , fSized = null; - - /** - * The family type of the font last used - */ - private String family = ""; - - /** - * The style of the font last used - */ - private int style = 0; - - /** - * The size of the font last used - */ - private float size = 0; - - /** - * The FontMetrics object used to calculate character width etc. - */ - private FontMetrics fmt = null; - - /** - * Temp graphics object needed to get the font metrics - */ - private Graphics2D graphics; - - /** - * Constructs a new Font-metrics. - * @param graphics a temp graphics object - this is needed so - * that we can get an instance of java.awt.FontMetrics - */ - public AWTFontMetrics(Graphics2D graphics) { - this.graphics = graphics; - } - - /** - * Determines the font ascent of the Font described by this - * FontMetrics object - * @param family font family (java name) to use - * @param style font style (java def.) to use - * @param size font size - * @return ascent in milliponts - */ - public int getAscender(String family, int style, int size) { - setFont(family, style, size); - // return (int)(FONT_FACTOR * fmt.getAscent()); - - // workaround for sun bug on FontMetrics.getAscent() - // http://developer.java.sun.com/developer/bugParade/bugs/4399887.html - /* - * Bug 4399887 has status Closed, not a bug. The comments on the bug - * are: - * The submitter is incorrectly assuming that the string he has used - * is displaying characters which represent those with the maximum - * ascent in the font. If (for example) the unicode character - * \u00c1 which is the A-acute character used in many European - * languages is placed in the bodu of the "Wrong" string it can be - * seen that the JDK is exactly correct in its determination of the - * ascent of the font. - * If the bounds of a particular string are interesting then the - * Rectangle FontMetrics.getStringBounds(..) method can be called. - * The y value of the rectangle is the offset from the origin - * (baseline) apparently needed by the sample test program - * - * xxxxx@xxxxx 2001-05-15 - */ - int realAscent = fmt.getAscent() - - (fmt.getDescent() + fmt.getLeading()); - return FONT_FACTOR * realAscent; - } - - - /** - * The size of a capital letter measured from the font's baseline - * @param family font family - * @param style font style - * @param size font size - * @return capital height in millipoints - */ - public int getCapHeight(String family, int style, int size) { - // currently just gets Ascent value but maybe should use - // getMaxAcent() at some stage - return getAscender(family, style, size); - } - - /** - * Determines the font descent of the Font described by this - * FontMetrics object - * @param family font family (jave name) to use - * @param style font style (jave def.) to use - * @param size font size - * @return descent in milliponts - */ - public int getDescender(String family, int style, int size) { - setFont(family, style, size); - return (-1 * FONT_FACTOR * fmt.getDescent()); - } - - /** - * Determines the typical font height of a small cap letter - * FontMetrics object - * @param family font family (jave name) to use - * @param style font style (jave def.) to use - * @param size font size - * @return font height in milliponts - */ - public int getXHeight(String family, int style, int size) { - setFont(family, style, size); - return (int)(FONT_FACTOR * xHeight); - } - - /** - * Returns width (in 1/1000ths of point size) of character at - * code point i - * @param i the character for which to get the width - * @param family font family (jave name) to use - * @param style font style (jave def.) to use - * @param size font size - * @return character width in millipoints - */ - public int width(int i, String family, int style, int size) { - int w; - setFont(family, style, size); - // the output seems to look a little better if the - // space is rendered larger than given by - // the FontMetrics object - if (i <= 32) { - w = (int)(1.4 * fmt.charWidth(i) * FONT_FACTOR); - } else { - w = (int)(fmt.charWidth(i) * FONT_FACTOR); - } - return w; - } - - /** - * Return widths (in 1/1000ths of point size) of all - * characters - * @param family font family (jave name) to use - * @param style font style (jave def.) to use - * @param size font size - * @return array of character widths in millipoints - */ - public int[] getWidths(String family, int style, int size) { - int i; - - if (width == null) { - width = new int[256]; - } - setFont(family, style, size); - for (i = 0; i < 256; i++) { - width[i] = FONT_FACTOR * fmt.charWidth(i); - } - return width; - } - - /** - * Checks whether the font for which values are - * requested is the one used immediately before or - * whether it is a new one - * @param family font family (jave name) to use - * @param style font style (jave def.) to use - * @param size font size - * @return true if the font was changed, false otherwise - */ - private boolean setFont(String family, int style, int size) { - boolean changed = false; - Rectangle2D rect; - TextLayout layout; - int s = (int)(size / 1000f); - - if (f1 == null) { - f1 = new Font(family, style, s); - fmt = graphics.getFontMetrics(f1); - changed = true; - } else { - if ((this.style != style) || !this.family.equals(family) - || this.size != s) { - if (family.equals(this.family)) { - f1 = f1.deriveFont(style, (float)s); - } else { - f1 = new Font(family, style, s); - } - fmt = graphics.getFontMetrics(f1); - changed = true; - } - // else the font is unchanged from last time - } - if (changed) { - layout = new TextLayout("m", f1, graphics.getFontRenderContext()); - rect = layout.getBounds(); - xHeight = (int)rect.getHeight(); - } - // save the family and style for later comparison - this.family = family; - this.style = style; - this.size = s; - return changed; - } - - - /** - * Returns a java.awt.Font instance for the desired - * family, style and size type. - * This is here, so that the font-mapping - * of FOP-defined fonts to java-fonts can be done - * in one place and does not need to occur in - * AWTFontRenderer. - * @param family font family (jave name) to use - * @param style font style (jave def.) to use - * @param size font size - * @return font with the desired characeristics. - */ - public java.awt.Font getFont(String family, int style, int size) { - setFont(family, style, size); - return f1; - /* - * if( setFont(family,style, size) ) fSized = null; - * if( fSized == null || this.size != size ) { - * fSized = f1.deriveFont( size / 1000f ); - * } - * this.size = size; - * return fSized; - */ - } - -} - - - - - - diff --git a/src/java/org/apache/fop/render/awt/AWTGraphicsState.java b/src/java/org/apache/fop/render/awt/AWTGraphicsState.java deleted file mode 100644 index 7dae50b78..000000000 --- a/src/java/org/apache/fop/render/awt/AWTGraphicsState.java +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright 2005 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.render.awt; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.Paint; -import java.awt.Shape; -import java.awt.geom.AffineTransform; -import java.awt.geom.Area; -import java.awt.geom.GeneralPath; -import java.util.List; - -import org.apache.fop.datatypes.ColorType; -import org.apache.fop.fo.Constants; -import org.apache.fop.fonts.FontInfo; - -/** - * Keeps information about the current state of the Graphics2D currentGraphics. - * It is also used as a stack to hold a graphics context. - * <p> - * The graphics context is updated with the updateXXX() methods. - */ -public class AWTGraphicsState implements Constants, RendererState { - - /** Holds the datas of the current state */ - private Graphics2D currentGraphics; - - private BasicStroke currentStroke; - - private float currentStrokeWidth; - - private int currentStrokeStyle; - - private List stateStack = new java.util.ArrayList(); - - /** Font configuration, passed from AWTRenderer */ - private FontInfo fontInfo; - - /** State for storing graphics state. */ - public AWTGraphicsState(Graphics2D graphics, FontInfo fontInfo) { - this.fontInfo = fontInfo; - this.currentGraphics = graphics; - } - - /** - * @return the currently valid state - */ - public Graphics2D getGraph() { - return currentGraphics; - } - - /** @see org.apache.fop.render.awt.RendererState#push() */ - public void push() { - Graphics2D tmpGraphics = (Graphics2D) currentGraphics.create(); - stateStack.add(tmpGraphics); - } - - /** @see org.apache.fop.render.awt.RendererState#pop() */ - public Graphics2D pop() { - if (getStackLevel() > 0) { - Graphics2D popped = (Graphics2D) stateStack.remove(stateStack - .size() - 1); - - currentGraphics = popped; - return popped; - } else { - return null; - } - } - - /** @see org.apache.fop.render.awt.RendererState#getStackLevel() */ - public int getStackLevel() { - return stateStack.size(); - } - - /** - * Restore the state to a particular level. this can be used to restore to a - * known level without making multiple pop calls. - * - * @param stack the level to restore to - */ - /* - * public void restoreLevel(int stack) { int pos = stack; while - * (stateStack.size() > pos + 1) { stateStack.remove(stateStack.size() - 1); } - * if (stateStack.size() > pos) { pop(); } } - */ - - /** - * Set the current background color. Check if the background color will - * change and then set the new color. - * - * @param col the new color as a java.awt.Color - * @return true if the background color has changed - */ - public boolean updateColor(Color col) { - if (!col.equals(getGraph().getColor())) { - getGraph().setColor(col); - return true; - } else { - return false; - } - } - - /** - * Converts a ColorType to a java.awt.Color (sRGB). - * - * @param col the color as a org.apache.fop.datatypes.ColorType - * @return the converted color as a java.awt.Color - */ - public Color toColor(ColorType col) { - return new Color(col.getRed(), col.getGreen(), col.getBlue()); - } - - /** - * @see org.apache.fop.render.awt.RendererState#updateColor(org.apache.fop.datatypes.ColorType, - * boolean, java.lang.StringBuffer) - */ - public boolean updateColor(ColorType col, boolean fill, StringBuffer pdf) { - if (col == null) { - return false; - } - Color newCol = toColor(col); - return updateColor(newCol); - } - - /** - * Update the current Color - * @param col the ColorType - */ - public void updateColor(ColorType col) { - if (col == null) { - return; - } - Color newCol = toColor(col); - updateColor(newCol); - } - - /** - * @return the current java.awt.Color - */ - public java.awt.Color getColor() { - return currentGraphics.getColor(); - } - - /** - * @see org.apache.fop.render.awt.RendererState#updateFont(java.lang.String, - * int, java.lang.StringBuffer) - */ - public boolean updateFont(String name, int size, StringBuffer pdf) { - - boolean updateName = (!name.equals(getGraph().getFont().getFontName())); - boolean updateSize = (size != (getGraph().getFont().getSize())); - - if (updateName || updateSize) { - // the font name and/or the font size have changed - FontMetricsMapper mapper = (FontMetricsMapper) fontInfo - .getMetricsFor(name); - java.awt.Font font = mapper.getFont(size); - - currentGraphics.setFont(font); - return true; - } else { - return false; - } - } - - /** - * @return the current java.awt.Font - */ - public java.awt.Font getFont() { - return currentGraphics.getFont(); - } - - /** - * @see org.apache.fop.render.awt.RendererState#updateStroke(float, int) - */ - public boolean updateStroke(float width, int style) { - - boolean update = false; - - // only update if necessary - if ((width != currentStrokeWidth) || (style != currentStrokeStyle)) { - - update = true; - - switch (style) { - case EN_DOTTED: - - currentStroke = new BasicStroke(width, BasicStroke.CAP_BUTT, - BasicStroke.JOIN_BEVEL, 0f, new float[] { 2f }, 0f); - currentGraphics.setStroke(currentStroke); - - currentStrokeWidth = width; - currentStrokeStyle = style; - - break; - - case EN_DASHED: - - currentStroke = new BasicStroke(width, BasicStroke.CAP_BUTT, - BasicStroke.JOIN_BEVEL, 0f, new float[] { 8f, 2f }, 0f); - currentGraphics.setStroke(currentStroke); - - currentStrokeWidth = width; - currentStrokeStyle = style; - - break; - - default: // EN_SOLID: - - currentStroke = new BasicStroke(width); - currentGraphics.setStroke(currentStroke); - - currentStrokeWidth = width; - currentStrokeStyle = style; - - break; - } - } - - return update; - } - - public BasicStroke getStroke() { - return (BasicStroke) currentGraphics.getStroke(); - } - - /** @see org.apache.fop.render.awt.RendererState#updatePaint(java.awt.Paint) */ - public boolean updatePaint(Paint p) { - if (getGraph().getPaint() == null) { - if (p != null) { - getGraph().setPaint(p); - return true; - } - } else if (p.equals(getGraph().getPaint())) { - getGraph().setPaint(p); - return true; - } - return false; - } - - /** @see org.apache.fop.render.awt.RendererState#checkClip(java.awt.Shape) */ - // TODO implement and test - public boolean checkClip(Shape cl) { - if (getGraph().getClip() == null) { - if (cl != null) { - return true; - } - } else if (cl.equals(getGraph().getClip())) { - return true; - } - // TODO check for clips that are larger than the current - return false; - } - - /** - * @see org.apache.fop.render.awt.RendererState#updateClip(java.awt.Shape) - */ - public boolean updateClip(Shape cl) { - if (getGraph().getClip() != null) { - Area newClip = new Area(getGraph().getClip()); - newClip.intersect(new Area(cl)); - getGraph().setClip(new GeneralPath(newClip)); - } else { - getGraph().setClip(cl); - } - return true; // TODO only update if necessary - } - - /** - * @see org.apache.fop.render.awt.RendererState#checkTransform(java.awt.geom.AffineTransform) - */ - public boolean checkTransform(AffineTransform tf) { - return !tf.equals(getGraph().getTransform()); - } - - /** - * @see org.apache.fop.render.awt.RendererState#setTransform(java.awt.geom.AffineTransform) - */ - public void setTransform(AffineTransform tf) { - getGraph().setTransform(tf); - } - - /** - * @see org.apache.fop.render.awt.RendererState#transform(java.awt.geom.AffineTransform) - */ - public void transform(AffineTransform tf) { - getGraph().transform(tf); - } - - /** - * @see org.apache.fop.render.awt.RendererState#getTransform() - */ - public AffineTransform getTransform() { - /* - * AffineTransform tf; AffineTransform at = new AffineTransform(); for - * (Iterator iter = stateStack.iterator(); iter.hasNext();) { Data d = - * (Data) iter.next(); tf = d.transform; at.concatenate(tf); } - * at.concatenate(getCurrentGraphics().transform); - * - * return at; - */ - return getGraph().getTransform(); - } - - /** a verbose description of the current state */ - public String toString() { - String s = "AWTGraphicsState " + currentGraphics.toString() - + ", Stroke (width: " + currentStrokeWidth + " style: " - + currentStrokeStyle + "), " + getTransform() - + ", StackLevel: " + getStackLevel(); - return s; - } -} diff --git a/src/java/org/apache/fop/render/awt/AWTPrintRenderer.java b/src/java/org/apache/fop/render/awt/AWTPrintRenderer.java deleted file mode 100644 index 5b057959a..000000000 --- a/src/java/org/apache/fop/render/awt/AWTPrintRenderer.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 1999-2004 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.render.awt; - -import java.awt.print.PrinterException; -import java.awt.print.PrinterJob; -import java.io.IOException; -import java.util.Vector; - -public class AWTPrintRenderer extends AWTRenderer { - - private static final int EVEN_AND_ALL = 0; - private static final int EVEN = 1; - private static final int ODD = 2; - - private int startNumber; - private int endNumber; - private int mode = EVEN_AND_ALL; - private int copies = 1; - private PrinterJob printerJob; - - public AWTPrintRenderer() { - initialize(); - } - - private void initialize() throws IllegalArgumentException { - // read from command-line options - copies = getIntProperty("copies", 1); - startNumber = getIntProperty("start", 1) - 1; - endNumber = getIntProperty("end", -1); - String str = System.getProperty("even"); - if (str != null) { - mode = Boolean.valueOf(str).booleanValue() ? EVEN : ODD; - } - - printerJob = PrinterJob.getPrinterJob(); - printerJob.setJobName("FOP Document"); - printerJob.setCopies(copies); - if (System.getProperty("dialog") != null) { - if (!printerJob.printDialog()) { - throw new IllegalArgumentException("Printing cancelled by operator"); - } - } - printerJob.setPageable(this); - } - - public void stopRenderer() throws IOException { - super.stopRenderer(); - - if (endNumber == -1) { - endNumber = getNumberOfPages(); - } - - Vector numbers = getInvalidPageNumbers(); - for (int i = numbers.size() - 1; i > -1; i--) { - // removePage(Integer.parseInt((String)numbers.elementAt(i))); - } - - try { - printerJob.print(); - } catch (PrinterException e) { - e.printStackTrace(); - throw new IOException("Unable to print: " - + e.getClass().getName() - + ": " + e.getMessage()); - } - } - - public static int getIntProperty(String name, int def) { - String propValue = System.getProperty(name); - if (propValue != null) { - try { - return Integer.parseInt(propValue); - } catch (Exception e) { - return def; - } - } else { - return def; - } - } - - private Vector getInvalidPageNumbers() { - Vector vec = new Vector(); - int max = getNumberOfPages(); - boolean isValid; - for (int i = 0; i < max; i++) { - isValid = true; - if (i < startNumber || i > endNumber) { - isValid = false; - } else if (mode != EVEN_AND_ALL) { - if (mode == EVEN && ((i + 1) % 2 != 0)) { - isValid = false; - } else if (mode == ODD && ((i + 1) % 2 != 1)) { - isValid = false; - } - } - - if (!isValid) { - vec.add(i + ""); - } - } - return vec; - } -} // class AWTPrintRenderer - diff --git a/src/java/org/apache/fop/render/awt/AWTRenderer.java b/src/java/org/apache/fop/render/awt/AWTRenderer.java index ecc8e28cf..a771a739f 100644 --- a/src/java/org/apache/fop/render/awt/AWTRenderer.java +++ b/src/java/org/apache/fop/render/awt/AWTRenderer.java @@ -26,145 +26,46 @@ package org.apache.fop.render.awt; */ // Java -import java.awt.Color; -import java.awt.Component; -import java.awt.Container; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; -import java.awt.RenderingHints; import java.awt.Toolkit; -import java.awt.color.ColorSpace; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; -import java.awt.geom.AffineTransform; -import java.awt.geom.Line2D; -import java.awt.geom.NoninvertibleTransformException; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; -import java.awt.image.ColorModel; -import java.awt.image.ComponentColorModel; -import java.awt.image.DataBuffer; -import java.awt.image.DataBufferByte; -import java.awt.image.MemoryImageSource; -import java.awt.image.PixelInterleavedSampleModel; -import java.awt.image.Raster; -import java.awt.image.SampleModel; -import java.awt.image.WritableRaster; import java.awt.print.PageFormat; import java.awt.print.Pageable; +import java.awt.print.Paper; import java.awt.print.Printable; +import java.awt.print.PrinterException; import java.io.IOException; -import java.io.OutputStream; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Vector; -import org.apache.batik.bridge.BridgeContext; -import org.apache.batik.bridge.GVTBuilder; -import org.apache.batik.bridge.ViewBox; -import org.apache.batik.gvt.GraphicsNode; import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.area.Area; -import org.apache.fop.area.Block; -import org.apache.fop.area.BlockViewport; -import org.apache.fop.area.CTM; -import org.apache.fop.area.Page; import org.apache.fop.area.PageViewport; -import org.apache.fop.area.Trait; -import org.apache.fop.area.inline.Character; -import org.apache.fop.area.inline.ForeignObject; -import org.apache.fop.area.inline.Image; -import org.apache.fop.area.inline.InlineArea; -import org.apache.fop.area.inline.Leader; -import org.apache.fop.area.inline.TextArea; import org.apache.fop.datatypes.ColorType; -import org.apache.fop.fo.Constants; import org.apache.fop.fo.properties.ColorTypeProperty; -import org.apache.fop.fonts.Font; -import org.apache.fop.fonts.FontInfo; -import org.apache.fop.fonts.FontMetrics; -import org.apache.fop.image.FopImage; -import org.apache.fop.image.ImageFactory; -import org.apache.fop.image.XMLImage; -import org.apache.fop.render.AbstractRenderer; -import org.apache.fop.render.RendererContext; import org.apache.fop.render.awt.viewer.PreviewDialog; import org.apache.fop.render.awt.viewer.Translator; -import org.apache.fop.render.pdf.CTMHelper; -import org.apache.fop.svg.SVGUserAgent; -import org.apache.fop.traits.BorderProps; -import org.w3c.dom.Document; -import org.w3c.dom.svg.SVGDocument; -import org.w3c.dom.svg.SVGSVGElement; +import org.apache.fop.render.java2d.Java2DRenderer; /** - * The <code>Java2DRenderer</code> class provides the abstract technical - * foundation for all rendering with the Java2D API. Renderers like - * <code>AWTRenderer</code> subclass it and provide the concrete output paths. - * <p> - * A lot of the logic is performed by <code>AbstractRenderer</code>. The - * class-variables <code>currentIPPosition</code> and - * <code>currentBPPosition</code> hold the position of the currently rendered - * area. - * <p> - * <code>AWTGraphicsState state</code> holds the <code>Graphics2D</code>, - * which is used along the whole rendering. <code>state</code> also acts as a - * stack (<code>state.push()</code> and <code>state.pop()</code>). - * <p> - * The rendering process is basically always the same: - * <p> - * <code>void renderXXXXX(Area area) { - * //calculate the currentPosition - * state.updateFont(name, size, null); - * state.updateColor(ct, false, null); - * state.getGraph.draw(new Shape(args)); - * }</code> - * + * The AWTRender outputs the pages generated by the layout engine to a Swing + * window. This Swing window serves as default viewer for the -awt switch and as + * an example of how to embed the AWTRenderer into an AWT/Swing application. */ -public class AWTRenderer extends AbstractRenderer implements Printable, - Pageable { +public class AWTRenderer extends Java2DRenderer implements Pageable, Printable { /** The MIME type for AWT-Rendering */ - public static final String MIME_TYPE = "application/awt"; - - protected double scaleFactor = 100.0; - - protected int pageNumber = 0; - - private int pageWidth = 0; - - private int pageHeight = 0; - - private Vector pageViewportList = new java.util.Vector(); - - private Vector pageList = new java.util.Vector(); - - private Vector bufferedImageList = new java.util.Vector(); - - protected BufferedImage currentPageImage = null; - - protected boolean antialiasing = true; - - protected boolean qualityRendering = true; - - /** The current state, holds a Graphics2D and its context */ - protected AWTGraphicsState state; - - /** a Line2D.Float used to draw text decorations and leaders */ - protected Line2D.Float line = new Line2D.Float(); - - /** Font configuration */ - protected FontInfo fontInfo; + public static final String MIME_TYPE = "application/X-awt"; /** The resource bundle used for AWT messages. */ protected Translator translator = null; - private Map fontNames = new java.util.Hashtable(); - - private Map fontStyles = new java.util.Hashtable(); + /** flag for debugging */ + public boolean debug; /** * The preview dialog frame used for display of the documents. Also used as @@ -172,95 +73,34 @@ public class AWTRenderer extends AbstractRenderer implements Printable, */ protected PreviewDialog frame; - /** Flag for visual-debugging */ - public boolean debug = false; - public AWTRenderer() { translator = new Translator(); } public void setUserAgent(FOUserAgent foUserAgent) { super.setUserAgent(foUserAgent); - userAgent.setRendererOverride(this); // for document regeneration createPreviewDialog(); } - public FOUserAgent getUserAgent() { - return userAgent; - } - - /** - * @see org.apache.fop.render.Renderer - */ - public boolean supportsOutOfOrder() { - return false; - } - - public Translator getTranslator() { - return translator; - } - - /** @see org.apache.fop.render.AbstractRenderer */ - public String getMimeType() { - return MIME_TYPE; - } - - public void setupFontInfo(FontInfo inFontInfo) { - // create a temp Image to test font metrics on - fontInfo = inFontInfo; - BufferedImage fontImage = new BufferedImage(100, 100, - BufferedImage.TYPE_INT_RGB); - FontSetup.setup(fontInfo, fontImage.createGraphics()); - } - - public int getPageNumber() { - return pageNumber; - } - - public void setPageNumber(int aValue) { - pageNumber = aValue; - } + public void renderPage(PageViewport pageViewport) throws IOException, + FOPException { - public void setScaleFactor(double newScaleFactor) { - scaleFactor = newScaleFactor; - } + super.renderPage(pageViewport); - public double getScaleFactor() { - return scaleFactor; - } + // Shows the page if it's the first one + if (getCurrentPageNumber() == 1) { + frame.showPage(); + } + frame.setInfo(); - public void startRenderer(OutputStream out) throws IOException { - // empty pageViewportList, in case of a reload from PreviewDialog - pageViewportList.removeAllElements(); - pageList.removeAllElements(); - bufferedImageList.removeAllElements(); - System.out.println("\nRegion Types: 0-Before/Top, 1-Start/Left," - + " 2-Body, 3-End/Right, 4-After/Bottom"); } public void stopRenderer() throws IOException { + super.stopRenderer(); frame.setStatus(translator.getString("Status.Show")); - frame.showPage(); - // TODO set all vars to null for gc - } - - // Printable Interface - public PageFormat getPageFormat(int pos) { - return null; - } - - public Printable getPrintable(int pos) { - return null; - } - - public int getNumberOfPages() { - return pageViewportList.size(); - } - - public int print(Graphics g, PageFormat format, int pos) { - return 0; } + /** Creates and initialize the AWT Viewer main window */ private PreviewDialog createPreviewDialog() { frame = new PreviewDialog(userAgent); frame.addWindowListener(new WindowAdapter() { @@ -280,320 +120,92 @@ public class AWTRenderer extends AbstractRenderer implements Printable, } frame.setLocation((screenSize.width - frameSize.width) / 2, (screenSize.height - frameSize.height) / 2); - frame.setVisible(true); frame.setStatus(translator.getString("Status.Build.FO.tree")); + frame.setVisible(true); return frame; } /** - * This method override only stores the PageViewport in a vector. No actual - * rendering performed -- this is done by getPageImage(pageNum) instead. - * - * @param pageViewport the <code>PageViewport</code> object supplied by - * the Area Tree - * @see org.apache.fop.render.Renderer - */ - public void renderPage(PageViewport pageViewport) throws IOException, - FOPException { - pageViewportList.add(pageViewport); - pageList.add(pageViewport.getPage().clone()); - bufferedImageList - .add(getPageImage(pageViewport, pageViewport.getPage())); - } - - public BufferedImage getBufferedPageImage(int pageNum) throws FOPException { - return (BufferedImage) bufferedImageList.get(pageNum); - } - - /** - * Generates a desired page from the renderer's page viewport vector. - * - * @param pageNum the 0-based page number to generate - * @return the <code>java.awt.image.BufferedImage</code> corresponding to - * the page - * @throws FOPException in case of an out-of-range page number requested + * @see java.awt.print.Printable#print(java.awt.Graphics, + * java.awt.print.PageFormat, int) */ - public BufferedImage getPageImage(PageViewport pageViewport, Page page) - throws FOPException { - - Rectangle2D bounds = pageViewport.getViewArea(); - pageWidth = (int) Math.round(bounds.getWidth() / 1000f); - pageHeight = (int) Math.round(bounds.getHeight() / 1000f); - - getLogger().info( - "Rendering Page " + pageViewport.getPageNumberString() - + " (pageWidth " + pageWidth + ", pageHeight " - + pageHeight + ")"); - - currentPageImage = new BufferedImage( - (int) ((pageWidth * (int) scaleFactor) / 100), - (int) ((pageHeight * (int) scaleFactor) / 100), - BufferedImage.TYPE_INT_RGB); - - Graphics2D graphics = currentPageImage.createGraphics(); - graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, - RenderingHints.VALUE_FRACTIONALMETRICS_ON); - if (antialiasing) { - graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, - RenderingHints.VALUE_TEXT_ANTIALIAS_ON); - } - if (qualityRendering) { - graphics.setRenderingHint(RenderingHints.KEY_RENDERING, - RenderingHints.VALUE_RENDER_QUALITY); + public int print(Graphics g, PageFormat pageFormat, int pageIndex) + throws PrinterException { + if (pageIndex >= getNumberOfPages()) { + return NO_SUCH_PAGE; } - // transform page based on scale factor supplied - AffineTransform at = graphics.getTransform(); - at.scale(scaleFactor / 100.0, scaleFactor / 100.0); - graphics.setTransform(at); + Graphics2D g2 = (Graphics2D) g; - // draw page frame - graphics.setColor(Color.white); - graphics.fillRect(0, 0, pageWidth, pageHeight); - graphics.setColor(Color.black); - graphics.drawRect(-1, -1, pageWidth + 2, pageHeight + 2); - graphics.drawLine(pageWidth + 2, 0, pageWidth + 2, pageHeight + 2); - graphics.drawLine(pageWidth + 3, 1, pageWidth + 3, pageHeight + 3); - graphics.drawLine(0, pageHeight + 2, pageWidth + 2, pageHeight + 2); - graphics.drawLine(1, pageHeight + 3, pageWidth + 3, pageHeight + 3); - - state = new AWTGraphicsState(graphics, this.fontInfo); + BufferedImage image; + try { + image = getPageImage(pageIndex); + } catch (FOPException e) { + e.printStackTrace(); + return NO_SUCH_PAGE; + } - // reset the current Positions - currentBPPosition = 0; - currentIPPosition = 0; + g2.drawImage(image, null, 0, 0); - // this toggles the rendering of all areas - renderPageAreas(page); - return currentPageImage; + return PAGE_EXISTS; } - /** - * Generates a desired page from the renderer's page viewport vector. - * - * @param pageNum the 0-based page number to generate - * @return the <code>java.awt.image.BufferedImage</code> corresponding to - * the page - * @throws FOPException in case of an out-of-range page number requested - */ - public BufferedImage getPageImage(int pageNum) throws FOPException { - if (pageNum < 0 || pageNum >= pageViewportList.size()) { - throw new FOPException("out-of-range page number (" + pageNum - + ") requested; only " + pageViewportList.size() - + " page(s) available."); - } - PageViewport pageViewport = (PageViewport) pageViewportList - .get(pageNum); - Page page = (Page) pageList.get(pageNum); - return getPageImage(pageViewport, page); - } + /** @see java.awt.print.Pageable#getPageFormat(int) */ + public PageFormat getPageFormat(int pageIndex) + throws IndexOutOfBoundsException { + if (pageIndex >= getNumberOfPages()) + return null; - /** - * @see org.apache.fop.render.AbstractRenderer#startVParea(CTM) - */ - protected void startVParea(CTM ctm) { + PageFormat pageFormat = new PageFormat(); - // push (and save) the current graphics state - state.push(); + Paper paper = new Paper(); + pageFormat.setPaper(paper); - // Set the given CTM in the graphics state - state.setTransform(new AffineTransform(CTMHelper.toPDFArray(ctm))); + Rectangle2D dim = getPageViewport(pageIndex).getViewArea(); + double width = dim.getWidth(); + double height = dim.getHeight(); - // TODO Set clip? + // if the width is greater than the height assume lanscape mode + // and swap the width and height values in the paper format + if (width > height) { + paper.setImageableArea(0, 0, height / 1000d, width / 1000d); + paper.setSize(height / 1000d, width / 1000d); + pageFormat.setOrientation(PageFormat.LANDSCAPE); + } else { + paper.setImageableArea(0, 0, width / 1000d, height / 1000d); + paper.setSize(width / 1000d, height / 1000d); + pageFormat.setOrientation(PageFormat.PORTRAIT); + } + return pageFormat; } - /** - * @see org.apache.fop.render.AbstractRenderer#endVParea() - */ - protected void endVParea() { - state.pop(); + /** @see java.awt.print.Pageable#getPrintable(int) */ + public Printable getPrintable(int pageIndex) + throws IndexOutOfBoundsException { + return this; } - /** - * @see org.apache.fop.render.AbstractRenderer#renderBlockViewport(BlockViewport, - * List) - */ - protected void renderBlockViewport(BlockViewport bv, List children) { - // clip and position viewport if necessary - - // save positions - int saveIP = currentIPPosition; - int saveBP = currentBPPosition; - - CTM ctm = bv.getCTM(); - int borderPaddingStart = bv.getBorderAndPaddingWidthStart(); - int borderPaddingBefore = bv.getBorderAndPaddingWidthBefore(); - float x, y; - x = (float) (bv.getXOffset() + containingIPPosition) / 1000f; - y = (float) (bv.getYOffset() + containingBPPosition) / 1000f; - - if (bv.getPositioning() == Block.ABSOLUTE - || bv.getPositioning() == Block.FIXED) { - // TODO not tested yet - // For FIXED, we need to break out of the current viewports to the - // one established by the page. We save the state stack for - // restoration - // after the block-container has been painted. See below. - List breakOutList = null; - if (bv.getPositioning() == Block.FIXED) { - getLogger().debug("Block.FIXED --> break out"); - breakOutList = new java.util.ArrayList(); - Graphics2D graph; - while (true) { - graph = state.getGraph(); - if (state.pop() == null) { - break; - } - breakOutList.add(0, graph); // Insert because of - // stack-popping - getLogger().debug("Adding to break out list: " + graph); - } - } - - CTM tempctm = new CTM(containingIPPosition, containingBPPosition); - ctm = tempctm.multiply(ctm); - - // This is the content-rect - float width = (float) bv.getIPD() / 1000f; - float height = (float) bv.getBPD() / 1000f; - - // Adjust for spaces (from margin or indirectly by start-indent etc. - Integer spaceStart = (Integer) bv.getTrait(Trait.SPACE_START); - if (spaceStart != null) { - x += spaceStart.floatValue() / 1000; - } - Integer spaceBefore = (Integer) bv.getTrait(Trait.SPACE_BEFORE); - if (spaceBefore != null) { - y += spaceBefore.floatValue() / 1000; - } - - float bpwidth = (borderPaddingStart + bv - .getBorderAndPaddingWidthEnd()) / 1000f; - float bpheight = (borderPaddingBefore + bv - .getBorderAndPaddingWidthAfter()) / 1000f; - - drawBackAndBorders(bv, x, y, width + bpwidth, height + bpheight); - - // Now adjust for border/padding - x += borderPaddingStart / 1000f; - y += borderPaddingBefore / 1000f; - - if (bv.getClip()) { - // saves the graphics state in a stack - state.push(); - - clip(x, y, width, height); - } - - startVParea(ctm); - - renderBlocks(bv, children); - endVParea(); - - if (bv.getClip()) { - // restores the last graphics state from the stack - state.pop(); - } - - // clip if necessary - - if (breakOutList != null) { - getLogger().debug( - "Block.FIXED --> restoring context after break-out"); - Graphics2D graph; - Iterator i = breakOutList.iterator(); - while (i.hasNext()) { - graph = (Graphics2D) i.next(); - getLogger().debug("Restoring: " + graph); - state.push(); - } - } - - currentIPPosition = saveIP; - currentBPPosition = saveBP; - - } else { // orientation = Block.STACK or RELATIVE - - Integer spaceBefore = (Integer) bv.getTrait(Trait.SPACE_BEFORE); - if (spaceBefore != null) { - currentBPPosition += spaceBefore.intValue(); - } - - // borders and background in the old coordinate system - handleBlockTraits(bv); - - CTM tempctm = new CTM(containingIPPosition, currentBPPosition - + containingBPPosition); - ctm = tempctm.multiply(ctm); - - // Now adjust for border/padding - x += borderPaddingStart / 1000f; - y += borderPaddingBefore / 1000f; - - // clip if necessary - if (bv.getClip()) { - // saves the graphics state in a stack - state.push(); - float width = (float) bv.getIPD() / 1000f; - float height = (float) bv.getBPD() / 1000f; - clip(x, y, width, height); - } - - if (ctm != null) { - startVParea(ctm); - } - renderBlocks(bv, children); - if (ctm != null) { - endVParea(); - } - - if (bv.getClip()) { - // restores the last graphics state from the stack - state.pop(); - } - - currentIPPosition = saveIP; - currentBPPosition = saveBP; - - // Adjust BP position (alloc BPD + spaces) - if (spaceBefore != null) { - currentBPPosition += spaceBefore.intValue(); - } - currentBPPosition += (int) (bv.getAllocBPD()); - Integer spaceAfter = (Integer) bv.getTrait(Trait.SPACE_AFTER); - if (spaceAfter != null) { - currentBPPosition += spaceAfter.intValue(); - } - } + /** @see org.apache.fop.render.Renderer */ + public boolean supportsOutOfOrder() { + return true; // TODO true? } - /** - * Clip an area. - */ - protected void clip() { - // TODO via AWTGraphicsState.updateClip(); - // currentStream.add("W\n"); - // currentStream.add("n\n"); + /** @return the Translator for this renderer */ + public Translator getTranslator() { + return translator; } - /** - * Clip an area. write a clipping operation given coordinates in the current - * transform. - * @param x the x coordinate - * @param y the y coordinate - * @param width the width of the area - * @param height the height of the area - */ - protected void clip(float x, float y, float width, float height) { - // TODO via AWTGraphicsState.updateClip(); - // currentStream.add(x + " " + y + " " + width + " " + height + " - // re "); - clip(); + /** @see org.apache.fop.render.AbstractRenderer */ + public String getMimeType() { + return MIME_TYPE; } /** - * Draw the background and borders. This draws the background and border - * traits for an area given the position. + * Draws the background and borders and adds a basic debug view // TODO + * implement visual-debugging as standalone + * + * @see org.apache.fop.render.java2d.Java2DRenderer#drawBackAndBorders(org.apache.fop.area.Area, + * float, float, float, float) * * @param block the area to get the traits from * @param startx the start x position @@ -604,130 +216,11 @@ public class AWTRenderer extends AbstractRenderer implements Printable, protected void drawBackAndBorders(Area area, float startx, float starty, float width, float height) { - if (debug) { // TODO implement visual-debugging as standalone - // Renderer + if (debug) { debugBackAndBorders(area, startx, starty, width, height); } - BorderProps bpsBefore = (BorderProps) area - .getTrait(Trait.BORDER_BEFORE); - BorderProps bpsAfter = (BorderProps) area.getTrait(Trait.BORDER_AFTER); - BorderProps bpsStart = (BorderProps) area.getTrait(Trait.BORDER_START); - BorderProps bpsEnd = (BorderProps) area.getTrait(Trait.BORDER_END); - - // draw background - Trait.Background back; - back = (Trait.Background) area.getTrait(Trait.BACKGROUND); - if (back != null) { - - // Calculate padding rectangle - float sx = startx; - float sy = starty; - float paddRectWidth = width; - float paddRectHeight = height; - - if (bpsStart != null) { - sx += bpsStart.width / 1000f; - paddRectWidth -= bpsStart.width / 1000f; - } - if (bpsBefore != null) { - sy += bpsBefore.width / 1000f; - paddRectHeight -= bpsBefore.width / 1000f; - } - if (bpsEnd != null) { - paddRectWidth -= bpsEnd.width / 1000f; - } - if (bpsAfter != null) { - paddRectHeight -= bpsAfter.width / 1000f; - } - - if (back.getColor() != null) { - drawBackground(back, sx, sy, paddRectWidth, paddRectHeight); - } - - // background image - if (back.getFopImage() != null) { - FopImage fopimage = back.getFopImage(); - if (fopimage != null && fopimage.load(FopImage.DIMENSIONS)) { - clip(sx, sy, paddRectWidth, paddRectHeight); - int horzCount = (int) ((paddRectWidth * 1000 / fopimage - .getIntrinsicWidth()) + 1.0f); - int vertCount = (int) ((paddRectHeight * 1000 / fopimage - .getIntrinsicHeight()) + 1.0f); - if (back.getRepeat() == EN_NOREPEAT) { - horzCount = 1; - vertCount = 1; - } else if (back.getRepeat() == EN_REPEATX) { - vertCount = 1; - } else if (back.getRepeat() == EN_REPEATY) { - horzCount = 1; - } - // change from points to millipoints - sx *= 1000; - sy *= 1000; - if (horzCount == 1) { - sx += back.getHoriz(); - } - if (vertCount == 1) { - sy += back.getVertical(); - } - for (int x = 0; x < horzCount; x++) { - for (int y = 0; y < vertCount; y++) { - // place once - Rectangle2D pos; - pos = new Rectangle2D.Float(sx - + (x * fopimage.getIntrinsicWidth()), sy - + (y * fopimage.getIntrinsicHeight()), - fopimage.getIntrinsicWidth(), fopimage - .getIntrinsicHeight()); - putImage(back.getURL(), pos); // TODO test - } - } - - } else { - getLogger().warn( - "Can't find background image: " + back.getURL()); - } - } - } - - // draw border - // BORDER_BEFORE - if (bpsBefore != null) { - int borderWidth = (int) Math.round((bpsBefore.width / 1000f) - * (scaleFactor / 100f)); - state.updateColor(bpsBefore.color); - state.getGraph().fillRect((int) startx, (int) starty, (int) width, - borderWidth); - } - // BORDER_AFTER - if (bpsAfter != null) { - int borderWidth = (int) Math.round((bpsAfter.width / 1000f) - * (scaleFactor / 100f)); - float sy = starty + height; - state.updateColor(bpsAfter.color); - state.getGraph().fillRect((int) startx, - (int) (starty + height - borderWidth), (int) width, - borderWidth); - } - // BORDER_START - if (bpsStart != null) { - int borderWidth = (int) Math.round((bpsStart.width / 1000f) - * (scaleFactor / 100f)); - state.updateColor(bpsStart.color); - state.getGraph().fillRect((int) startx, (int) starty, borderWidth, - (int) height); - } - // BORDER_END - if (bpsEnd != null) { - int borderWidth = (int) Math.round((bpsEnd.width / 1000f) - * (scaleFactor / 100f)); - float sx = startx + width; - state.updateColor(bpsEnd.color); - state.getGraph().fillRect((int) (startx + width - borderWidth), - (int) starty, borderWidth, (int) height); - } - + super.drawBackAndBorders(area, startx, starty, width, height); } /** Draws a thin border around every area to help debugging */ @@ -746,452 +239,4 @@ public class AWTRenderer extends AbstractRenderer implements Printable, // restores the last graphics state from the stack state.pop(); } - - /** - * Draw the Background Rectangle of a given area. - * - * @param back the Trait.Background - * @param sx x coordinate of the rectangle to be filled. - * @param sy y the y coordinate of the rectangle to be filled. - * @param paddRectWidth the width of the rectangle to be filled. - * @param paddRectHeight the height of the rectangle to be filled. - */ - protected void drawBackground(Trait.Background back, float sx, float sy, - float paddRectWidth, float paddRectHeight) { - - state.updateColor(back.getColor()); - state.getGraph().fillRect((int) sx, (int) sy, (int) paddRectWidth, - (int) paddRectHeight); - } - - /** - * Handle block traits. The block could be any sort of block with any - * positioning so this should render the traits such as border and - * background in its position. - * - * @param block the block to render the traits - */ - protected void handleBlockTraits(Block block) { - // copied from pdf - int borderPaddingStart = block.getBorderAndPaddingWidthStart(); - int borderPaddingBefore = block.getBorderAndPaddingWidthBefore(); - - float startx = currentIPPosition / 1000f; - float starty = currentBPPosition / 1000f; - float width = block.getIPD() / 1000f; - float height = block.getBPD() / 1000f; - - startx += block.getStartIndent() / 1000f; - startx -= block.getBorderAndPaddingWidthStart() / 1000f; - width += borderPaddingStart / 1000f; - width += block.getBorderAndPaddingWidthEnd() / 1000f; - height += borderPaddingBefore / 1000f; - height += block.getBorderAndPaddingWidthAfter() / 1000f; - - drawBackAndBorders(block, startx, starty, width, height); - } - - /** - * @see org.apache.fop.render.Renderer#renderText(TextArea) - */ - public void renderText(TextArea text) { - - float x = currentIPPosition; - float y = currentBPPosition + text.getOffset(); // baseline - - String name = (String) text.getTrait(Trait.FONT_NAME); - int size = ((Integer) text.getTrait(Trait.FONT_SIZE)).intValue(); - state.updateFont(name, size, null); - - ColorType ct = (ColorType) text.getTrait(Trait.COLOR); - state.updateColor(ct, false, null); - - String s = text.getTextArea(); - state.getGraph().drawString(s, x / 1000f, y / 1000f); - - getLogger().debug( - "renderText(): \"" + s + "\", x: " + x + ", y: " + y + state); - - // rendering text decorations - FontMetrics metrics = fontInfo.getMetricsFor(name); - Font fs = new Font(name, metrics, size); - renderTextDecoration(fs, text, y, x); - - super.renderText(text); - } - - /** - * @see org.apache.fop.render.Renderer#renderCharacter(Character) - */ - public void renderCharacter(Character ch) { - - float x = currentIPPosition; - float y = currentBPPosition + ch.getOffset(); // baseline - - String name = (String) ch.getTrait(Trait.FONT_NAME); - int size = ((Integer) ch.getTrait(Trait.FONT_SIZE)).intValue(); - state.updateFont(name, size, null); - - ColorType ct = (ColorType) ch.getTrait(Trait.COLOR); - state.updateColor(ct, false, null); - - String s = ch.getChar(); - state.getGraph().drawString(s, x / 1000f, y / 1000f); - - getLogger().debug( - "renderCharacter(): \"" + s + "\", x: " + x + ", y: " + y - + state); - - // rendering text decorations - FontMetrics metrics = fontInfo.getMetricsFor(name); - Font fs = new Font(name, metrics, size); - renderTextDecoration(fs, ch, y, x); - - super.renderCharacter(ch); - } - - /** - * Paints the text decoration marks. - * @param fs Current font - * @param inline inline area to paint the marks for - * @param baseline position of the baseline - * @param startIPD start IPD - */ - protected void renderTextDecoration(Font fs, InlineArea inline, - float baseline, float startIPD) { - - boolean hasTextDeco = inline.hasUnderline() || inline.hasOverline() - || inline.hasLineThrough(); - - if (hasTextDeco) { - state.updateStroke((fs.getDescender() / (-8 * 1000f)), - Constants.EN_SOLID); - float endIPD = startIPD + inline.getIPD(); - if (inline.hasUnderline()) { - ColorType ct = (ColorType) inline - .getTrait(Trait.UNDERLINE_COLOR); - state.updateColor(ct, false, null); - float y = baseline - fs.getDescender() / 2; - line.setLine(startIPD / 1000f, y / 1000f, endIPD / 1000f, - y / 1000f); - state.getGraph().draw(line); - } - if (inline.hasOverline()) { - ColorType ct = (ColorType) inline - .getTrait(Trait.OVERLINE_COLOR); - state.updateColor(ct, false, null); - float y = (float) (baseline - (1.1 * fs.getCapHeight())); - line.setLine(startIPD / 1000f, y / 1000f, endIPD / 1000f, - y / 1000f); - state.getGraph().draw(line); - } - if (inline.hasLineThrough()) { - ColorType ct = (ColorType) inline - .getTrait(Trait.LINETHROUGH_COLOR); - state.updateColor(ct, false, null); - float y = (float) (baseline - (0.45 * fs.getCapHeight())); - line.setLine(startIPD / 1000f, y / 1000f, endIPD / 1000f, - y / 1000f); - state.getGraph().draw(line); - } - } - } - - /** - * Render leader area. This renders a leader area which is an area with a - * rule. - * - * @param area the leader area to render - */ - public void renderLeader(Leader area) { - - // TODO leader-length: 25%, 50%, 75%, 100% not working yet - // TODO Colors do not work on Leaders yet - - float startx = ((float) currentIPPosition) / 1000f; - float starty = ((currentBPPosition + area.getOffset()) / 1000f); - float endx = (currentIPPosition + area.getIPD()) / 1000f; - - ColorType ct = (ColorType) area.getTrait(Trait.COLOR); - state.updateColor(ct, true, null); - - line.setLine(startx, starty, endx, starty); - float thickness = area.getRuleThickness() / 1000f; - - int style = area.getRuleStyle(); - switch (style) { - case EN_SOLID: - case EN_DOTTED: - case EN_DASHED: - state.updateStroke(thickness, style); - state.getGraph().draw(line); - break; - case EN_DOUBLE: - - state.updateStroke(thickness / 3f, EN_SOLID); // only a third - - // upper Leader - line.setLine(startx, starty, endx, starty); - state.getGraph().draw(line); - // lower Leader - line.setLine(startx, starty + 2 * thickness, endx, starty + 2 - * thickness); - state.getGraph().draw(line); - - break; - - case EN_GROOVE: - // The rule looks as though it were carved into the canvas. - // (Top/left half of the rule's thickness is the - // color specified; the other half is white.) - - state.updateStroke(thickness / 2f, EN_SOLID); // only the half - - // upper Leader - line.setLine(startx, starty, endx, starty); - state.getGraph().draw(line); - // lower Leader - line.setLine(startx, starty + thickness, endx, starty + thickness); - state.getGraph().setColor(Color.WHITE); - state.getGraph().draw(line); - - // TODO the implementation could be nicer, f.eg. with triangles at - // the tip of the lines. See also RenderX's implementation (looks - // like a button) - - break; - - case EN_RIDGE: - // The opposite of "groove", the rule looks as though it were - // coming out of the canvas. (Bottom/right half of the rule's - // thickness is the color specified; the other half is white.) - - state.updateStroke(thickness / 2f, EN_SOLID); // only the half - - // lower Leader - line.setLine(startx, starty + thickness, endx, starty + thickness); - state.getGraph().draw(line); - // upperLeader - line.setLine(startx, starty, endx, starty); - state.getGraph().setColor(Color.WHITE); - state.getGraph().draw(line); - - // TODO the implementation could be nicer, f.eg. with triangles at - // the tip of the lines. See also RenderX's implementation (looks - // like a button) - - break; - - case EN_NONE: - // No rule is drawn - break; - - } // end switch - - super.renderLeader(area); - } - - /** - * @see org.apache.fop.render.AbstractRenderer#renderImage(Image, - * Rectangle2D) - */ - public void renderImage(Image image, Rectangle2D pos) { - // endTextObject(); - String url = image.getURL(); - putImage(url, pos); - } - - /** - * draws an image - * - * @param url URL of the bitmap - * @param pos Position of the bitmap - */ - protected void putImage(String pUrl, Rectangle2D pos) { - - int x = currentIPPosition; // TODO + area.getXOffset(); - int y = currentBPPosition; - String url = ImageFactory.getURL(pUrl); - - ImageFactory fact = ImageFactory.getInstance(); - FopImage fopimage = fact.getImage(url, userAgent); - - if (fopimage == null) { - return; - } - if (!fopimage.load(FopImage.DIMENSIONS)) { - return; - } - int w = fopimage.getWidth(); - int h = fopimage.getHeight(); - String mime = fopimage.getMimeType(); - if ("text/xml".equals(mime)) { - if (!fopimage.load(FopImage.ORIGINAL_DATA)) { - return; - } - Document doc = ((XMLImage) fopimage).getDocument(); - String ns = ((XMLImage) fopimage).getNameSpace(); - renderDocument(doc, ns, pos); - - } else if ("image/svg+xml".equals(mime)) { - if (!fopimage.load(FopImage.ORIGINAL_DATA)) { - return; - } - Document doc = ((XMLImage) fopimage).getDocument(); - renderSVGDocument(doc, pos); // TODO check if ok. - - } else if ("image/eps".equals(mime)) { - getLogger().warn("EPS images are not supported by this renderer"); - currentBPPosition += (h * 1000); - } else if ("image/jpeg".equals(mime)) { - if (!fopimage.load(FopImage.ORIGINAL_DATA)) { - return; - } - - // TODO Load JPEGs rather through fopimage.load(FopImage.BITMAP), - // but JpegImage will need to be extended for that - - //url = url.substring(7); - //url = "C:/eclipse/myWorkbenches/fop4/xml-fop/examples/fo" + url; - java.awt.Image awtImage = new javax.swing.ImageIcon(url).getImage(); - - state.getGraph().drawImage(awtImage, (int) (x / 1000f), - (int) (y / 1000f), (int) w, h, null); - currentBPPosition += (h * 1000); - } else { - if (!fopimage.load(FopImage.BITMAP)) { - getLogger().warn("Loading of bitmap failed: " + url); - return; - } - - byte[] raw = fopimage.getBitmaps(); - - //TODO Hardcoded color and sample models, FIX ME! - ColorModel cm = new ComponentColorModel( - ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB), - false, false, ColorModel.OPAQUE, DataBuffer.TYPE_BYTE); - SampleModel sampleModel = new PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE, - w, h, 3, w * 3, new int[] {0, 1, 2}); - DataBuffer dbuf = new DataBufferByte(raw, w * h * 3); - - WritableRaster raster = Raster.createWritableRaster(sampleModel, dbuf, null); - - java.awt.Image awtImage; - // Combine the color model and raster into a buffered image - awtImage = new BufferedImage(cm, raster, false, null); - - state.getGraph().drawImage(awtImage, (int) (x / 1000f), - (int) (y / 1000f), (int) w, h, null); - currentBPPosition += (h * 1000); - } - } - - /** - * @see org.apache.fop.render.AbstractRenderer#renderForeignObject(ForeignObject, - * Rectangle2D) - */ - public void renderForeignObject(ForeignObject fo, Rectangle2D pos) { - Document doc = fo.getDocument(); - String ns = fo.getNameSpace(); - if (ns.equals("http://www.w3.org/2000/svg")) { - renderSVGDocument(doc, pos); - } else { - renderDocument(doc, ns, pos); - } - // this.currentXPosition += area.getContentWidth(); - } - - /** - * Renders an XML document (SVG for example). - * - * @param doc DOM document representing the XML document - * @param ns Namespace for the document - * @param pos Position on the page - */ - public void renderDocument(Document doc, String ns, Rectangle2D pos) { - RendererContext context; - context = new RendererContext(MIME_TYPE); - context.setUserAgent(userAgent); - // TODO implement - /* - * context.setProperty(PDFXMLHandler.PDF_DOCUMENT, pdfDoc); - * context.setProperty(PDFXMLHandler.OUTPUT_STREAM, ostream); - * context.setProperty(PDFXMLHandler.PDF_STATE, currentState); - * context.setProperty(PDFXMLHandler.PDF_PAGE, currentPage); - * context.setProperty(PDFXMLHandler.PDF_CONTEXT, currentContext == null ? - * currentPage : currentContext); - * context.setProperty(PDFXMLHandler.PDF_CONTEXT, currentContext); - * context.setProperty(PDFXMLHandler.PDF_STREAM, currentStream); - * context.setProperty(PDFXMLHandler.PDF_XPOS, new - * Integer(currentIPPosition + (int) pos.getX())); - * context.setProperty(PDFXMLHandler.PDF_YPOS, new - * Integer(currentBPPosition + (int) pos.getY())); - * context.setProperty(PDFXMLHandler.PDF_FONT_INFO, fontInfo); - * context.setProperty(PDFXMLHandler.PDF_FONT_NAME, currentFontName); - * context.setProperty(PDFXMLHandler.PDF_FONT_SIZE, new - * Integer(currentFontSize)); - * context.setProperty(PDFXMLHandler.PDF_WIDTH, new Integer((int) - * pos.getWidth())); context.setProperty(PDFXMLHandler.PDF_HEIGHT, new - * Integer((int) pos.getHeight())); renderXML(userAgent, context, doc, - * ns); - */ - } - - protected void renderSVGDocument(Document doc, Rectangle2D pos) { - - int x = currentIPPosition; // TODO + area.getXOffset(); - int y = currentBPPosition; - - RendererContext context; - context = new RendererContext(MIME_TYPE); - context.setUserAgent(userAgent); - - SVGUserAgent ua = new SVGUserAgent(context.getUserAgent() - .getPixelUnitToMillimeter(), new AffineTransform()); - - GVTBuilder builder = new GVTBuilder(); - BridgeContext ctx = new BridgeContext(ua); - - GraphicsNode root; - try { - root = builder.build(ctx, doc); - } catch (Exception e) { - getLogger().error( - "svg graphic could not be built: " + e.getMessage(), e); - return; - } - float w = (float) ctx.getDocumentSize().getWidth() * 1000f; - float h = (float) ctx.getDocumentSize().getHeight() * 1000f; - - // correct integer roundoff - state.getGraph().translate(x / 1000, y / 1000); - - SVGSVGElement svg = ((SVGDocument) doc).getRootElement(); - AffineTransform at = ViewBox.getPreserveAspectRatioTransform(svg, - w / 1000f, h / 1000f); - AffineTransform inverse = null; - try { - inverse = at.createInverse(); - } catch (NoninvertibleTransformException e) { - getLogger().warn(e); - } - if (!at.isIdentity()) { - state.getGraph().transform(at); - } - - try { - root.paint(state.getGraph()); - } catch (Exception e) { - e.printStackTrace(); - } - - if (inverse != null && !inverse.isIdentity()) { - state.getGraph().transform(inverse); - } - // correct integer roundoff - // currentState.getCurrentGraphics().translate(-x / 1000f, y / 1000f - - // pageHeight); - state.getGraph().translate(-(x + 500) / 1000, - (y + 500) / 1000 - pageHeight); - } } diff --git a/src/java/org/apache/fop/render/awt/FontMetricsMapper.java b/src/java/org/apache/fop/render/awt/FontMetricsMapper.java deleted file mode 100644 index 6e0df2c66..000000000 --- a/src/java/org/apache/fop/render/awt/FontMetricsMapper.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright 1999-2004 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.render.awt; - -// Java -import java.awt.Graphics2D; -import java.util.Map; - -// FOP -import org.apache.fop.fonts.FontMetrics; -import org.apache.fop.fonts.FontType; - - -/** - * This class implements org.apache.fop.layout.FontMetrics and - * is added to the hash table in FontInfo. It deferes the - * actual calculation of the metrics to - * AWTFontMetrics. It only keeps the java name and - * style as member varibles - */ - -public class FontMetricsMapper implements FontMetrics { - - /** - * The first and last non space-character - */ - private static final int FIRST_CHAR = 32; - private static final int LAST_CHAR = 255; - - /** - * This is a AWTFontMetrics that does the real calculation. - * It is only one class that dynamically determines the font-size. - */ - private static AWTFontMetrics metric = null; - - /** - * The java name of the font. - * # Make the family name immutable. - */ - private final String family; - - /** - * The java style of the font. - * # Make the style immutable. - */ - private final int style; - - /** - * Constructs a new Font-metrics. - * @param family the family name of the font (java value) - * @param style the java type style value of the font - * @param graphics a Graphics2D object - this is needed so - * that we can get an instance of java.awt.FontMetrics - */ - public FontMetricsMapper(String family, int style, Graphics2D graphics) { - this.family = family; - this.style = style; - if (metric == null) { - metric = new AWTFontMetrics(graphics); - } - } - - /** - * @see org.apache.fop.fonts.FontMetrics#getFontName() - */ - public String getFontName() { - return family; - } - - /** - * @see org.apache.fop.fonts.FontMetrics#getFontType() - */ - public FontType getFontType() { - return FontType.OTHER; - } - - /** - * @see org.apache.fop.fonts.FontMetrics#getAscender(int) - */ - public int getAscender(int size) { - return metric.getAscender(family, style, size); - } - - /** - * @see org.apache.fop.fonts.FontMetrics#getCapHeight(int) - */ - public int getCapHeight(int size) { - return metric.getCapHeight(family, style, size); - } - - /** - * @see org.apache.fop.fonts.FontMetrics#getDescender(int) - */ - public int getDescender(int size) { - return metric.getDescender(family, style, size); - } - - /** - * @see org.apache.fop.fonts.FontMetrics#getXHeight(int) - */ - public int getXHeight(int size) { - return metric.getXHeight(family, style, size); - } - - /** - * @see org.apache.fop.fonts.FontMetrics#getWidth(int, int) - */ - public int getWidth(int i, int size) { - return metric.width(i, family, style, size); - } - - - /** - * @see org.apache.fop.fonts.FontMetrics#getWidths() - */ - public int[] getWidths() { - return metric.getWidths(family, style, AWTFontMetrics.FONT_SIZE); - } - - /** - * Gets a Font instance of the Font that this - * FontMetrics describes in the desired size. - * @param size font size - * @return font with the desired characeristics. - */ - public java.awt.Font getFont(int size) { - return metric.getFont(family, style, size); - } - - /** - * @see org.apache.fop.fonts.FontMetrics#getKerningInfo() - */ - public Map getKerningInfo() { - return java.util.Collections.EMPTY_MAP; - } - - /** - * @see org.apache.fop.fonts.FontMetrics#hasKerningInfo() - */ - public boolean hasKerningInfo() { - return false; - } - - -} - - - - - diff --git a/src/java/org/apache/fop/render/awt/FontSetup.java b/src/java/org/apache/fop/render/awt/FontSetup.java deleted file mode 100644 index 0c7811003..000000000 --- a/src/java/org/apache/fop/render/awt/FontSetup.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright 1999-2004 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.render.awt; - -// FOP -import org.apache.fop.fonts.FontInfo; -import org.apache.fop.fonts.Font; - -// Java -import java.awt.Graphics2D; - -/** - * Sets up the AWT fonts. It is similar to - * org.apache.fop.render.pdf.FontSetup. - * Assigns the font (with metrics) to internal names like "F1" and - * assigns family-style-weight triplets to the fonts. - */ -public class FontSetup { - - - /** - * Sets up the font info object. - * - * Adds metrics for basic fonts and useful family-style-weight - * triplets for lookup. - * - * @param fontInfo the font info object to set up - * @param graphics needed for acces to font metrics - */ - public static void setup(FontInfo fontInfo, Graphics2D graphics) { - FontMetricsMapper metric; - int normal, bold, bolditalic, italic; - - /* - * available java fonts are: - * Serif - bold, normal, italic, bold-italic - * SansSerif - bold, normal, italic, bold-italic - * MonoSpaced - bold, normal, italic, bold-italic - */ - normal = java.awt.Font.PLAIN; - bold = java.awt.Font.BOLD; - italic = java.awt.Font.ITALIC; - bolditalic = java.awt.Font.BOLD + java.awt.Font.ITALIC; - - metric = new FontMetricsMapper("SansSerif", normal, graphics); - // --> goes to F1 - fontInfo.addMetrics("F1", metric); - metric = new FontMetricsMapper("SansSerif", italic, graphics); - // --> goes to F2 - fontInfo.addMetrics("F2", metric); - metric = new FontMetricsMapper("SansSerif", bold, graphics); - // --> goes to F3 - fontInfo.addMetrics("F3", metric); - metric = new FontMetricsMapper("SansSerif", bolditalic, graphics); - // --> goes to F4 - fontInfo.addMetrics("F4", metric); - - - metric = new FontMetricsMapper("Serif", normal, graphics); - // --> goes to F5 - fontInfo.addMetrics("F5", metric); - metric = new FontMetricsMapper("Serif", italic, graphics); - // --> goes to F6 - fontInfo.addMetrics("F6", metric); - metric = new FontMetricsMapper("Serif", bold, graphics); - // --> goes to F7 - fontInfo.addMetrics("F7", metric); - metric = new FontMetricsMapper("Serif", bolditalic, graphics); - // --> goes to F8 - fontInfo.addMetrics("F8", metric); - - metric = new FontMetricsMapper("MonoSpaced", normal, graphics); - // --> goes to F9 - fontInfo.addMetrics("F9", metric); - metric = new FontMetricsMapper("MonoSpaced", italic, graphics); - // --> goes to F10 - fontInfo.addMetrics("F10", metric); - metric = new FontMetricsMapper("MonoSpaced", bold, graphics); - // --> goes to F11 - fontInfo.addMetrics("F11", metric); - metric = new FontMetricsMapper("MonoSpaced", bolditalic, graphics); - // --> goes to F12 - fontInfo.addMetrics("F12", metric); - - metric = new FontMetricsMapper("Symbol", bolditalic, graphics); - // --> goes to F13 and F14 - fontInfo.addMetrics("F13", metric); - fontInfo.addMetrics("F14", metric); - - // Custom type 1 fonts step 1/2 - // fontInfo.addMetrics("F15", new OMEP()); - // fontInfo.addMetrics("F16", new GaramondLightCondensed()); - // fontInfo.addMetrics("F17", new BauerBodoniBoldItalic()); - - /* any is treated as serif */ - fontInfo.addFontProperties("F5", "any", "normal", Font.NORMAL); - fontInfo.addFontProperties("F6", "any", "italic", Font.NORMAL); - fontInfo.addFontProperties("F6", "any", "oblique", Font.NORMAL); - fontInfo.addFontProperties("F7", "any", "normal", Font.BOLD); - fontInfo.addFontProperties("F8", "any", "italic", Font.BOLD); - fontInfo.addFontProperties("F8", "any", "oblique", Font.BOLD); - - fontInfo.addFontProperties("F1", "sans-serif", "normal", Font.NORMAL); - fontInfo.addFontProperties("F2", "sans-serif", "oblique", Font.NORMAL); - fontInfo.addFontProperties("F2", "sans-serif", "italic", Font.NORMAL); - fontInfo.addFontProperties("F3", "sans-serif", "normal", Font.BOLD); - fontInfo.addFontProperties("F4", "sans-serif", "oblique", Font.BOLD); - fontInfo.addFontProperties("F4", "sans-serif", "italic", Font.BOLD); - fontInfo.addFontProperties("F5", "serif", "normal", Font.NORMAL); - fontInfo.addFontProperties("F6", "serif", "oblique", Font.NORMAL); - fontInfo.addFontProperties("F6", "serif", "italic", Font.NORMAL); - fontInfo.addFontProperties("F7", "serif", "normal", Font.BOLD); - fontInfo.addFontProperties("F8", "serif", "oblique", Font.BOLD); - fontInfo.addFontProperties("F8", "serif", "italic", Font.BOLD); - fontInfo.addFontProperties("F9", "monospace", "normal", Font.NORMAL); - fontInfo.addFontProperties("F10", "monospace", "oblique", Font.NORMAL); - fontInfo.addFontProperties("F10", "monospace", "italic", Font.NORMAL); - fontInfo.addFontProperties("F11", "monospace", "normal", Font.BOLD); - fontInfo.addFontProperties("F12", "monospace", "oblique", Font.BOLD); - fontInfo.addFontProperties("F12", "monospace", "italic", Font.BOLD); - - fontInfo.addFontProperties("F1", "Helvetica", "normal", Font.NORMAL); - fontInfo.addFontProperties("F2", "Helvetica", "oblique", Font.NORMAL); - fontInfo.addFontProperties("F2", "Helvetica", "italic", Font.NORMAL); - fontInfo.addFontProperties("F3", "Helvetica", "normal", Font.BOLD); - fontInfo.addFontProperties("F4", "Helvetica", "oblique", Font.BOLD); - fontInfo.addFontProperties("F4", "Helvetica", "italic", Font.BOLD); - fontInfo.addFontProperties("F5", "Times", "normal", Font.NORMAL); - fontInfo.addFontProperties("F6", "Times", "oblique", Font.NORMAL); - fontInfo.addFontProperties("F6", "Times", "italic", Font.NORMAL); - fontInfo.addFontProperties("F7", "Times", "normal", Font.BOLD); - fontInfo.addFontProperties("F8", "Times", "oblique", Font.BOLD); - fontInfo.addFontProperties("F8", "Times", "italic", Font.BOLD); - fontInfo.addFontProperties("F9", "Courier", "normal", Font.NORMAL); - fontInfo.addFontProperties("F10", "Courier", "oblique", Font.NORMAL); - fontInfo.addFontProperties("F10", "Courier", "italic", Font.NORMAL); - fontInfo.addFontProperties("F11", "Courier", "normal", Font.BOLD); - fontInfo.addFontProperties("F12", "Courier", "oblique", Font.BOLD); - fontInfo.addFontProperties("F12", "Courier", "italic", Font.BOLD); - fontInfo.addFontProperties("F13", "Symbol", "normal", Font.NORMAL); - fontInfo.addFontProperties("F14", "ZapfDingbats", "normal", Font.NORMAL); - - // Custom type 1 fonts step 2/2 - // fontInfo.addFontProperties("F15", "OMEP", "normal", FontInfo.NORMAL); - // fontInfo.addFontProperties("F16", "Garamond-LightCondensed", "normal", FontInfo.NORMAL); - // fontInfo.addFontProperties("F17", "BauerBodoni", "italic", FontInfo.BOLD); - - /* for compatibility with PassiveTex */ - fontInfo.addFontProperties("F5", "Times-Roman", "normal", Font.NORMAL); - fontInfo.addFontProperties("F6", "Times-Roman", "oblique", Font.NORMAL); - fontInfo.addFontProperties("F6", "Times-Roman", "italic", Font.NORMAL); - fontInfo.addFontProperties("F7", "Times-Roman", "normal", Font.BOLD); - fontInfo.addFontProperties("F8", "Times-Roman", "oblique", Font.BOLD); - fontInfo.addFontProperties("F8", "Times-Roman", "italic", Font.BOLD); - fontInfo.addFontProperties("F5", "Times Roman", "normal", Font.NORMAL); - fontInfo.addFontProperties("F6", "Times Roman", "oblique", Font.NORMAL); - fontInfo.addFontProperties("F6", "Times Roman", "italic", Font.NORMAL); - fontInfo.addFontProperties("F7", "Times Roman", "normal", Font.BOLD); - fontInfo.addFontProperties("F8", "Times Roman", "oblique", Font.BOLD); - fontInfo.addFontProperties("F8", "Times Roman", "italic", Font.BOLD); - fontInfo.addFontProperties("F9", "Computer-Modern-Typewriter", - "normal", Font.NORMAL); - } - -} - diff --git a/src/java/org/apache/fop/render/awt/RendererState.java b/src/java/org/apache/fop/render/awt/RendererState.java deleted file mode 100644 index 3fdc8690a..000000000 --- a/src/java/org/apache/fop/render/awt/RendererState.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright 2005 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* $Id$ */ - -package org.apache.fop.render.awt; - -import java.awt.Graphics2D; -import java.awt.Paint; -import java.awt.Shape; -import java.awt.geom.AffineTransform; - -import org.apache.fop.datatypes.ColorType; - -/** - * An interface for the classes which hold the state of the current graphics context. - */ -public interface RendererState { - - /** - * Push the current state onto the stack. - */ - public abstract void push(); - - /** - * Pop the state from the stack and restore the graphics context. - * @return the restored state, null if the stack is empty. - */ - public abstract Graphics2D pop(); - - /** - * Get the current stack level. - * - * @return the current stack level - */ - public abstract int getStackLevel(); - - /** - * Establishes a new foreground or fill color. - * @param col the color to apply (null skips this operation) - * @param fill true to set the fill color, false for the foreground color - * @param pdf only used by the PDFRenderer, is set to null. - * @return true if the new Color changes the current Color - */ - public abstract boolean updateColor(ColorType col, boolean fill, StringBuffer pdf); - - /** - * Set the current font name. Check if the font name will change and then - * set the new name. - * - * @param name the new font name - * @param size - * @param pdf - * @return true if the new Font changes the current Font - */ - public abstract boolean updateFont(String name, int size, StringBuffer pdf); - - /** - * Sets the current Stroke. The line width should be set with - * updateLineWidth() before calling this method - * - * @param style the constant for the style of the line as an int - * @return true if the new Stroke changes the current Stroke - */ - public abstract boolean updateStroke(float width, int style); - - /** - * Set the current paint. This checks if the paint will change and then sets - * the current paint. - * - * @param p the new paint - * @return true if the new paint changes the current paint - */ - public abstract boolean updatePaint(Paint p); - - /** - * Check if the clip will change the current state. A clip is assumed to be - * used in a situation where it will add to any clip in the current or - * parent states. A clip cannot be cleared, this can only be achieved by - * going to a parent level with the correct clip. If the clip is different - * then it may start a new state so that it can return to the previous clip. - * - * @param cl the clip shape to check - * @return true if the clip will change the current clip. - */ - // TODO test - public abstract boolean checkClip(Shape cl); - - /** - * Set the current clip. This either sets a new clip or sets the clip to the - * intersect of the old clip and the new clip. - * - * @param cl the new clip in the current state - */ - public abstract boolean updateClip(Shape cl); - - /** - * Check the current transform. The transform for the current state is the - * combination of all transforms in the current state. The parameter is - * compared against this current transform. - * - * @param tf the transform to check against - * @return true if the new transform is different from the current transform - */ - public abstract boolean checkTransform(AffineTransform tf); - - /** - * Overwrites the Transform in the Graphics2D context. Use <code>transform()</code> if you - * wish to compose with the current Affinetransform instead. - * @see java.awt.Graphics2D.setTransform(). - * @param tf the transform to concatonate to the current level transform - */ - public abstract void setTransform(AffineTransform tf); - - /** - * Composes an AffineTransform object with the Transform in this Graphics2D - * according to the rule last-specified-first-applied. - * @see java.awt.Graphics2D.transform(). - * - * @param tf the transform to concatonate to the current level transform - */ - public abstract void transform(AffineTransform tf); - - /** - * Get the current transform. This gets the combination of all transforms in - * the current state. - * - * @return the calculate combined transform for the current state - */ - public abstract AffineTransform getTransform(); - -} diff --git a/src/java/org/apache/fop/render/awt/viewer/PreviewDialog.java b/src/java/org/apache/fop/render/awt/viewer/PreviewDialog.java index 340eeec1d..b1e6e0c29 100644 --- a/src/java/org/apache/fop/render/awt/viewer/PreviewDialog.java +++ b/src/java/org/apache/fop/render/awt/viewer/PreviewDialog.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -15,14 +15,17 @@ */ /* $Id$ */ - + +// Originally contributed by: +// Juergen Verwohlt: Juergen.Verwohlt@jCatalog.com, +// Rainer Steinkuhle: Rainer.Steinkuhle@jCatalog.com, +// Stanislav Gorkhover: Stanislav.Gorkhover@jCatalog.com package org.apache.fop.render.awt.viewer; -//Java +// Java import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; -import java.awt.Graphics; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; @@ -44,9 +47,11 @@ import javax.swing.JMenuBar; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; +import javax.swing.JButton; import javax.swing.JToolBar; import javax.swing.SwingUtilities; import javax.swing.UIManager; +import javax.swing.border.EmptyBorder; import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; @@ -54,15 +59,9 @@ import org.apache.fop.apps.Fop; import org.apache.fop.fo.Constants; import org.apache.fop.render.awt.AWTRenderer; -/** - * AWT Viewer main window. - * Originally contributed by: - * Juergen Verwohlt: Juergen.Verwohlt@jCatalog.com, - * Rainer Steinkuhle: Rainer.Steinkuhle@jCatalog.com, - * Stanislav Gorkhover: Stanislav.Gorkhover@jCatalog.com - */ +/** AWT Viewer main window. */ public class PreviewDialog extends JFrame { - + /** The Translator for localization */ protected Translator translator; /** The AWT renderer */ @@ -72,12 +71,22 @@ public class PreviewDialog extends JFrame { /** The Fop object used for refreshing/reloading the view */ protected Fop fop; + /** The number of the page which is currently visible */ private int currentPage = 0; - private int pageCount = 0; + + /** The Reloader, when the user clicks on menu "reload" */ private Reloader reloader; + + /** The JCombobox to rescale the rendered page view */ private JComboBox scale; + + /** The JLabel for the process status bar */ private JLabel processStatus; + + /** The JLabel that holds the rendered page */ private JLabel pageLabel; + + /** The JLabel information status bar */ private JLabel infoStatus; /** @@ -92,7 +101,7 @@ public class PreviewDialog extends JFrame { //Commands aka Actions Command printAction = new Command(translator.getString("Menu.Print"), "Print") { public void doit() { - print(); + startPrinterJob(); } }; Command firstPageAction = new Command(translator.getString("Menu.First.page"), @@ -124,11 +133,16 @@ public class PreviewDialog extends JFrame { } }; Command debugAction = new Command(" Debug") { - //TODO use Translator + // TODO use Translator public void doit() { debug(); } }; + Command aboutAction = new Command("About FOP", "fopLogo") { + public void doit() { + startHelpAbout(); + } + }; //set the system look&feel try { @@ -146,6 +160,8 @@ public class PreviewDialog extends JFrame { //Page view stuff pageLabel = new JLabel(); + pageLabel.setHorizontalAlignment(0 /* CENTER */); + pageLabel.setBorder(new EmptyBorder(20, 0, 20, 0)); JScrollPane previewArea = new JScrollPane(pageLabel); previewArea.getViewport().setBackground(Color.gray); previewArea.setMinimumSize(new Dimension(50, 50)); @@ -159,20 +175,20 @@ public class PreviewDialog extends JFrame { scale.addItem("100%"); scale.addItem("150%"); scale.addItem("200%"); + scale.addItem("400%"); scale.setMaximumSize(new Dimension(80, 24)); scale.setPreferredSize(new Dimension(80, 24)); + scale.setSelectedItem("100%"); scale.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { scaleActionPerformed(e); } }); - scale.setSelectedItem("100%"); - renderer.setScaleFactor(100.0); //Menu setJMenuBar(setupMenu()); - //Toolbar + // Toolbar JToolBar toolBar = new JToolBar(); toolBar.add(printAction); toolBar.add(reloadAction); @@ -181,21 +197,24 @@ public class PreviewDialog extends JFrame { toolBar.add(previousPageAction); toolBar.add(nextPageAction); toolBar.add(lastPageAction); - toolBar.addSeparator(); + toolBar.addSeparator(new Dimension(20,0)); toolBar.add(new JLabel(translator.getString("Menu.Zoom"))); toolBar.add(scale); toolBar.addSeparator(); toolBar.add(debugAction); + toolBar.addSeparator(new Dimension(60,0)); + toolBar.add(aboutAction); getContentPane().add(toolBar, BorderLayout.NORTH); - //Status bar + + // Status bar JPanel statusBar = new JPanel(); processStatus = new JLabel(); processStatus.setBorder(BorderFactory.createCompoundBorder( - BorderFactory.createEtchedBorder(), + BorderFactory.createEtchedBorder(), BorderFactory.createEmptyBorder(0, 3, 0, 0))); infoStatus = new JLabel(); infoStatus.setBorder(BorderFactory.createCompoundBorder( - BorderFactory.createEtchedBorder(), + BorderFactory.createEtchedBorder(), BorderFactory.createEmptyBorder(0, 3, 0, 0))); statusBar.setLayout(new GridBagLayout()); @@ -229,7 +248,7 @@ public class PreviewDialog extends JFrame { //Adds mostly the same actions, but without icons menu.add(new Command(translator.getString("Menu.Print")) { public void doit() { - print(); + startPrinterJob(); } }); // inputHandler must be set to allow reloading @@ -305,6 +324,11 @@ public class PreviewDialog extends JFrame { setScale(200.0); } }); + subMenu.add(new Command("400%") { + public void doit() { + setScale(400.0); + } + }); menu.add(subMenu); menu.addSeparator(); menu.add(new Command(translator.getString("Menu.Default.zoom")) { @@ -323,9 +347,7 @@ public class PreviewDialog extends JFrame { return menuBar; } - /** - * Shows the About box - */ + /** Shows the About box */ private void startHelpAbout() { PreviewDialogAboutBox dlg = new PreviewDialogAboutBox(this, translator); //Centers the box @@ -343,8 +365,8 @@ public class PreviewDialog extends JFrame { */ private void goToPage(int number) { currentPage = number; - renderer.setPageNumber(number); showPage(); + setInfo(); } /** @@ -358,12 +380,11 @@ public class PreviewDialog extends JFrame { goToPage(currentPage); } - /** * Shows the next page. */ private void goToNextPage() { - if (currentPage >= pageCount - 1) { + if (currentPage >= renderer.getNumberOfPages() - 1) { return; } currentPage++; @@ -374,10 +395,10 @@ public class PreviewDialog extends JFrame { * Shows the last page. */ private void goToLastPage() { - if (currentPage == pageCount - 1) { + if (currentPage == renderer.getNumberOfPages() - 1) { return; } - currentPage = pageCount - 1; + currentPage = renderer.getNumberOfPages() - 1; goToPage(currentPage); } @@ -396,26 +417,38 @@ public class PreviewDialog extends JFrame { */ private void debug(){ renderer.debug = !renderer.debug; - showPage(); + reload(); } /** - * This class is used to reload document in - * a thread safe way. + * This class is used to reload document in a thread safe way. */ private class Reloader extends Thread { public void run() { + + if (!renderer.renderingDone) { + // do not allow the reloading while FOP is + // still rendering + JOptionPane.showMessageDialog(getContentPane(), + "Cannot perform the requested operation until " + + "all page are rendererd. Please wait", + "Please wait ", 1 /* INFORMATION_MESSAGE */); + return; + } + if (fop == null) { fop = new Fop(Constants.RENDER_AWT, foUserAgent); } - + pageLabel.setIcon(null); - infoStatus.setText(""); + int savedCurrentPage = currentPage; currentPage = 0; + renderer.clearViewportList(); try { setStatus(translator.getString("Status.Build.FO.tree")); foUserAgent.getInputHandler().render(fop); + goToPage(savedCurrentPage); setStatus(translator.getString("Status.Show")); } catch (FOPException e) { reportException(e); @@ -433,16 +466,14 @@ public class PreviewDialog extends JFrame { (int)getLocation().getY() + 50); d.setVisible(true); currentPage = d.getPageNumber(); - if (currentPage < 1 || currentPage > pageCount) { + if (currentPage < 1 || currentPage > renderer.getNumberOfPages()) { return; } currentPage--; goToPage(currentPage); } - /** - * Shows the first page. - */ + /** Shows the first page. */ private void goToFirstPage() { if (currentPage == 0) { return; @@ -451,24 +482,20 @@ public class PreviewDialog extends JFrame { goToPage(currentPage); } - /** - * Prints the document - */ - private void print() { + /** Prints the document */ + private void startPrinterJob() { PrinterJob pj = PrinterJob.getPrinterJob(); pj.setPageable(renderer); if (pj.printDialog()) { try { pj.print(); - } catch (PrinterException pe) { - pe.printStackTrace(); + } catch (PrinterException e) { + e.printStackTrace(); } } } - /** - * Scales page image - */ + /** Scales page image */ private void setScale(double scaleFactor) { if (scaleFactor == 25.0) { scale.setSelectedIndex(0); @@ -482,11 +509,11 @@ public class PreviewDialog extends JFrame { scale.setSelectedIndex(4); } else if (scaleFactor == 200.0) { scale.setSelectedIndex(5); + } else if (scaleFactor == 400.0) { + scale.setSelectedIndex(6); } - renderer.setScaleFactor(scaleFactor); - if (renderer.getNumberOfPages() != 0) { - showPage(); - } + renderer.setScaleFactor(scaleFactor / 100d); + reload(); } private void scaleActionPerformed(ActionEvent e) { @@ -502,32 +529,50 @@ public class PreviewDialog extends JFrame { SwingUtilities.invokeLater(new ShowStatus(message)); } - /** - * This class is used to show status in a thread safe way. - */ + /** This class is used to show status in a thread safe way. */ private class ShowStatus implements Runnable { - /** - * The message to display - */ + + /** The message to display */ private String message; + /** - * Constructs ShowStatus thread + * Constructs ShowStatus thread * @param message message to display */ public ShowStatus(String message) { this.message = message; } - + public void run() { processStatus.setText(message.toString()); } } /** - * Starts rendering process and shows the current page. + * Updates the message to be shown in the info bar in a thread safe way. */ - public void showPage() { + public void setInfo() { + SwingUtilities.invokeLater(new ShowInfo()); + } + + /** This class is used to show info in a thread safe way. */ + private class ShowInfo implements Runnable { + + public void run() { + + String message = translator.getString("Status.Page") + " " + + (currentPage + 1) + " " + + translator.getString("Status.of") + " " + + renderer.getCurrentPageNumber(); + + infoStatus.setText(message); + } + } + + /** Starts rendering process and shows the current page. */ + public synchronized void showPage() { ShowPageImage viewer = new ShowPageImage(); + if (SwingUtilities.isEventDispatchThread()) { viewer.run(); } else { @@ -535,38 +580,25 @@ public class PreviewDialog extends JFrame { } } - - /** - * This class is used to update the page image - * in a thread safe way. - */ + /** This class is used to render the page image in a thread safe way. */ private class ShowPageImage implements Runnable { + /** - * The run method that does the actual updating + * The run method that does the actual rendering of the viewed page */ public void run() { + + setStatus(translator.getString("Status.Build.FO.tree")); + + BufferedImage pageImage = null; try { - BufferedImage pageImage = null; - Graphics graphics = null; - pageImage = renderer.getPageImage(currentPage); - if (pageImage == null) - return; - graphics = pageImage.getGraphics(); - graphics.setColor(Color.black); - graphics.drawRect(0, 0, pageImage.getWidth() - 1, - pageImage.getHeight() - 1); - - pageLabel.setIcon(new ImageIcon(pageImage)); - pageCount = renderer.getNumberOfPages(); - - // Update status bar - infoStatus.setText(translator.getString("Status.Page") + " " - + (currentPage + 1) + " " - + translator.getString("Status.of") + " " + pageCount); } catch (FOPException e) { reportException(e); } + pageLabel.setIcon(new ImageIcon(pageImage)); + + setStatus(translator.getString("Status.Show")); } } @@ -581,10 +613,9 @@ public class PreviewDialog extends JFrame { getContentPane(), "<html><b>" + msg + ":</b><br>" + e.getClass().getName() + "<br>" - + e.getMessage() + "</html>", + + e.getMessage() + "</html>", translator.getString("Exception.Error"), JOptionPane.ERROR_MESSAGE ); } } - diff --git a/src/java/org/apache/fop/render/awt/viewer/PreviewDialogAboutBox.java b/src/java/org/apache/fop/render/awt/viewer/PreviewDialogAboutBox.java index 9974f841e..45535aa44 100644 --- a/src/java/org/apache/fop/render/awt/viewer/PreviewDialogAboutBox.java +++ b/src/java/org/apache/fop/render/awt/viewer/PreviewDialogAboutBox.java @@ -1,12 +1,12 @@ /* * Copyright 1999-2004 The Apache Software Foundation. - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -15,7 +15,7 @@ */ /* $Id$ */ - + package org.apache.fop.render.awt.viewer; //Java @@ -65,9 +65,9 @@ public class PreviewDialogAboutBox extends Dialog implements ActionListener { JPanel insetsPanel3 = new JPanel(); okButton = new JButton(); JLabel imageControl1 = new JLabel(); - imageControl1.setIcon(new ImageIcon(getClass().getResource("images/fop.gif"))); + imageControl1.setIcon(new ImageIcon(getClass().getResource("images/logo_big.jpg"))); JLabel label1 = new JLabel(translator.getString("About.Product")); - JLabel label2 = new JLabel(translator.getString("About.Version") + JLabel label2 = new JLabel(translator.getString("About.Version") + " " + Fop.getVersion()); JLabel label3 = new JLabel(translator.getString("About.Copyright")); panel1.setLayout(new BorderLayout()); diff --git a/src/java/org/apache/fop/render/awt/viewer/images/fopLogo.gif b/src/java/org/apache/fop/render/awt/viewer/images/fopLogo.gif new file mode 100644 index 000000000..3d1a74ee7 --- /dev/null +++ b/src/java/org/apache/fop/render/awt/viewer/images/fopLogo.gif @@ -0,0 +1,11 @@ +GIF89a,� �#G�<����]k}}}RRX���666wpt������%%%������\\\222iiibbb������BBB���W:���???DED===ppp����������$BWVW���""!ddd���� =```ttu���������RRR��ƴ��xxx�K���llljjjCBE!*&OOO������KKK$---���,,,fff)))**+^^^dcc[Z[ooo������������������vvv�����������������ԗ�������������㖖���³�����sss��������ꇇ��������������������������������ᬬ�������HHH������6J�����ӌ-6=@pvq'('���N///NNRXW[l8-IJK���GTN�������+! %�����ѩ=���������LLL9=?C/D���qsu���������ghg\D:ggl?���@GE��?��w�����Ԋ������������|*�2`������u5f�Ea�p_�����oyu���"!KPT���^EE���7L����q}�R�.�??TV 433�����˶�?�>PdKMrxvFFL�����貚�#$#���hfl���˵u���,85������W\_���o?O 8���]]]�Fefg?ï¿½ï¿½é¤§ï ª,,.^e_�
+?�A�����̳��F+?@=>��J?0�5�?Y�UV�N�Et>Ey5IpR?��1$+������h)������!�,,�?�H��C5P�)�4�{4�G��ŋ-���R5w�2V|2Q�Ɍm��#*T��$Ŝ�褦�6� ��줓'`�����-Z\p!A��5FHE"�9��������@��&|�Q�„ )l���F� �2rk 1n���(A?+�bӘ9$a��gd�":�Dr���!�,t`����v�ȷ�b�o�F�4��(�<�� '8z��_�B� ����ѯ]���{��I)t
+����%��\tb�G?�����\��#@EB�oQ������EE?]�
+6p�B
+K���!�wN=�����X�$ZH�? �EV��\DS�5� ��(�G8��C?Hlg�3�?����U(�@h�3@�L`�T�H/5tS:�S@rx?1�
+A�$e1�
+��PB��p��<��1��?)��3�?�sTı6��Yn�?l ��A?�<pG!æˆ ï¿½ï¿½Ä³ï¿½1���?h���Bc�Bg�N�R?Ñ€W�aL?D?D'����="@�M:��PD?=T��!PP�?UP$�J��`Ei�@%S(Q)�XÒŠ*���G ���RL�?]�hIe$x�9�P�=��6�r�=pѨ
+r�$"��`?� lQ�P�@% pF(̈�
+_���P����C��6
+9lca�B!�`h�C?t�In���&
+0H�vH�A1,\`�uT�[�P�_?��s�����n���V�6|��1.QFw��D?L�u0���d�K#�t0q�+|�Erx`''��Ȱ!SFtn� o\���@DB�BH3L3CA�?P;
diff --git a/src/java/org/apache/fop/render/awt/viewer/images/logo_big.jpg b/src/java/org/apache/fop/render/awt/viewer/images/logo_big.jpg new file mode 100644 index 000000000..f52c79376 --- /dev/null +++ b/src/java/org/apache/fop/render/awt/viewer/images/logo_big.jpg @@ -0,0 +1,126 @@ +����JFIFHH���ExifMM*bj(1r2��i��HHAdobe Photoshop 7.02005:03:18 22:30:26����x�A(&�HH����JFIFHH��Adobe_CM��Adobed����
+
+
+
+��Ax"����?
+
+3!1AQa"q?2���B#$R�b34r��C%�S���cs5���&D�TdE£t6�U�e���u��F'�������������Vfv��������7GWgw��������5!1AQaq"2?���B#�R��3$b�r��CScs4�%���&5��D�T�dEU6te����u��F�������������Vfv��������'7GWgw�������?�\?��98��jd�M��?�?�7��Z���Vfw\��t!�c}GӉ궩ۻc���.C�r��[GB��7W6�w��;hIO�~������m���f���O����?�72[����?�BlO��?�z5���U�����#����)�f���O���_�zw�ŧ��o�EX��s�X���^�,Ϳ�ɉ�?�k]��RS��7��Z���R�ӿ�-?���+ή��j��t��h?F��v�>����6��{�����Wq��rJ}'�oN�����m�Ȫ����v;�sjǦ��s��O���r���I��t�~D{Lײַ�{YkY�VZ�~��z�]���z���ѫ����ɥ�ٹl��*2�����s��Ǻ��uC���!�-������m�ߧ�m.��oN�����m�Ȭo��:������o�=R�%��
+��k���p�7�8�܌��1��p.ql��?�Q℣�e###�"Ǜ�L��$�y��f���O���_�zw�ŧ��o�Eq���pq�[.<�?����p��?)��#+{�y?����������\�7?F5�[dM��I
+��Ӻ�Ռ�ޛso�~-���>��?i�1�$��������
+����?.;�MQ^GZ��%�]�+]���OC����K?�_����ѕ����A�?����qq]��g��?�]??L��)�Ͷ��KY�n?ٔ��?�뻺ٰ]��D��~�N���j��Rz�o�9�.q�m��G�ʻw����}uͷ;�@'p��Y�����u\]٦���f6��Ɔ��2˲2�6����\Ous �j�-lnp�2�����q-
+ǀ#�/%�T�0Y&y']w��H"#��\�/��'�8Ϫ�l�?.(ZL]�S��no��4|�uN:o���>�u�>��`��m-xs�F����cOѷa��A_�} \�f���e����bzUb�G��� �
+"����Zl6{���y����1q|���/�}c���S/����sx ���S����c�?����˶��_?�.��u���%��W�eV�q�S�o����e���O�����4�U��z�Kqm�{�}o��ښì¦Æ¹ï¿½ï¿½;�q?�+���t���P�����{�g�
+�ޒ�=��O"��N�|��?糰}ls�g�ؒ��-�.E�u~���c��R��u�f�o�]_M$�������Ș��T�碼��/զ}b���u��i��o�CI;��v���^���?��Ž��K?�����N�ϴ$�M���0�z���h�;�^��}��]m,{=+Z�������%骗V��GO���iIO��c��$�@2I?
+Һ\��99y+���j�fP��0
+�o��uo���uk��̶4}V
+��O�5%9Ù88F�4���6A??��Y��_��ֵ�u�A�4�WAe�]]�����1�6Q�G0������Y��^�9�'�u>�U��ǵ�.��xpi{Y�������� p�@o>�
+��q��\BG�<��)���K�S��k!�k�˿=q�
+�U5��!����t��~O�8�վ��ޯ��pe����S�9cY�l?� q_:�3�qXƖE_h��%��5��ձ5�)Jr2��H��^��]���&s?8ǜWJ�z�?��d�����A�?`3f��?������Ѿ�bc\6�i��i�:ӿi��[�����|o�;o�?Ik۞��4��o�a:ok?�r���-:�Z��Z:��g�#O�w�l���zpcG)$�7��Y��©�cՉsY[�7��u����[����IO������W�xۄ��?.+�Lٷ�]���K��;?�W�zf5v:赮o�\Ƈ5.?�3��K�׋�]y{K=V�N�F��rJz�H�:I)�߯�U�~^U�b5��< uoh���˯����??i��Q��p6?���h�uu+��]��q�ʻ"���R����Z?�׈��w�c�=Ӳ��wS`�J�����`b�3,T��i�ݨ��ݻ��^��I?�BgUˢ��eO����-�����~�z�.?��j��,k�LK?﫸��-2�:]o�mulq�N0{�C]����w�$���?��S�f;1:uUf��O�)m.%��O��m�������;�'���]@u��L-�?֫��󹯵��Cs�/�R�7�^?�,�ŬZ�,#{��r��]hh?�INO�c�O���x?�{c��
+��g��Y����=W����hݰ̇y�.��/�S2݋[�*x��e�ӹ������$�IM��"u�+w�{zIu����[����IO��˧���?"��S�/;I%>���S�i�?���DIy�I)�D�?���DIy�I)���]���R\
+I)����zPhotoshop 3.08BIM%8BIM�HH8BIM&?�8BIM
+8BIM8BIM� 8BIM
+8BIM'
+8BIM�H/fflff/ff���2Z5-8BIM�p��������������������������������������������������������������������������������������������8BIM8BIM8BIM@@8BIM8BIMEAxlogo_bigxAnullboundsObjcRct1Top longLeftlongBtomlongARghtlongxslicesVlLsObjcslicesliceIDlonggroupIDlongoriginenumESliceOrigin
+autoGeneratedTypeenum
+ESliceTypeImg boundsObjcRct1Top longLeftlongBtomlongARghtlongxurlTEXTnullTEXTMsgeTEXTaltTagTEXTcellTextIsHTMLboolcellTextTEXT horzAlignenumESliceHorzAligndefault vertAlignenumESliceVertAligndefaultbgColorTypeenumESliceBGColorTypeNone topOutsetlong
+leftOutsetlongbottomOutsetlongrightOutsetlong8BIM8BIM8BIM�xAh[h�����JFIFHH��Adobe_CM��Adobed����
+
+
+
+��Ax"����?
+
+3!1AQa"q?2���B#$R�b34r��C%�S���cs5���&D�TdE£t6�U�e���u��F'�������������Vfv��������7GWgw��������5!1AQaq"2?���B#�R��3$b�r��CScs4�%���&5��D�T�dEU6te����u��F�������������Vfv��������'7GWgw�������?�\?��98��jd�M��?�?�7��Z���Vfw\��t!�c}GӉ궩ۻc���.C�r��[GB��7W6�w��;hIO�~������m���f���O����?�72[����?�BlO��?�z5���U�����#����)�f���O���_�zw�ŧ��o�EX��s�X���^�,Ϳ�ɉ�?�k]��RS��7��Z���R�ӿ�-?���+ή��j��t��h?F��v�>����6��{�����Wq��rJ}'�oN�����m�Ȫ����v;�sjǦ��s��O���r���I��t�~D{Lײַ�{YkY�VZ�~��z�]���z���ѫ����ɥ�ٹl��*2�����s��Ǻ��uC���!�-������m�ߧ�m.��oN�����m�Ȭo��:������o�=R�%��
+��k���p�7�8�܌��1��p.ql��?�Q℣�e###�"Ǜ�L��$�y��f���O���_�zw�ŧ��o�Eq���pq�[.<�?����p��?)��#+{�y?����������\�7?F5�[dM��I
+��Ӻ�Ռ�ޛso�~-���>��?i�1�$��������
+����?.;�MQ^GZ��%�]�+]���OC����K?�_����ѕ����A�?����qq]��g��?�]??L��)�Ͷ��KY�n?ٔ��?�뻺ٰ]��D��~�N���j��Rz�o�9�.q�m��G�ʻw����}uͷ;�@'p��Y�����u\]٦���f6��Ɔ��2˲2�6����\Ous �j�-lnp�2�����q-
+ǀ#�/%�T�0Y&y']w��H"#��\�/��'�8Ϫ�l�?.(ZL]�S��no��4|�uN:o���>�u�>��`��m-xs�F����cOѷa��A_�} \�f���e����bzUb�G��� �
+"����Zl6{���y����1q|���/�}c���S/����sx ���S����c�?����˶��_?�.��u���%��W�eV�q�S�o����e���O�����4�U��z�Kqm�{�}o��ښì¦Æ¹ï¿½ï¿½;�q?�+���t���P�����{�g�
+�ޒ�=��O"��N�|��?糰}ls�g�ؒ��-�.E�u~���c��R��u�f�o�]_M$�������Ș��T�碼��/զ}b���u��i��o�CI;��v���^���?��Ž��K?�����N�ϴ$�M���0�z���h�;�^��}��]m,{=+Z�������%骗V��GO���iIO��c��$�@2I?
+Һ\��99y+���j�fP��0
+�o��uo���uk��̶4}V
+��O�5%9Ù88F�4���6A??��Y��_��ֵ�u�A�4�WAe�]]�����1�6Q�G0������Y��^�9�'�u>�U��ǵ�.��xpi{Y�������� p�@o>�
+��q��\BG�<��)���K�S��k!�k�˿=q�
+�U5��!����t��~O�8�վ��ޯ��pe����S�9cY�l?� q_:�3�qXƖE_h��%��5��ձ5�)Jr2��H��^��]���&s?8ǜWJ�z�?��d�����A�?`3f��?������Ѿ�bc\6�i��i�:ӿi��[�����|o�;o�?Ik۞��4��o�a:ok?�r���-:�Z��Z:��g�#O�w�l���zpcG)$�7��Y��©�cՉsY[�7��u����[����IO������W�xۄ��?.+�Lٷ�]���K��;?�W�zf5v:赮o�\Ƈ5.?�3��K�׋�]y{K=V�N�F��rJz�H�:I)�߯�U�~^U�b5��< uoh���˯����??i��Q��p6?���h�uu+��]��q�ʻ"���R����Z?�׈��w�c�=Ӳ��wS`�J�����`b�3,T��i�ݨ��ݻ��^��I?�BgUˢ��eO����-�����~�z�.?��j��,k�LK?﫸��-2�:]o�mulq�N0{�C]����w�$���?��S�f;1:uUf��O�)m.%��O��m�������;�'���]@u��L-�?֫��󹯵��Cs�/�R�7�^?�,�ŬZ�,#{��r��]hh?�INO�c�O���x?�{c��
+��g��Y����=W����hݰ̇y�.��/�S2݋[�*x��e�ӹ������$�IM��"u�+w�{zIu����[����IO��˧���?"��S�/;I%>���S�i�?���DIy�I)�D�?���DIy�I)���]���R\
+I)��8BIM!UAdobe PhotoshopAdobe Photoshop 7.08BIM��Hhttp://ns.adobe.com/xap/1.0/<?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d'?>
+<?adobe-xap-filters esc="CR"?>
+<x:xapmeta xmlns:x='adobe:ns:meta/' x:xaptk='XMP toolkit 2.8.2-33, framework 1.5'>
+<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' xmlns:iX='http://ns.adobe.com/iX/1.0/'>
+
+ <rdf:Description about='uuid:47579067-97f4-11d9-a2dc-e4c74314cde2'
+ xmlns:xapMM='http://ns.adobe.com/xap/1.0/mm/'>
+ <xapMM:DocumentID>adobe:docid:photoshop:47579060-97f4-11d9-a2dc-e4c74314cde2</xapMM:DocumentID>
+ </rdf:Description>
+
+</rdf:RDF>
+</x:xapmeta>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<?xpacket end='w'?>��Adobed@�����Ax�����
+
+ u!"1A2# QBa$3Rq?b�%C���&4r
+��5'�S6��DTsEF7Gc(UVW�����d�t��e�����)8f�u*9:HIJXYZghijvwxyz�������������������������������������������������������m!1"AQ2aqB?#�R�b3 �$��Cr��4%�ScD�&5T6Ed'
+s��Ft����UeuV7��������)�����������(GWf8v��������gw��������HXhx��������9IYiy��������*:JZjz����������?��><tOG��EGFt���O^M<�u�ʖi��h��Ye���K#�,ĒI���Ы�˗ǯ���3���d�?ߺ�^�e�����~���_�?����{������|?L����c��׿�r���>��W�?����^���|z���?�+�G�X��u��\�=χ���#��~�׺��._����������?~��{�/?_���g�E~����u�~�_����'�=鱾<u��Ɵd��u��Օg?��\'��szl��ᜓ� X��[QV#�^?
+9/����M�.^�
+?�7&>\�$�}���U
+���o�0ݰ�{��?Q�nN���Uxn����04yS�jV̮
+���?�}��J�[PPV����U_w�w~��=�<����o-�����y��L�y�͹R�{QJ��T��yW���e�����~���_�?���/z�z��._����������?~��{�/?_���g�E~����u�͟?�?�e�⾃�z�����}��V�u�̦������5=U-D8T����d��20G�u����Ǽ�p�σ1�øp�w���\]��ذ�??����9���,h2�Ú���-Lʿ���^�\����M�5<^�*~���|=1�d�qܟ�ʜn8�����7�GBk*�"����^�A���p�&/���i�i��M|���R�Loϫ�x�����{��S�
+�N���������x���wի���w�۵;�yc6?���:�0g.*
+��ob>��׺�Ic�y�O���^ꞿ�����_�B9�]���;����5~?�:��?wv���3?���J\��B�]��?C�ּ��q�O�#���j�[�'`u�Y�{#�oq�ޢ�R�Õ�cZ:�����\��^����95�[?�������m���5���U~ ����
+m���+���{�a���>���Vu�͟�=��C�����cV6��L�P����;{lo\�-�SE��'�&�t�k����U�������W�}�:�Ϟ">_�0�?;/%���xl?�KG��9^����VW%��FZ��!�Ț�KU�?�����mC��a���!?�ZV����]�����!��
+{k����`�?>�����Pg�[�.�?;�j�=�|og�V�7��tßµY������ܥS�w�5%m8�*LfÔ aJ�ԫ��}/p@W�yv�h���nNO�?>�)_\�\����i��nJ���?��O�&��H�I��� =?�stW,.��>ά޻�hm]��;���nڼ� Nz{�I���66��?���(��%��� �1E�x�;`R?��W��{�{�����
+?�C�w���$7����uhx9s�7>����h����߃������o�~n,��]��������H���L��X��7R�ۇ Z)3[gp�d`*�*����,E�׺�ѵo�-�|�^��lo�?�A����y�����׺�������b���w�7L-Y���<��Ti��g_�A�׿uU:��]���������{�_X|P���͔����ao��U����V}�ߺ�Z��ˆ?�C�/M�����/�}��W�2ʇ��c"�^��z�]�
+\]?~okR�~��|�U��fO��H�������u3��Wt�R�������KY&�lj��R�5��j*�����{7�o�
+��ڻ�7��5��g�՗������u�WM��/|Z��6�dz�“[���/�?e;���?N����xOp����$��w�(�?�?`팵L��&��~:Q�g�U������P�#�:�q�YC��/�5t��
+��iV=��yr��e��s�S�>��Y�?���ޣj�w�����u|��&����ˌ�v��^��f72�����jn`�O�_KRd|��(��rd�j��QT�p?L�O��u��{�l�w�A���/��S��c�o�c~m�6���ܮ���o=��ܶ$�9\Ff����4A?�~�?���t�A/�(���Hi�i�N�ץ��m����?�׺��>|w�Q�KW��O��O�{�=�u�����]�2���g�|?_n^��M�׿����u�gu�����>cmW�ЮDa��d�i��u �{�^�Z��M��^��{���j��UMս���Wn,��ga���]]���ݴ���W�����������ҸO��G=_������o�M�?�O��y�׺��3�e����,����~��}*d�8c��(�?ɘ[���~�����=��6.�z?�?`��8ݻ���cSR6��Ê����a��{�?o�����?v�US6J����=�"7
+E�0��n�������{�_)z�:�웯�>����Ki��{��]����z������~��9����'��d��MMIO�������c1u��ϼ�� ��G��?�G�����8s>��ܼ~���[ߥ�J�Ȣ�[c
+�����WT2/����02rv�\֩��w��nG��!��ۛ߮��o��������i�Yy��~��>����Wu�r�_�J�GW��:}���U?�ͯ����MPh꿋nz��)������=�{��y�
+��U�^���1�}���?���O����%��A��T6�ڽ����LG�:C!Wr**�Z��v�b,mD�¬��������G�^_��'��(�K�c�Wm���s������Ԁ�co�e-)��ߺ�Z��(:yh�J=5M7��'�h������ߺ�_\O~��j��
+S�1��>.g�1��r����z��^�߻�n�6آ���ͽ?�T�W�(<{�^�TO�M������o�������/?�)z?knIԥ.��}��U?]��=���ilj��XC�����{��Ӻ?��dMҿ����?~��hY���+��W{�Cz�ʫ뎔^��?Te�,�V����c�y�~Z1?4y�l�=�u���$�ȟ��_1+?���ζo��ǯ���е���۴?��[#�n.�휖��[K��x�}?�vvO���}��v%em&��
+:�B��3�4���׺�?��̣�����E��@�?4��&ַ�7�Ͽu�Ǵz>J�??�,�緶Z��V����^�Guc�>>��f������{���q���i8f��
+����}��X����a�,ߟ�Y�� >�ru?�>�s��?�<���.�k�����%�K>�z�?���^��~o�?��o�]�?�6�Ug P`h?ʪ����U��d9�v-���:���[^���78}�=�K�Z���������[�|_�Ƕ�n��lݱ��nJ]�����}]%W��q�'�}��}�C���P}��V?GeQîs�����g�������%��4���N�h��m�}��6�3O���Gb���=�*���V?k���O
+l?ȧ�FBx�4�?5kG1����ꮞ��A�{�^�Z�?�ͯ��d�;�v�ɤ�g�?�;�?S�h����������?��u~��f�
+�����"��R���M�?�?��*j�����޶ߵJPx5t�1�ٜy6�Co~��}[� ��7��� �_�^���֑f��f��O���T[�2�I���/M���@ ���{�����:���������Zu���߸?��6�����m��
+#0��dkk�**�UU1,�>�׺�Ը_��R���8Ŭ~!nr?��0<�_~��k;��w���.���;���㽺;� ���{����u�g�=�����v�@KU[�j�#���ǿu�C��c��}��+:�p�Ӆ���?�+K��?���!��U&H��)��׺�>��
+�����#�w�>ߛGoc��z?�C��n#�7jmϳ��d(3��������np���ׇnomٞ鿎;#p��=Vq{��,gvndRm�������@W'��L
+�����'��:4_�%m����*~��E��W�>;�v��Y,�q�|������~Cr���^a�??�>��F�����n?�4�w�;����G�S�=���?�g��`���wk�q-:�!��}!���?�6~s����k����{;��?b?�?���?Ŀa��nm����UUUׯ6��Ou����_���=���jp�մ���E_�U�=�����vv_�2[OdP��W{�^�u�7o�-�窷�;�Gd�ʯ���ت��Y��v�e�-��L�c^6�\���{�^�L��9$��sѲo!��ܗ$M��B��{�^���v>?�A��ߺ�N��׺+_9��a�|���M�}�u�յ_�G���k� |�>o:�7���Q��ߺ�Z��4s�¿��`b�r�@������C���~��}G��uH�X�_�r���ln=�u�����W;1�? �_s���ie�'��)>�;�{�k�i�n-�H5�����]U(����>�׺��|��z�b|z��U�ڹ����{�,sج�q�aq�mŻ��s��?��k��{�^��ttw'ǎ��wOR��7aŀ�����Χ�p���(�����+�6}�}�VR���=�u�����7�e������꾮��w�Rv��{��+�T�X���쌾��m����ͩWM���u��}��u�S���2���_��N|d��_�G��^��+=e��-ٸr{ct�;��˧{�}���e�>�IP6eUNp�րO�r}�tL���o� 1��o�m��+c�n��N��-�D�üw�|�#soݶD'j�v U&.ZUl�T_�?>��{�����񀨩�wzm�{��������[�^�x��?���,�Ŗ�`iM�S7�����FOroeo�08�~��}?=�u�~������D�0��V�A�ݾ�׺�����~m��z7m�\��zKg�3���\�=���Y�EW�z�WQ��׺��O�h�Y�3z/ouOEl-��+��mx�n���Vv�tP��f��+��?�S?�ߺ�V���{�{�^�_��R�����۰���Pv�uo���~���m���o-�C�py���b�����8�Y�))[H<���ݲ��K׺�o�O��󻮊�}�|�ڿ�*'�p||��P���5�<��oj>��׫н���fM���i��0��j���?���Lx�+7{�}��/�N�����W�N��;=����~��U�g�ߣ�7��ٙZ�?�+n^���n;��KRc��TV�1���t�k�~|2�c�G^t_��<`cE�*q5��xQ9ZMݿqg(~��b/�G�ߺ�W?GGOC�����a��~��?��b�!�sl#�l©k�P�U9�����uT_�>�>?v���|�B��w�6&��v���Uo�|�#}��5���xq���U)jR�����u�׺�u���_�"�_�_ ���n�~����!{7�=
+�����u���׺R{�^���׺�u���{�{�^넟������?~��{ߺ�^��׽�u�~��{ߺ�^���{۟�*{;�����o%��{���
|