--- /dev/null
+/*
+ * 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;
+
+import java.awt.Color;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.util.Iterator;
+import java.util.List;
+
+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.RegionViewport;
+import org.apache.fop.area.Trait;
+import org.apache.fop.area.inline.Viewport;
+import org.apache.fop.datatypes.ColorType;
+import org.apache.fop.image.FopImage;
+import org.apache.fop.pdf.PDFState;
+import org.apache.fop.render.pdf.CTMHelper;
+import org.apache.fop.traits.BorderProps;
+
+/**
+ * Abstract base class for renderers like PDF and PostScript where many painting operations
+ * follow similar patterns which makes it possible to share some code.
+ */
+public abstract class AbstractPathOrientedRenderer extends PrintRenderer {
+
+ /**
+ * Converts a ColorType to a java.awt.Color (sRGB).
+ * @param col the color
+ * @return the converted color
+ */
+ protected Color toColor(ColorType col) {
+ return new Color(col.getRed(), col.getGreen(), col.getBlue());
+ }
+
+ /**
+ * 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) {
+ 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;
+
+ /* using start-indent now
+ Integer spaceStart = (Integer) block.getTrait(Trait.SPACE_START);
+ if (spaceStart != null) {
+ startx += spaceStart.floatValue() / 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);
+ }
+
+ /**
+ * Handle the traits for a region
+ * This is used to draw the traits for the given page region.
+ * (See Sect. 6.4.1.2 of XSL-FO spec.)
+ * @param region the RegionViewport whose region is to be drawn
+ */
+ protected void handleRegionTraits(RegionViewport region) {
+ Rectangle2D viewArea = region.getViewArea();
+ float startx = (float)(viewArea.getX() / 1000f);
+ float starty = (float)(viewArea.getY() / 1000f);
+ float width = (float)(viewArea.getWidth() / 1000f);
+ float height = (float)(viewArea.getHeight() / 1000f);
+
+ if (region.getRegionReference().getRegionClass() == FO_REGION_BODY) {
+ currentBPPosition = region.getBorderAndPaddingWidthBefore();
+ currentIPPosition = region.getBorderAndPaddingWidthStart();
+ }
+ drawBackAndBorders(region, startx, starty, width, height);
+ }
+
+
+ /**
+ * Draw the background and borders.
+ * This draws the background and border traits for an area given
+ * the position.
+ *
+ * @param area the area to get the traits from
+ * @param startx the start x position
+ * @param starty the start y position
+ * @param width the width of the area
+ * @param height the height of the area
+ */
+ protected void drawBackAndBorders(Area area,
+ float startx, float starty,
+ float width, float height) {
+ // draw background then border
+
+ 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);
+
+ Trait.Background back;
+ back = (Trait.Background)area.getTrait(Trait.BACKGROUND);
+ if (back != null) {
+ endTextObject();
+
+ //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) {
+ updateColor(back.getColor(), true);
+ fillRect(sx, sy, paddRectWidth, paddRectHeight);
+ }
+ if (back.getFopImage() != null) {
+ FopImage fopimage = back.getFopImage();
+ if (fopimage != null && fopimage.load(FopImage.DIMENSIONS)) {
+ saveGraphicsState();
+ clipRect(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());
+ drawImage(back.getURL(), pos);
+ }
+ }
+
+ restoreGraphicsState();
+ } else {
+ log.warn("Can't find background image: " + back.getURL());
+ }
+ }
+ }
+
+ boolean[] b = new boolean[] {
+ (bpsBefore != null), (bpsEnd != null),
+ (bpsAfter != null), (bpsStart != null)};
+ if (!b[0] && !b[1] && !b[2] && !b[3]) {
+ return;
+ }
+ float[] bw = new float[] {
+ (b[0] ? bpsBefore.width / 1000f : 0.0f),
+ (b[1] ? bpsEnd.width / 1000f : 0.0f),
+ (b[2] ? bpsAfter.width / 1000f : 0.0f),
+ (b[3] ? bpsStart.width / 1000f : 0.0f)};
+ float[] clipw = new float[] {
+ BorderProps.getClippedWidth(bpsBefore) / 1000f,
+ BorderProps.getClippedWidth(bpsEnd) / 1000f,
+ BorderProps.getClippedWidth(bpsAfter) / 1000f,
+ BorderProps.getClippedWidth(bpsStart) / 1000f};
+ starty += clipw[0];
+ height -= clipw[0];
+ height -= clipw[2];
+ startx += clipw[3];
+ width -= clipw[3];
+ width -= clipw[1];
+
+ boolean[] slant = new boolean[] {
+ (b[3] && b[0]), (b[0] && b[1]), (b[1] && b[2]), (b[2] && b[3])};
+ if (bpsBefore != null) {
+ endTextObject();
+
+ float sx1 = startx;
+ float sx2 = (slant[0] ? sx1 + bw[3] - clipw[3] : sx1);
+ float ex1 = startx + width;
+ float ex2 = (slant[1] ? ex1 - bw[1] + clipw[1] : ex1);
+ float outery = starty - clipw[0];
+ float clipy = outery + clipw[0];
+ float innery = outery + bw[0];
+
+ saveGraphicsState();
+ moveTo(sx1, clipy);
+ float sx1a = sx1;
+ float ex1a = ex1;
+ if (bpsBefore.mode == BorderProps.COLLAPSE_OUTER) {
+ if (bpsStart != null && bpsStart.mode == BorderProps.COLLAPSE_OUTER) {
+ sx1a -= clipw[3];
+ }
+ if (bpsEnd != null && bpsEnd.mode == BorderProps.COLLAPSE_OUTER) {
+ ex1a += clipw[1];
+ }
+ lineTo(sx1a, outery);
+ lineTo(ex1a, outery);
+ }
+ lineTo(ex1, clipy);
+ lineTo(ex2, innery);
+ lineTo(sx2, innery);
+ closePath();
+ clip();
+ drawBorderLine(sx1a, outery, ex1a, innery, true, true,
+ bpsBefore.style, bpsBefore.color);
+ restoreGraphicsState();
+ }
+ if (bpsEnd != null) {
+ endTextObject();
+
+ float sy1 = starty;
+ float sy2 = (slant[1] ? sy1 + bw[0] - clipw[0] : sy1);
+ float ey1 = starty + height;
+ float ey2 = (slant[2] ? ey1 - bw[2] + clipw[2] : ey1);
+ float outerx = startx + width + clipw[1];
+ float clipx = outerx - clipw[1];
+ float innerx = outerx - bw[1];
+
+ saveGraphicsState();
+ moveTo(clipx, sy1);
+ float sy1a = sy1;
+ float ey1a = ey1;
+ if (bpsEnd.mode == BorderProps.COLLAPSE_OUTER) {
+ if (bpsBefore != null && bpsBefore.mode == BorderProps.COLLAPSE_OUTER) {
+ sy1a -= clipw[0];
+ }
+ if (bpsAfter != null && bpsAfter.mode == BorderProps.COLLAPSE_OUTER) {
+ ey1a += clipw[2];
+ }
+ lineTo(outerx, sy1a);
+ lineTo(outerx, ey1a);
+ }
+ lineTo(clipx, ey1);
+ lineTo(innerx, ey2);
+ lineTo(innerx, sy2);
+ closePath();
+ clip();
+ drawBorderLine(innerx, sy1a, outerx, ey1a, false, false, bpsEnd.style, bpsEnd.color);
+ restoreGraphicsState();
+ }
+ if (bpsAfter != null) {
+ endTextObject();
+
+ float sx1 = startx;
+ float sx2 = (slant[3] ? sx1 + bw[3] - clipw[3] : sx1);
+ float ex1 = startx + width;
+ float ex2 = (slant[2] ? ex1 - bw[1] + clipw[1] : ex1);
+ float outery = starty + height + clipw[2];
+ float clipy = outery - clipw[2];
+ float innery = outery - bw[2];
+
+ saveGraphicsState();
+ moveTo(ex1, clipy);
+ float sx1a = sx1;
+ float ex1a = ex1;
+ if (bpsAfter.mode == BorderProps.COLLAPSE_OUTER) {
+ if (bpsStart != null && bpsStart.mode == BorderProps.COLLAPSE_OUTER) {
+ sx1a -= clipw[3];
+ }
+ if (bpsEnd != null && bpsEnd.mode == BorderProps.COLLAPSE_OUTER) {
+ ex1a += clipw[1];
+ }
+ lineTo(ex1a, outery);
+ lineTo(sx1a, outery);
+ }
+ lineTo(sx1, clipy);
+ lineTo(sx2, innery);
+ lineTo(ex2, innery);
+ closePath();
+ clip();
+ drawBorderLine(sx1a, innery, ex1a, outery, true, false, bpsAfter.style, bpsAfter.color);
+ restoreGraphicsState();
+ }
+ if (bpsStart != null) {
+ endTextObject();
+
+ float sy1 = starty;
+ float sy2 = (slant[0] ? sy1 + bw[0] - clipw[0] : sy1);
+ float ey1 = sy1 + height;
+ float ey2 = (slant[3] ? ey1 - bw[2] + clipw[2] : ey1);
+ float outerx = startx - clipw[3];
+ float clipx = outerx + clipw[3];
+ float innerx = outerx + bw[3];
+
+ saveGraphicsState();
+ moveTo(clipx, ey1);
+ float sy1a = sy1;
+ float ey1a = ey1;
+ if (bpsStart.mode == BorderProps.COLLAPSE_OUTER) {
+ if (bpsBefore != null && bpsBefore.mode == BorderProps.COLLAPSE_OUTER) {
+ sy1a -= clipw[0];
+ }
+ if (bpsAfter != null && bpsAfter.mode == BorderProps.COLLAPSE_OUTER) {
+ ey1a += clipw[2];
+ }
+ lineTo(outerx, ey1a);
+ lineTo(outerx, sy1a);
+ }
+ lineTo(clipx, sy1);
+ lineTo(innerx, sy2);
+ lineTo(innerx, ey2);
+ closePath();
+ clip();
+ drawBorderLine(outerx, sy1a, innerx, ey1a, false, true, bpsStart.style, bpsStart.color);
+ restoreGraphicsState();
+ }
+ }
+
+ /**
+ * @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;
+ //String saveFontName = currentFontName;
+
+ 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) {
+
+ //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) {
+ breakOutList = breakOutOfStateStack();
+ }
+
+ 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()) {
+ saveGraphicsState();
+ clipRect(x, y, width, height);
+ }
+
+ startVParea(ctm);
+
+ currentIPPosition = 0;
+ currentBPPosition = 0;
+
+ renderBlocks(bv, children);
+ endVParea();
+
+ if (bv.getClip()) {
+ restoreGraphicsState();
+ }
+
+ // clip if necessary
+
+ if (breakOutList != null) {
+ restoreStateStackAfterBreakOut(breakOutList);
+ }
+
+ currentIPPosition = saveIP;
+ currentBPPosition = saveBP;
+ } else {
+
+ 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);
+ ctm = tempctm.multiply(ctm);
+
+ //Now adjust for border/padding
+ x += borderPaddingStart / 1000f;
+ y += borderPaddingBefore / 1000f;
+
+ // clip if necessary
+ if (bv.getClip()) {
+ saveGraphicsState();
+ float width = (float)bv.getIPD() / 1000f;
+ float height = (float)bv.getBPD() / 1000f;
+ clipRect(x, y, width, height);
+ }
+
+ if (ctm != null) {
+ startVParea(ctm);
+ currentIPPosition = 0;
+ currentBPPosition = 0;
+ }
+ renderBlocks(bv, children);
+ if (ctm != null) {
+ endVParea();
+ }
+
+ if (bv.getClip()) {
+ restoreGraphicsState();
+ }
+
+ 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();
+ }
+ }
+ //currentFontName = saveFontName;
+ }
+
+ /**
+ * Render an inline viewport.
+ * This renders an inline viewport by clipping if necessary.
+ * @param viewport the viewport to handle
+ */
+ public void renderViewport(Viewport viewport) {
+
+ float x = currentIPPosition / 1000f;
+ float y = (currentBPPosition + viewport.getOffset()) / 1000f;
+ float width = viewport.getIPD() / 1000f;
+ float height = viewport.getBPD() / 1000f;
+ // TODO: Calculate the border rect correctly.
+ float borderPaddingStart = viewport.getBorderAndPaddingWidthStart() / 1000f;
+ float borderPaddingBefore = viewport.getBorderAndPaddingWidthBefore() / 1000f;
+ float bpwidth = borderPaddingStart
+ + (viewport.getBorderAndPaddingWidthEnd() / 1000f);
+ float bpheight = borderPaddingBefore
+ + (viewport.getBorderAndPaddingWidthAfter() / 1000f);
+
+ drawBackAndBorders(viewport, x, y, width + bpwidth, height + bpheight);
+
+ if (viewport.getClip()) {
+ saveGraphicsState();
+
+ clipRect(x + borderPaddingStart, y + borderPaddingBefore, width, height);
+ }
+ super.renderViewport(viewport);
+
+ if (viewport.getClip()) {
+ restoreGraphicsState();
+ }
+ }
+
+ /**
+ * Restores the state stack after a break out.
+ * @param breakOutList the state stack to restore.
+ */
+ protected abstract void restoreStateStackAfterBreakOut(List breakOutList);
+
+ /**
+ * Breaks out of the state stack to handle fixed block-containers.
+ * @return the saved state stack to recreate later
+ */
+ protected abstract List breakOutOfStateStack();
+
+ /** Saves the graphics state of the rendering engine. */
+ protected abstract void saveGraphicsState();
+
+ /** Restores the last graphics state of the rendering engine. */
+ protected abstract void restoreGraphicsState();
+
+ /** Indicates the beginning of a text object. */
+ protected abstract void beginTextObject();
+
+ /** Indicates the end of a text object. */
+ protected abstract void endTextObject();
+
+ /** Clip using the current path. */
+ protected abstract void clip();
+
+ /**
+ * Clip using a rectangular area.
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param width the width of the rectangle
+ * @param height the height of the rectangle
+ */
+ protected abstract void clipRect(float x, float y, float width, float height);
+
+ /**
+ * Moves the current point to (x, y), omitting any connecting line segment.
+ * @param x x coordinate
+ * @param y y coordinate
+ */
+ protected abstract void moveTo(float x, float y);
+
+ /**
+ * Appends a straight line segment from the current point to (x, y). The
+ * new current point is (x, y).
+ * @param x x coordinate
+ * @param y y coordinate
+ */
+ protected abstract void lineTo(float x, float y);
+
+ /**
+ * Closes the current subpath by appending a straight line segment from
+ * the current point to the starting point of the subpath.
+ */
+ protected abstract void closePath();
+
+ /**
+ * Fill a rectangular area.
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @param width the width of the rectangle
+ * @param height the height of the rectangle
+ */
+ protected abstract void fillRect(float x, float y, float width, float height);
+
+ /**
+ * 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
+ */
+ protected abstract void updateColor(ColorType col, boolean fill);
+
+ /**
+ * Draw an image at the indicated location.
+ * @param url the URI/URL of the image
+ * @param pos the position of the image
+ */
+ protected abstract void drawImage(String url, Rectangle2D pos);
+
+ /**
+ * Draw a border segment of an XSL-FO style border.
+ * @param x1 starting x coordinate
+ * @param y1 starting y coordinate
+ * @param x2 ending x coordinate
+ * @param y2 ending y coordinate
+ * @param horz true for horizontal border segments, false for vertical border segments
+ * @param startOrBefore true for border segments on the start or before edge,
+ * false for end or after.
+ * @param style the border style (one of Constants.EN_DASHED etc.)
+ * @param col the color for the border segment
+ */
+ protected abstract void drawBorderLine(float x1, float y1, float x2, float y2,
+ boolean horz, boolean startOrBefore, int style, ColorType col);
+
+}
package org.apache.fop.render;
// FOP
+import org.apache.fop.area.Area;
+import org.apache.fop.area.Trait;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontSetup;
+import org.apache.fop.image.FopImage;
+import org.apache.fop.traits.BorderProps;
// Java
+import java.awt.Color;
+import java.awt.geom.Rectangle2D;
import java.util.List;
/** Abstract base class of "Print" type renderers. */
FontSetup.setup(fontInfo, fontList);
}
+ /**
+ * Lightens up a color for groove, ridge, inset and outset border effects.
+ * @param col the color to lighten up
+ * @param factor factor by which to lighten up (negative values darken the color)
+ * @return the modified color
+ */
+ protected Color lightenColor(Color col, float factor) {
+ float[] cols = new float[3];
+ cols = col.getColorComponents(cols);
+ if (factor > 0) {
+ cols[0] += (1.0 - cols[0]) * factor;
+ cols[1] += (1.0 - cols[1]) * factor;
+ cols[2] += (1.0 - cols[2]) * factor;
+ } else {
+ cols[0] -= cols[0] * -factor;
+ cols[1] -= cols[1] * -factor;
+ cols[2] -= cols[2] * -factor;
+ }
+ return new Color(cols[0], cols[1], cols[2]);
+ }
+
}
import org.apache.fop.pdf.PDFStream;
import org.apache.fop.pdf.PDFText;
import org.apache.fop.pdf.PDFXObject;
+import org.apache.fop.render.AbstractPathOrientedRenderer;
import org.apache.fop.render.PrintRenderer;
import org.apache.fop.render.RendererContext;
import org.apache.fop.traits.BorderProps;
* Renderer that renders areas to PDF
*
*/
-public class PDFRenderer extends PrintRenderer {
+public class PDFRenderer extends AbstractPathOrientedRenderer {
/**
* The mime type for pdf
*/
protected void handleRegionTraits(RegionViewport region) {
currentFontName = "";
- Rectangle2D viewArea = region.getViewArea();
- float startx = (float)(viewArea.getX() / 1000f);
- float starty = (float)(viewArea.getY() / 1000f);
- float width = (float)(viewArea.getWidth() / 1000f);
- float height = (float)(viewArea.getHeight() / 1000f);
-
- if (region.getRegionReference().getRegionClass() == FO_REGION_BODY) {
- currentBPPosition = region.getBorderAndPaddingWidthBefore();
- currentIPPosition = region.getBorderAndPaddingWidthStart();
- }
- drawBackAndBorders(region, startx, starty, width, height);
- }
-
- /**
- * 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) {
- 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;
-
- /* using start-indent now
- Integer spaceStart = (Integer) block.getTrait(Trait.SPACE_START);
- if (spaceStart != null) {
- startx += spaceStart.floatValue() / 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);
- }
-
- /**
- * Draw the background and borders.
- * This draws the background and border traits for an area given
- * the position.
- *
- * @param area the area to get the traits from
- * @param startx the start x position
- * @param starty the start y position
- * @param width the width of the area
- * @param height the height of the area
- */
- protected void drawBackAndBorders(Area area,
- float startx, float starty,
- float width, float height) {
- // draw background then border
-
- 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);
-
- Trait.Background back;
- back = (Trait.Background)area.getTrait(Trait.BACKGROUND);
- if (back != null) {
- endTextObject();
-
- //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) {
- updateColor(back.getColor(), true, null);
- currentStream.add(sx + " " + sy + " "
- + paddRectWidth + " " + paddRectHeight + " re\n");
- currentStream.add("f\n");
- }
- if (back.getFopImage() != null) {
- FopImage fopimage = back.getFopImage();
- if (fopimage != null && fopimage.load(FopImage.DIMENSIONS)) {
- saveGraphicsState();
- 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);
- }
- }
-
- restoreGraphicsState();
- } else {
- log.warn("Can't find background image: " + back.getURL());
- }
- }
- }
-
- boolean[] b = new boolean[] {
- (bpsBefore != null), (bpsEnd != null),
- (bpsAfter != null), (bpsStart != null)};
- if (!b[0] && !b[1] && !b[2] && !b[3]) {
- return;
- }
- float[] bw = new float[] {
- (b[0] ? bpsBefore.width / 1000f : 0.0f),
- (b[1] ? bpsEnd.width / 1000f : 0.0f),
- (b[2] ? bpsAfter.width / 1000f : 0.0f),
- (b[3] ? bpsStart.width / 1000f : 0.0f)};
- float[] clipw = new float[] {
- BorderProps.getClippedWidth(bpsBefore) / 1000f,
- BorderProps.getClippedWidth(bpsEnd) / 1000f,
- BorderProps.getClippedWidth(bpsAfter) / 1000f,
- BorderProps.getClippedWidth(bpsStart) / 1000f};
- starty += clipw[0];
- height -= clipw[0];
- height -= clipw[2];
- startx += clipw[3];
- width -= clipw[3];
- width -= clipw[1];
-
- boolean[] slant = new boolean[] {
- (b[3] && b[0]), (b[0] && b[1]), (b[1] && b[2]), (b[2] && b[3])};
- if (bpsBefore != null) {
- endTextObject();
-
- float sx1 = startx;
- float sx2 = (slant[0] ? sx1 + bw[3] - clipw[3] : sx1);
- float ex1 = startx + width;
- float ex2 = (slant[1] ? ex1 - bw[1] + clipw[1] : ex1);
- float outery = starty - clipw[0];
- float clipy = outery + clipw[0];
- float innery = outery + bw[0];
-
- saveGraphicsState();
- moveTo(sx1, clipy);
- float sx1a = sx1;
- float ex1a = ex1;
- if (bpsBefore.mode == BorderProps.COLLAPSE_OUTER) {
- if (bpsStart != null && bpsStart.mode == BorderProps.COLLAPSE_OUTER) {
- sx1a -= clipw[3];
- }
- if (bpsEnd != null && bpsEnd.mode == BorderProps.COLLAPSE_OUTER) {
- ex1a += clipw[1];
- }
- lineTo(sx1a, outery);
- lineTo(ex1a, outery);
- }
- lineTo(ex1, clipy);
- lineTo(ex2, innery);
- lineTo(sx2, innery);
- closePath();
- clip();
- drawBorderLine(sx1a, outery, ex1a, innery, true, true,
- bpsBefore.style, bpsBefore.color);
- restoreGraphicsState();
- }
- if (bpsEnd != null) {
- endTextObject();
-
- float sy1 = starty;
- float sy2 = (slant[1] ? sy1 + bw[0] - clipw[0] : sy1);
- float ey1 = starty + height;
- float ey2 = (slant[2] ? ey1 - bw[2] + clipw[2] : ey1);
- float outerx = startx + width + clipw[1];
- float clipx = outerx - clipw[1];
- float innerx = outerx - bw[1];
-
- saveGraphicsState();
- moveTo(clipx, sy1);
- float sy1a = sy1;
- float ey1a = ey1;
- if (bpsEnd.mode == BorderProps.COLLAPSE_OUTER) {
- if (bpsBefore != null && bpsBefore.mode == BorderProps.COLLAPSE_OUTER) {
- sy1a -= clipw[0];
- }
- if (bpsAfter != null && bpsAfter.mode == BorderProps.COLLAPSE_OUTER) {
- ey1a += clipw[2];
- }
- lineTo(outerx, sy1a);
- lineTo(outerx, ey1a);
- }
- lineTo(clipx, ey1);
- lineTo(innerx, ey2);
- lineTo(innerx, sy2);
- closePath();
- clip();
- drawBorderLine(innerx, sy1a, outerx, ey1a, false, false, bpsEnd.style, bpsEnd.color);
- restoreGraphicsState();
- }
- if (bpsAfter != null) {
- endTextObject();
-
- float sx1 = startx;
- float sx2 = (slant[3] ? sx1 + bw[3] - clipw[3] : sx1);
- float ex1 = startx + width;
- float ex2 = (slant[2] ? ex1 - bw[1] + clipw[1] : ex1);
- float outery = starty + height + clipw[2];
- float clipy = outery - clipw[2];
- float innery = outery - bw[2];
-
- saveGraphicsState();
- moveTo(ex1, clipy);
- float sx1a = sx1;
- float ex1a = ex1;
- if (bpsAfter.mode == BorderProps.COLLAPSE_OUTER) {
- if (bpsStart != null && bpsStart.mode == BorderProps.COLLAPSE_OUTER) {
- sx1a -= clipw[3];
- }
- if (bpsEnd != null && bpsEnd.mode == BorderProps.COLLAPSE_OUTER) {
- ex1a += clipw[1];
- }
- lineTo(ex1a, outery);
- lineTo(sx1a, outery);
- }
- lineTo(sx1, clipy);
- lineTo(sx2, innery);
- lineTo(ex2, innery);
- closePath();
- clip();
- drawBorderLine(sx1a, innery, ex1a, outery, true, false, bpsAfter.style, bpsAfter.color);
- restoreGraphicsState();
- }
- if (bpsStart != null) {
- endTextObject();
-
- float sy1 = starty;
- float sy2 = (slant[0] ? sy1 + bw[0] - clipw[0] : sy1);
- float ey1 = sy1 + height;
- float ey2 = (slant[3] ? ey1 - bw[2] + clipw[2] : ey1);
- float outerx = startx - clipw[3];
- float clipx = outerx + clipw[3];
- float innerx = outerx + bw[3];
-
- saveGraphicsState();
- moveTo(clipx, ey1);
- float sy1a = sy1;
- float ey1a = ey1;
- if (bpsStart.mode == BorderProps.COLLAPSE_OUTER) {
- if (bpsBefore != null && bpsBefore.mode == BorderProps.COLLAPSE_OUTER) {
- sy1a -= clipw[0];
- }
- if (bpsAfter != null && bpsAfter.mode == BorderProps.COLLAPSE_OUTER) {
- ey1a += clipw[2];
- }
- lineTo(outerx, ey1a);
- lineTo(outerx, sy1a);
- }
- lineTo(clipx, sy1);
- lineTo(innerx, sy2);
- lineTo(innerx, ey2);
- closePath();
- clip();
- drawBorderLine(outerx, sy1a, innerx, ey1a, false, true, bpsStart.style, bpsStart.color);
- restoreGraphicsState();
- }
- }
-
- private Color lightenColor(Color col, float factor) {
- float[] cols = new float[3];
- cols = col.getColorComponents(cols);
- if (factor > 0) {
- cols[0] += (1.0 - cols[0]) * factor;
- cols[1] += (1.0 - cols[1]) * factor;
- cols[2] += (1.0 - cols[2]) * factor;
- } else {
- cols[0] -= cols[0] * -factor;
- cols[1] -= cols[1] * -factor;
- cols[2] -= cols[2] * -factor;
- }
- return new Color(cols[0], cols[1], cols[2]);
+ super.handleRegionTraits(region);
}
- private void drawBorderLine(float x1, float y1, float x2, float y2,
+ /** @see org.apache.fop.render.AbstractPathOrientedRenderer */
+ protected void drawBorderLine(float x1, float y1, float x2, float y2,
boolean horz, boolean startOrBefore, int style, ColorType col) {
float w = x2 - x1;
float h = y2 - y1;
}
}
+ /**
+ * Clip a rectangular 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 clipRect(float x, float y, float width, float height) {
+ currentStream.add(x + " " + y + " " + width + " " + height + " re ");
+ clip();
+ }
+
+ /**
+ * Clip an area.
+ */
+ protected void clip() {
+ currentStream.add("W\n");
+ currentStream.add("n\n");
+ }
+
/**
* Moves the current point to (x, y), omitting any connecting line segment.
* @param x x coordinate
* @param y y coordinate
*/
- private void moveTo(float x, float y) {
+ protected void moveTo(float x, float y) {
currentStream.add(x + " " + y + " m ");
}
* @param x x coordinate
* @param y y coordinate
*/
- private void lineTo(float x, float y) {
+ protected void lineTo(float x, float y) {
currentStream.add(x + " " + y + " l ");
}
* Closes the current subpath by appending a straight line segment from
* the current point to the starting point of the subpath.
*/
- private void closePath() {
+ protected void closePath() {
currentStream.add("h ");
}
+
+ /**
+ * @see org.apache.fop.render.AbstractPathOrientedRenderer#fillRect(float, float, float, float)
+ */
+ protected void fillRect(float x, float y, float w, float h) {
+ currentStream.add(x + " " + y + " " + w + " " + h + " re f\n");
+ }
/**
* Draw a line.
/**
* @see org.apache.fop.render.AbstractRenderer#renderBlockViewport(BlockViewport, List)
- */
+ *//*
protected void renderBlockViewport(BlockViewport bv, List children) {
// clip and position viewport if necessary
//after the block-container has been painted. See below.
List breakOutList = null;
if (bv.getPositioning() == Block.FIXED) {
- //break out
- breakOutList = new java.util.ArrayList();
- PDFState.Data data;
- while (true) {
- data = currentState.getData();
- if (currentState.pop() == null) {
- break;
- }
- if (breakOutList.size() == 0) {
- comment("------ break out!");
- }
- breakOutList.add(0, data); //Insert because of stack-popping
- //getLogger().debug("Adding to break out list: " + data);
- restoreGraphicsState();
- }
+ breakOutList = breakOutOfStateStack();
}
CTM tempctm = new CTM(containingIPPosition, containingBPPosition);
if (bv.getClip()) {
saveGraphicsState();
- clip(x, y, width, height);
+ clipRect(x, y, width, height);
}
startVParea(ctm);
// clip if necessary
if (breakOutList != null) {
- comment("------ restoring context after break-out...");
- PDFState.Data data;
- Iterator i = breakOutList.iterator();
- while (i.hasNext()) {
- data = (PDFState.Data)i.next();
- //getLogger().debug("Restoring: " + data);
- currentState.push();
- saveGraphicsState();
- if (data.concatenations != null) {
- Iterator tr = data.concatenations.iterator();
- while (tr.hasNext()) {
- AffineTransform at = (AffineTransform)tr.next();
- currentState.setTransform(at);
- double[] matrix = new double[6];
- at.getMatrix(matrix);
- tempctm = new CTM(matrix[0], matrix[1], matrix[2], matrix[3],
- matrix[4] * 1000, matrix[5] * 1000);
- currentStream.add(CTMHelper.toPDFString(tempctm) + " cm\n");
- }
- }
- //TODO Break-out: Also restore items such as line width and color
- //Left out for now because all this painting stuff is very
- //inconsistent. Some values go over PDFState, some don't.
- }
- comment("------ done.");
+ restoreStateStackAfterBreakOut(breakOutList);
}
currentIPPosition = saveIP;
saveGraphicsState();
float width = (float)bv.getIPD() / 1000f;
float height = (float)bv.getBPD() / 1000f;
- clip(x, y, width, height);
+ clipRect(x, y, width, height);
}
if (ctm != null) {
}
}
currentFontName = saveFontName;
- }
-
+ }*/
+
/**
- * 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
+ * Breaks out of the state stack to handle fixed block-containers.
+ * @return the saved state stack to recreate later
*/
- protected void clip(float x, float y, float width, float height) {
- currentStream.add(x + " " + y + " " + width + " " + height + " re ");
- clip();
+ protected List breakOutOfStateStack() {
+ List breakOutList = new java.util.ArrayList();
+ PDFState.Data data;
+ while (true) {
+ data = currentState.getData();
+ if (currentState.pop() == null) {
+ break;
+ }
+ if (breakOutList.size() == 0) {
+ comment("------ break out!");
+ }
+ breakOutList.add(0, data); //Insert because of stack-popping
+ restoreGraphicsState();
+ }
+ return breakOutList;
}
/**
- * Clip an area.
+ * Restores the state stack after a break out.
+ * @param breakOutList the state stack to restore.
*/
- protected void clip() {
- currentStream.add("W\n");
- currentStream.add("n\n");
+ protected void restoreStateStackAfterBreakOut(List breakOutList) {
+ CTM tempctm;
+ comment("------ restoring context after break-out...");
+ PDFState.Data data;
+ Iterator i = breakOutList.iterator();
+ while (i.hasNext()) {
+ data = (PDFState.Data)i.next();
+ currentState.push();
+ saveGraphicsState();
+ if (data.concatenations != null) {
+ Iterator tr = data.concatenations.iterator();
+ while (tr.hasNext()) {
+ AffineTransform at = (AffineTransform)tr.next();
+ currentState.setTransform(at);
+ double[] matrix = new double[6];
+ at.getMatrix(matrix);
+ tempctm = new CTM(matrix[0], matrix[1], matrix[2], matrix[3],
+ matrix[4] * 1000, matrix[5] * 1000);
+ currentStream.add(CTMHelper.toPDFString(tempctm) + " cm\n");
+ }
+ }
+ //TODO Break-out: Also restore items such as line width and color
+ //Left out for now because all this painting stuff is very
+ //inconsistent. Some values go over PDFState, some don't.
+ }
+ comment("------ done.");
}
/**
}
}
- /**
- * Converts a ColorType to a java.awt.Color (sRGB).
- * @param col the color
- * @return the converted color
- */
- private Color toColor(ColorType col) {
- return new Color(col.getRed(), col.getGreen(), col.getBlue());
- }
-
/**
* Establishes a new foreground or fill color.
* @param col the color to apply (null skips this operation)
}
}
+ /** @see org.apache.fop.render.AbstractPathOrientedRenderer */
+ protected void updateColor(ColorType col, boolean fill) {
+ updateColor(col, fill, null);
+ }
+
private void updateFont(String name, int size, StringBuffer pdf) {
if ((!name.equals(this.currentFontName))
|| (size != this.currentFontSize)) {
putImage(url, pos);
}
+ /** @see org.apache.fop.render.AbstractPathOrientedRenderer */
+ protected void drawImage(String url, Rectangle2D pos) {
+ endTextObject();
+ putImage(url, pos);
+ }
+
/**
* Adds a PDF XObject (a bitmap) to the PDF that will later be referenced.
* @param url URL of the bitmap
}
- /**
- * Render an inline viewport.
- * This renders an inline viewport by clipping if necessary.
- * @param viewport the viewport to handle
- */
- public void renderViewport(Viewport viewport) {
-
- float x = currentIPPosition / 1000f;
- float y = (currentBPPosition + viewport.getOffset()) / 1000f;
- float width = viewport.getIPD() / 1000f;
- float height = viewport.getBPD() / 1000f;
- // TODO: Calculate the border rect correctly.
- drawBackAndBorders(viewport, x, y, width, height);
-
- if (viewport.getClip()) {
- saveGraphicsState();
-
- clip(x, y, width, height);
- }
- super.renderViewport(viewport);
-
- if (viewport.getClip()) {
- restoreGraphicsState();
- }
- }
-
/**
* Render leader area.
* This renders a leader area which is an area with a rule.
/*
- * Copyright 1999-2004 The Apache Software Foundation.
+ * Copyright 1999-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.
* <tt>PSGraphics2D</tt>.
*
* @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a>
- * @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a>
* @version $Id$
* @see org.apache.fop.render.ps.PSGraphics2D
*/
}
writePageHeader();
- gen.writeln("0.001 0.001 scale");
if ((this.viewportWidth != this.width
|| this.viewportHeight != this.height)
&& (this.viewportWidth > 0) && (this.viewportHeight > 0)){
gen.concatMatrix(this.width / this.viewportWidth, 0,
0, -1 * (this.height / this.viewportHeight),
- 0, this.height * 1000);
+ 0, this.height);
} else {
- gen.concatMatrix(1, 0, 0, -1, 0, this.height * 1000);
+ gen.concatMatrix(1, 0, 0, -1, 0, this.height);
}
gen.writeDSCComment(DSCConstants.END_PAGE_SETUP);
this.pagePending = true;
/*
- * Copyright 1999-2004 The Apache Software Foundation.
+ * Copyright 1999-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.
package org.apache.fop.render.ps;
+import java.awt.Color;
import java.awt.geom.AffineTransform;
import java.io.OutputStream;
import java.io.IOException;
* This class is used to output PostScript code to an OutputStream.
*
* @author <a href="mailto:fop-dev@xml.apache.org">Apache XML FOP Development Team</a>
- * @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a>
- * @version $Id: PSGenerator.java,v 1.3 2003/03/07 09:46:30 jeremias Exp $
+ * @version $Id$
*/
public class PSGenerator {
private Stack graphicsStateStack = new Stack();
private PSState currentState;
- private DecimalFormat df3 = new DecimalFormat("0.000", new DecimalFormatSymbols(Locale.US));
- private DecimalFormat df1 = new DecimalFormat("0.#", new DecimalFormatSymbols(Locale.US));
+ //private DecimalFormat df3 = new DecimalFormat("0.000", new DecimalFormatSymbols(Locale.US));
+ private DecimalFormat df3 = new DecimalFormat("0.###", new DecimalFormatSymbols(Locale.US));
private DecimalFormat df5 = new DecimalFormat("0.#####", new DecimalFormatSymbols(Locale.US));
private StringBuffer tempBuffer = new StringBuffer(256);
public PSGenerator(OutputStream out) {
this.out = out;
this.currentState = new PSState();
- this.graphicsStateStack.push(this.currentState);
+ //this.graphicsStateStack.push(this.currentState);
}
/**
/**
* Returns the selected PostScript level.
- * (Hardcoded to level 3 for the moment.)
+ * (Hardcoded to level 2 for the moment.)
* @return the PostScript level
*/
public int getPSLevel() {
- return 3;
+ return 2;
}
-
+
/**
* Writes a newline character to the OutputStream.
*
* @return the formatted value
*/
public String formatDouble(double value) {
- return df1.format(value);
+ return df3.format(value);
}
/**
public void saveGraphicsState() throws IOException {
writeln("gsave");
- PSState state = (PSState)this.currentState.clone();
+ PSState state = new PSState(this.currentState, false);
this.graphicsStateStack.push(this.currentState);
this.currentState = state;
}
/**
* Restores the last graphics state of the rendering engine.
+ * @return true if the state was restored, false if there's a stack underflow.
* @exception IOException In case of an I/O problem
*/
- public void restoreGraphicsState() throws IOException {
- writeln("grestore");
- this.currentState = (PSState)this.graphicsStateStack.pop();
+ public boolean restoreGraphicsState() throws IOException {
+ if (this.graphicsStateStack.size() > 0) {
+ writeln("grestore");
+ this.currentState = (PSState)this.graphicsStateStack.pop();
+ return true;
+ } else {
+ return false;
+ }
}
+
+ /**
+ * Returns the current graphics state.
+ * @return the current graphics state
+ */
+ public PSState getCurrentState() {
+ return this.currentState;
+ }
+
/**
* Concats the transformation matrix.
* @param a A part
* @exception IOException In case of an I/O problem
*/
public void concatMatrix(double a, double b,
- double c, double d,
- double e, double f) throws IOException {
- writeln("[" + formatDouble5(a) + " "
- + formatDouble5(b) + " "
- + formatDouble5(c) + " "
- + formatDouble5(d) + " "
- + formatDouble5(e) + " "
- + formatDouble5(f) + "] concat");
+ double c, double d,
+ double e, double f) throws IOException {
+ AffineTransform at = new AffineTransform(a, b, c, d, e, f);
+ concatMatrix(at);
+
}
/**
public void concatMatrix(AffineTransform at) throws IOException {
double[] matrix = new double[6];
at.getMatrix(matrix);
- concatMatrix(matrix);
+ getCurrentState().concatMatrix(at);
+ writeln("[" + formatDouble5(matrix[0]) + " "
+ + formatDouble5(matrix[1]) + " "
+ + formatDouble5(matrix[2]) + " "
+ + formatDouble5(matrix[3]) + " "
+ + formatDouble5(matrix[4]) + " "
+ + formatDouble5(matrix[5]) + "] concat");
}
/**
+ " " + formatDouble(h)
+ " re");
}
+
+ /**
+ * Establishes the specified line cap style.
+ * @param linecap the line cap style (0, 1 or 2) as defined by the setlinecap command.
+ * @exception IOException In case of an I/O problem
+ */
+ public void useLineCap(int linecap) throws IOException {
+ if (getCurrentState().useLineCap(linecap)) {
+ writeln(linecap + " setlinecap");
+ }
+ }
/**
- * Returns the current graphics state.
- * @return the current graphics state
+ * Establishes the specified line width.
+ * @param width the line width as defined by the setlinewidth command.
+ * @exception IOException In case of an I/O problem
*/
- public PSState getCurrentState() {
- return this.currentState;
+ public void useLineWidth(double width) throws IOException {
+ if (getCurrentState().useLineWidth(width)) {
+ writeln(formatDouble(width) + " setlinewidth");
+ }
+ }
+
+ /**
+ * Establishes the specified dash pattern.
+ * @param pattern the dash pattern as defined by the setdash command.
+ * @exception IOException In case of an I/O problem
+ */
+ public void useDash(String pattern) throws IOException {
+ if (pattern == null) {
+ pattern = PSState.DEFAULT_DASH;
+ }
+ if (getCurrentState().useDash(pattern)) {
+ writeln(pattern + " setdash");
+ }
+ }
+
+ /**
+ * Establishes the specified color (RGB).
+ * @param col the color as defined by the setrgbcolor command.
+ * @exception IOException In case of an I/O problem
+ */
+ public void useRGBColor(Color col) throws IOException {
+ if (col == null) {
+ col = PSState.DEFAULT_RGB_COLOR;
+ }
+ if (getCurrentState().useColor(col)) {
+ float[] comps = col.getColorComponents(null);
+ writeln(formatDouble(comps[0])
+ + " " + formatDouble(comps[1])
+ + " " + formatDouble(comps[2])
+ + " setrgbcolor");
+ }
}
-
+ /**
+ * Establishes the specified font and size.
+ * @param name name of the font for the "F" command (see FOP Std Proc Set)
+ * @param size size of the font
+ * @exception IOException In case of an I/O problem
+ */
+ public void useFont(String name, float size) throws IOException {
+ if (getCurrentState().useFont(name, size)) {
+ writeln(name + " " + formatDouble(size) + " F");
+ }
+ }
+
/** Used for the ATEND constant. See there. */
private static interface AtendIndicator {
}
+
}
* implementing a <tt>Graphic2D</tt> piece-meal.
*
* @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a>
- * @version $Id: PSGraphics2D.java,v 1.11 2003/03/11 08:42:24 jeremias Exp $
+ * @version $Id$
* @see org.apache.batik.ext.awt.g2d.AbstractGraphics2D
*/
public class PSGraphics2D extends AbstractGraphics2D {
+ private static final AffineTransform IDENTITY_TRANSFORM = new AffineTransform();
+
/** the logger for this class */
protected Log log = LogFactory.getLog(PSTextPainter.class);
/** the PostScript generator being created */
protected PSGenerator gen;
- private boolean clippingDisabled = true;
+ private boolean clippingDisabled = false;
/** Currently valid FontState */
protected Font font;
Shape imclip = getClip();
writeClip(imclip);
gen.concatMatrix(at);
- PSImageUtils.renderFopImage(fopimg,
- 1000 * x, 1000 * y, 1000 * width, 1000 * height, gen);
+ PSImageUtils.renderBitmapImage(fopimg,
+ x, y, width, height, gen);
gen.restoreGraphicsState();
} catch (IOException ioe) {
handleIOException(ioe);
/** @see org.apache.fop.image.FopImage#getIntrinsicWidth() */
public int getIntrinsicWidth() {
- return (int)(getWidth() * 72000 / getHorizontalResolution());
+ return (int)(getWidth() * 72 / getHorizontalResolution());
}
/** @see org.apache.fop.image.FopImage#getIntrinsicHeight() */
public int getIntrinsicHeight() {
- return (int)(getHeight() * 72000 / getVerticalResolution());
+ return (int)(getHeight() * 72 / getVerticalResolution());
}
/** @see org.apache.fop.image.FopImage#getHorizontalResolution() */
int type = iter.currentSegment(vals);
switch (type) {
case PathIterator.SEG_CUBICTO:
- gen.writeln(gen.formatDouble(1000 * vals[0]) + " "
- + gen.formatDouble(1000 * vals[1]) + " "
- + gen.formatDouble(1000 * vals[2]) + " "
- + gen.formatDouble(1000 * vals[3]) + " "
- + gen.formatDouble(1000 * vals[4]) + " "
- + gen.formatDouble(1000 * vals[5])
+ gen.writeln(gen.formatDouble(vals[0]) + " "
+ + gen.formatDouble(vals[1]) + " "
+ + gen.formatDouble(vals[2]) + " "
+ + gen.formatDouble(vals[3]) + " "
+ + gen.formatDouble(vals[4]) + " "
+ + gen.formatDouble(vals[5])
+ " curveto");
break;
case PathIterator.SEG_LINETO:
- gen.writeln(gen.formatDouble(1000 * vals[0]) + " "
- + gen.formatDouble(1000 * vals[1])
+ gen.writeln(gen.formatDouble(vals[0]) + " "
+ + gen.formatDouble(vals[1])
+ " lineto");
break;
case PathIterator.SEG_MOVETO:
- gen.writeln(gen.formatDouble(1000 * vals[0]) + " "
- + gen.formatDouble(1000 * vals[1])
+ gen.writeln(gen.formatDouble(vals[0]) + " "
+ + gen.formatDouble(vals[1])
+ " M");
break;
case PathIterator.SEG_QUADTO:
- gen.writeln(gen.formatDouble(1000 * vals[0]) + " "
- + gen.formatDouble(1000 * vals[1]) + " "
- + gen.formatDouble(1000 * vals[2]) + " "
- + gen.formatDouble(1000 * vals[3]) + " QUADTO ");
+ gen.writeln(gen.formatDouble(vals[0]) + " "
+ + gen.formatDouble(vals[1]) + " "
+ + gen.formatDouble(vals[2]) + " "
+ + gen.formatDouble(vals[3]) + " QUADTO ");
break;
case PathIterator.SEG_CLOSE:
gen.writeln("closepath");
preparePainting();
try {
gen.saveGraphicsState();
+
+ AffineTransform trans = getTransform();
+ boolean newTransform = gen.getCurrentState().checkTransform(trans)
+ && !trans.isIdentity();
+
Shape imclip = getClip();
writeClip(imclip);
+ if (newTransform) {
+ gen.concatMatrix(trans);
+ }
establishColor(getColor());
applyPaint(getPaint(), false);
applyStroke(getStroke());
gen.writeln("newpath");
- PathIterator iter = s.getPathIterator(getTransform());
+ PathIterator iter = s.getPathIterator(IDENTITY_TRANSFORM);
processPathIterator(iter);
doDrawing(false, true, false);
gen.restoreGraphicsState();
PathIterator iter = s.getPathIterator(getTransform());
processPathIterator(iter);
// clip area
- gen.writeln("clippath");
+ gen.writeln("clip");
} catch (IOException ioe) {
handleIOException(ioe);
}
if (da != null) {
gen.write("[");
for (int count = 0; count < da.length; count++) {
- gen.write("" + (1000 * (int)da[count]));
+ gen.write("" + ((int)da[count]));
if (count < da.length - 1) {
gen.write(" ");
}
}
gen.write("] ");
float offset = bs.getDashPhase();
- gen.writeln((1000 * (int)offset) + " setdash");
+ gen.writeln(((int)offset) + " setdash");
}
int ec = bs.getEndCap();
switch (ec) {
default: log.warn("Unsupported line join: " + lj);
}
float lw = bs.getLineWidth();
- gen.writeln(gen.formatDouble(1000 * lw) + " setlinewidth");
+ gen.writeln(gen.formatDouble(lw) + " setlinewidth");
float ml = bs.getMiterLimit();
- gen.writeln(gen.formatDouble(1000 * ml) + " setmiterlimit");
+ gen.writeln(gen.formatDouble(ml) + " setmiterlimit");
}
} catch (IOException ioe) {
handleIOException(ioe);
//Prepare correct transformation
AffineTransform trans = getTransform();
- gen.writeln("[" + toArray(trans) + "] concat");
- gen.writeln(gen.formatDouble(1000 * x) + " "
- + gen.formatDouble(1000 * y) + " moveto ");
+ gen.concatMatrix(trans);
+ gen.writeln(gen.formatDouble(x) + " "
+ + gen.formatDouble(y) + " moveto ");
gen.writeln("1 -1 scale");
StringBuffer sb = new StringBuffer("(");
}
}
- /**
- * Converts an AffineTransform to a value array.
- * @param at AffineTransform to convert
- * @return a String (array of six space-separated values)
- */
- protected String toArray(AffineTransform at) {
- final double[] vals = new double[6];
- at.getMatrix(vals);
- return gen.formatDouble5(vals[0]) + " "
- + gen.formatDouble5(vals[1]) + " "
- + gen.formatDouble5(vals[2]) + " "
- + gen.formatDouble5(vals[3]) + " "
- + gen.formatDouble(1000 * vals[4]) + " "
- + gen.formatDouble(1000 * vals[5]);
- }
-
private void escapeText(final String text, StringBuffer target) {
final int l = text.length();
for (int i = 0; i < l; i++) {
/*
- * Copyright 2004 The Apache Software Foundation.
+ * Copyright 2004-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.
import java.io.IOException;
import java.io.OutputStream;
+import org.apache.commons.io.output.CountingOutputStream;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fop.image.EPSImage;
import org.apache.fop.image.FopImage;
import org.apache.fop.image.JpegImage;
+import org.apache.fop.image.XMLImage;
import org.apache.fop.util.ASCII85OutputStream;
import org.apache.fop.util.Finalizable;
import org.apache.fop.util.FlateEncodeOutputStream;
import org.apache.fop.util.RunLengthEncodeOutputStream;
+import org.w3c.dom.Document;
/**
* Utility code for rendering images in PostScript.
*/
public class PSImageUtils {
+ /** logging instance */
+ protected static Log log = LogFactory.getLog(PSImageUtils.class);
+
/**
- * Renders an image to PostScript.
+ * Renders a bitmap image to PostScript.
* @param img image to render
* @param x x position
* @param y y position
* @param gen PS generator
* @throws IOException In case of an I/O problem while rendering the image
*/
- public static void renderFopImage(FopImage img, int x, int y, int w, int h, PSGenerator gen) throws IOException {
+ public static void renderBitmapImage(FopImage img,
+ float x, float y, float w, float h, PSGenerator gen)
+ throws IOException {
+ if (img instanceof JpegImage) {
+ if (!img.load(FopImage.ORIGINAL_DATA)) {
+ gen.commentln("%JPEG image could not be processed: " + img);
+ return;
+ }
+ } else {
+ if (!img.load(FopImage.BITMAP)) {
+ gen.commentln("%Bitmap image could not be processed: " + img);
+ return;
+ }
+ }
boolean iscolor = img.getColorSpace().getType()
!= ColorSpace.CS_GRAY;
byte[] imgmap = img.getBitmaps();
gen.saveGraphicsState();
+ gen.commentln("%FOPBeginBitmap: " + img.getMimeType());
if (img.getColorSpace().getType() == ColorSpace.TYPE_CMYK) {
gen.writeln("/DeviceCMYK setcolorspace");
} else if (img.getColorSpace().getType() == ColorSpace.CS_GRAY) {
gen.writeln(" RawData flushfile");
gen.writeln("} exec");
- /*
- * for (int y=0; y<img.getHeight(); y++) {
- * int indx = y * img.getWidth();
- * if (iscolor) indx*= 3;
- * for (int x=0; x<img.getWidth(); x++) {
- * if (iscolor) {
- * writeASCIIHex(imgmap[indx++] & 0xFF);
- * writeASCIIHex(imgmap[indx++] & 0xFF);
- * writeASCIIHex(imgmap[indx++] & 0xFF);
- * } else {
- * writeASCIIHex(imgmap[indx++] & 0xFF);
- * }
- * }
- * }
- */
-
OutputStream out = gen.getOutputStream();
out = new ASCII85OutputStream(out);
if (img instanceof JpegImage) {
}
gen.writeln("");
+ gen.commentln("%FOPEndBitmap");
gen.restoreGraphicsState();
}
+ public static void renderEPS(EPSImage img,
+ float x, float y, float w, float h,
+ PSGenerator gen) {
+ try {
+ if (!img.load(FopImage.ORIGINAL_DATA)) {
+ gen.commentln("%EPS image could not be processed: " + img);
+ return;
+ }
+ int[] bbox = img.getBBox();
+ int bboxw = bbox[2] - bbox[0];
+ int bboxh = bbox[3] - bbox[1];
+ renderEPS(img.getEPSImage(), img.getDocName(),
+ x, y, w, h,
+ bbox[0], bbox[1], bboxw, bboxh, gen);
+
+ } catch (Exception e) {
+ log.error("PSRenderer.renderImageArea(): Error rendering bitmap ("
+ + e.getMessage() + ")", e);
+ }
+ }
+
+ /**
+ * Places an EPS file in the PostScript stream.
+ * @param rawEPS byte array containing the raw EPS data
+ * @param name name for the EPS document
+ * @param x x-coordinate of viewport in millipoints
+ * @param y y-coordinate of viewport in millipoints
+ * @param w width of viewport in millipoints
+ * @param h height of viewport in millipoints
+ * @param bboxx x-coordinate of EPS bounding box in points
+ * @param bboxy y-coordinate of EPS bounding box in points
+ * @param bboxw width of EPS bounding box in points
+ * @param bboxh height of EPS bounding box in points
+ * @throws IOException in case an I/O error happens during output
+ */
+ public static void renderEPS(byte[] rawEPS, String name,
+ float x, float y, float w, float h,
+ int bboxx, int bboxy, int bboxw, int bboxh,
+ PSGenerator gen) throws IOException {
+ gen.writeln("BeginEPSF");
+ gen.writeln("%%BeginDocument: " + name);
+
+ gen.writeln(gen.formatDouble(x) + " " + gen.formatDouble(y) + " translate");
+ gen.writeln("0 " + gen.formatDouble(h) + " translate");
+ gen.writeln("1 -1 scale");
+ float sx = w / bboxw;
+ float sy = h / bboxh;
+ if (sx != 1 || sy != 1) {
+ gen.writeln(gen.formatDouble(sx) + " " + gen.formatDouble(sy) + " scale");
+ }
+ if (bboxx != 0 || bboxy != 0) {
+ gen.writeln(gen.formatDouble(-bboxx) + " " + gen.formatDouble(-bboxy) + " translate");
+ }
+ gen.writeln(gen.formatDouble(bboxy) + " " + gen.formatDouble(bboxy)
+ + " " + gen.formatDouble(bboxw) + " " + gen.formatDouble(bboxh) + " re clip");
+ gen.writeln("newpath");
+ gen.writeByteArr(rawEPS);
+ gen.writeln("%%EndDocument");
+ gen.writeln("EndEPSF");
+ gen.writeln("");
+ }
}
package org.apache.fop.render.ps;
// Java
+import java.awt.Color;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.io.OutputStream;
+import java.util.Iterator;
import java.util.List;
// FOP
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
-import org.apache.fop.area.Area;
-import org.apache.fop.area.RegionViewport;
import org.apache.fop.apps.FOPException;
-import org.apache.fop.area.Block;
+import org.apache.fop.area.Area;
import org.apache.fop.area.BlockViewport;
import org.apache.fop.area.CTM;
import org.apache.fop.area.PageViewport;
+import org.apache.fop.area.RegionViewport;
import org.apache.fop.area.Trait;
import org.apache.fop.area.inline.ForeignObject;
+import org.apache.fop.area.inline.Image;
+import org.apache.fop.area.inline.InlineParent;
import org.apache.fop.area.inline.TextArea;
import org.apache.fop.datatypes.ColorType;
import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.fo.Constants;
import org.apache.fop.fonts.FontSetup;
import org.apache.fop.fonts.Typeface;
-import org.apache.fop.render.PrintRenderer;
-import org.apache.fop.render.RendererContext;
-
+import org.apache.fop.image.EPSImage;
import org.apache.fop.image.FopImage;
import org.apache.fop.image.ImageFactory;
-import org.apache.fop.traits.BorderProps;
+import org.apache.fop.image.XMLImage;
+import org.apache.fop.render.AbstractPathOrientedRenderer;
+import org.apache.fop.render.RendererContext;
import org.w3c.dom.Document;
* sure to also follow the DSC to make it simpler to programmatically modify
* the generated Postscript files (ex. extract pages etc.).
* <br>
- * The PS renderer operates in millipoints as the layout engine. Since PostScript
- * initially uses points, scaling is applied as needed.
+ * This renderer inserts FOP-specific comments into the PostScript stream which
+ * may help certain users to do certain types of post-processing of the output.
+ * These comments all start with "%FOP".
*
* @author <a href="mailto:fop-dev@xml.apache.org">Apache XML FOP Development Team</a>
- * @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a>
- * @version $Id: PSRenderer.java,v 1.31 2003/03/11 08:42:24 jeremias Exp $
+ * @version $Id$
*/
-public class PSRenderer extends PrintRenderer {
+public class PSRenderer extends AbstractPathOrientedRenderer {
/** The MIME type for PostScript */
public static final String MIME_TYPE = "application/postscript";
protected PSGenerator gen;
private boolean ioTrouble = false;
- private String currentFontName;
- private int currentFontSize;
- private float currRed;
- private float currGreen;
- private float currBlue;
+ private boolean inTextMode = false;
/**
* @see org.apache.avalon.framework.configuration.Configurable#configure(Configuration)
*/
protected void comment(String comment) {
if (this.enableComments) {
- writeln(comment);
+ if (comment.startsWith("%")) {
+ writeln(comment);
+ } else {
+ writeln("%" + comment);
+ }
}
}
moveTo(this.currentIPPosition, this.currentBPPosition);
}
+ /** @see org.apache.fop.render.AbstractPathOrientedRenderer#clip() */
+ protected void clip() {
+ writeln("clip newpath");
+ //writeln("newpath");
+ }
+
/**
- * Moves the cursor.
- * @param x X coordinate
- * @param y Y coordinate
+ * 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 moveTo(int x, int y) {
- writeln(x + " " + y + " M");
+ protected void clipRect(float x, float y, float width, float height) {
+ try {
+ gen.defineRect(x, y, width, height);
+ gen.writeln("clip");
+ //comment("clip here");
+ } catch (IOException ioe) {
+ handleIOTrouble(ioe);
+ }
}
+ /** @see org.apache.fop.render.AbstractPathOrientedRenderer#moveTo(float, float) */
+ protected void moveTo(float x, float y) {
+ writeln(gen.formatDouble(x) + " " + gen.formatDouble(y) + " M");
+ }
+
+ /** @see org.apache.fop.render.AbstractPathOrientedRenderer#lineTo(float, float) */
+ protected void lineTo(float x, float y) {
+ writeln(gen.formatDouble(x) + " " + gen.formatDouble(y) + " lineto");
+ }
+
+ /** @see org.apache.fop.render.AbstractPathOrientedRenderer#closePath() */
+ protected void closePath() {
+ writeln("cp");
+ }
+
+ /** @see org.apache.fop.render.AbstractPathOrientedRenderer */
+ protected void fillRect(float x, float y, float width, float height) {
+ try {
+ gen.defineRect(x, y, width, height);
+ gen.writeln("fill");
+ } catch (IOException ioe) {
+ handleIOTrouble(ioe);
+ }
+ }
+
+ /** @see org.apache.fop.render.AbstractPathOrientedRenderer */
+ protected void updateColor(ColorType col, boolean fill) {
+ try {
+ useColor(col);
+ } catch (IOException ioe) {
+ handleIOTrouble(ioe);
+ }
+ }
+
+ /** @see org.apache.fop.render.AbstractPathOrientedRenderer */
+ protected void drawImage(String url, Rectangle2D pos) {
+ endTextObject();
+ url = ImageFactory.getURL(url);
+ ImageFactory fact = ImageFactory.getInstance();
+ FopImage fopimage = fact.getImage(url, userAgent);
+ if (fopimage == null) {
+ return;
+ }
+ if (!fopimage.load(FopImage.DIMENSIONS)) {
+ return;
+ }
+ float x = (float)pos.getX() / 1000f;
+ x += currentIPPosition / 1000f;
+ float y = (float)pos.getY() / 1000f;
+ y += currentBPPosition / 1000f;
+ float w = (float)pos.getWidth() / 1000f;
+ float h = (float)pos.getHeight() / 1000f;
+ try {
+ 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();
+ String ns = ((XMLImage) fopimage).getNameSpace();
+
+ renderDocument(doc, ns, pos);
+ } else if (fopimage instanceof EPSImage) {
+ PSImageUtils.renderEPS((EPSImage)fopimage, x, y, w, h, gen);
+ } else {
+ PSImageUtils.renderBitmapImage(fopimage, x, y, w, h, gen);
+ }
+ } catch (IOException ioe) {
+ handleIOTrouble(ioe);
+ }
+ }
+
+ /**
+ * Draw a line.
+ *
+ * @param startx the start x position
+ * @param starty the start y position
+ * @param endx the x end position
+ * @param endy the y end position
+ */
+ private void drawLine(float startx, float starty, float endx, float endy) {
+ writeln(gen.formatDouble(startx) + " "
+ + gen.formatDouble(starty) + " M "
+ + gen.formatDouble(endx) + " "
+ + gen.formatDouble(endy) + " lineto stroke newpath");
+ }
+
/** Saves the graphics state of the rendering engine. */
public void saveGraphicsState() {
+ endTextObject();
try {
//delegate
gen.saveGraphicsState();
/** Restores the last graphics state of the rendering engine. */
public void restoreGraphicsState() {
+ endTextObject();
try {
//delegate
gen.restoreGraphicsState();
/** Indicates the beginning of a text object. */
protected void beginTextObject() {
- writeln("BT");
+ if (!inTextMode) {
+ writeln("BT");
+ inTextMode = true;
+ }
}
/** Indicates the end of a text object. */
protected void endTextObject() {
- writeln("ET");
+ if (inTextMode) {
+ writeln("ET");
+ inTextMode = false;
+ }
}
/**
}
}
- /**
- * Draws a filled rectangle.
- * @param x x-coordinate
- * @param y y-coordinate
- * @param w width
- * @param h height
- * @param col color to fill with
- */
- protected void fillRect(float x, float y, float w, float h,
- ColorType col) {
- useColor(col);
- writeln(gen.formatDouble(x)
- + " " + gen.formatDouble(y)
- + " " + gen.formatDouble(w)
- + " " + gen.formatDouble(h)
- + " rectfill");
- }
-
- /**
- * Draws a stroked rectangle with the current stroke settings.
- * @param x x-coordinate
- * @param y y-coordinate
- * @param w width
- * @param h height
- */
- protected void drawRect(float x, float y, float w, float h) {
- writeln(gen.formatDouble(x)
- + " " + gen.formatDouble(y)
- + " " + gen.formatDouble(w)
- + " " + gen.formatDouble(h)
- + " rectstroke");
- }
-
- /**
- * 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) {
- writeln(x + " " + y + " " + width + " " + height + " rectclip");
- }
-
/**
* Changes the currently used font.
* @param name name of the font
* @param size font size
*/
public void useFont(String name, int size) {
- if ((currentFontName != name) || (currentFontSize != size)) {
- writeln(name + " " + size + " F");
- currentFontName = name;
- currentFontSize = size;
+ try {
+ gen.useFont(name, size / 1000f);
+ } catch (IOException ioe) {
+ handleIOTrouble(ioe);
}
}
- private void useColor(ColorType col) {
- useColor(col.getRed(), col.getGreen(), col.getBlue());
+ private void useColor(ColorType col) throws IOException {
+ gen.useRGBColor(toColor(col));
}
- private void useColor(float red, float green, float blue) {
- if ((red != currRed) || (green != currGreen) || (blue != currBlue)) {
- writeln(gen.formatDouble(red)
- + " " + gen.formatDouble(green)
- + " " + gen.formatDouble(blue)
- + " setrgbcolor");
- currRed = red;
- currGreen = green;
- currBlue = blue;
+ /** @see org.apache.fop.render.AbstractPathOrientedRenderer */
+ protected void drawBackAndBorders(Area area, float startx, float starty,
+ float width, float height) {
+ if (area.hasTrait(Trait.BACKGROUND)
+ || area.hasTrait(Trait.BORDER_BEFORE)
+ || area.hasTrait(Trait.BORDER_AFTER)
+ || area.hasTrait(Trait.BORDER_START)
+ || area.hasTrait(Trait.BORDER_END)) {
+ comment("%FOPBeginBackgroundAndBorder: "
+ + startx + " " + starty + " " + width + " " + height);
+ super.drawBackAndBorders(area, startx, starty, width, height);
+ comment("%FOPEndBackgroundAndBorder");
}
}
-
+
+ /** @see org.apache.fop.render.AbstractPathOrientedRenderer */
+ protected void drawBorderLine(float x1, float y1, float x2, float y2,
+ boolean horz, boolean startOrBefore, int style, ColorType col) {
+ try {
+ float w = x2 - x1;
+ float h = y2 - y1;
+ if ((w < 0) || (h < 0)) {
+ log.error("Negative extent received. Border won't be painted.");
+ return;
+ }
+ switch (style) {
+ case Constants.EN_DASHED:
+ useColor(col);
+ if (horz) {
+ float unit = Math.abs(2 * h);
+ int rep = (int)(w / unit);
+ if (rep % 2 == 0) {
+ rep++;
+ }
+ unit = w / rep;
+ gen.useDash("[" + unit + "] 0");
+ gen.useLineCap(0);
+ gen.useLineWidth(h);
+ float ym = y1 + (h / 2);
+ drawLine(x1, ym, x2, ym);
+ } else {
+ float unit = Math.abs(2 * w);
+ int rep = (int)(h / unit);
+ if (rep % 2 == 0) {
+ rep++;
+ }
+ unit = h / rep;
+ gen.useDash("[" + unit + "] 0");
+ gen.useLineCap(0);
+ gen.useLineWidth(w);
+ float xm = x1 + (w / 2);
+ drawLine(xm, y1, xm, y2);
+ }
+ break;
+ case Constants.EN_DOTTED:
+ useColor(col);
+ gen.useLineCap(1); //Rounded!
+ if (horz) {
+ float unit = Math.abs(2 * h);
+ int rep = (int)(w / unit);
+ if (rep % 2 == 0) {
+ rep++;
+ }
+ unit = w / rep;
+ gen.useDash("[0 " + unit + "] 0");
+ gen.useLineWidth(h);
+ float ym = y1 + (h / 2);
+ drawLine(x1, ym, x2, ym);
+ } else {
+ float unit = Math.abs(2 * w);
+ int rep = (int)(h / unit);
+ if (rep % 2 == 0) {
+ rep++;
+ }
+ unit = h / rep;
+ gen.useDash("[0 " + unit + "] 0");
+ gen.useLineWidth(w);
+ float xm = x1 + (w / 2);
+ drawLine(xm, y1, xm, y2);
+ }
+ break;
+ case Constants.EN_DOUBLE:
+ useColor(col);
+ gen.useDash(null);
+ if (horz) {
+ float h3 = h / 3;
+ gen.useLineWidth(h3);
+ float ym1 = y1 + (h3 / 2);
+ float ym2 = ym1 + h3 + h3;
+ drawLine(x1, ym1, x2, ym1);
+ drawLine(x1, ym2, x2, ym2);
+ } else {
+ float w3 = w / 3;
+ gen.useLineWidth(w3);
+ float xm1 = x1 + (w3 / 2);
+ float xm2 = xm1 + w3 + w3;
+ drawLine(xm1, y1, xm1, y2);
+ drawLine(xm2, y1, xm2, y2);
+ }
+ break;
+ case Constants.EN_GROOVE:
+ case Constants.EN_RIDGE:
+ float colFactor = (style == EN_GROOVE ? 0.4f : -0.4f);
+ gen.useDash(null);
+ Color c = toColor(col);
+ if (horz) {
+ Color uppercol = lightenColor(c, -colFactor);
+ Color lowercol = lightenColor(c, colFactor);
+ float h3 = h / 3;
+ gen.useLineWidth(h3);
+ float ym1 = y1 + (h3 / 2);
+ gen.useRGBColor(uppercol);
+ drawLine(x1, ym1, x2, ym1);
+ gen.useRGBColor(c);
+ drawLine(x1, ym1 + h3, x2, ym1 + h3);
+ gen.useRGBColor(lowercol);
+ drawLine(x1, ym1 + h3 + h3, x2, ym1 + h3 + h3);
+ } else {
+ Color leftcol = lightenColor(c, -colFactor);
+ Color rightcol = lightenColor(c, colFactor);
+ float w3 = w / 3;
+ gen.useLineWidth(w3);
+ float xm1 = x1 + (w3 / 2);
+ gen.useRGBColor(leftcol);
+ drawLine(xm1, y1, xm1, y2);
+ gen.useRGBColor(c);
+ drawLine(xm1 + w3, y1, xm1 + w3, y2);
+ gen.useRGBColor(rightcol);
+ drawLine(xm1 + w3 + w3, y1, xm1 + w3 + w3, y2);
+ }
+ break;
+ case Constants.EN_INSET:
+ case Constants.EN_OUTSET:
+ colFactor = (style == EN_OUTSET ? 0.4f : -0.4f);
+ gen.useDash(null);
+ c = toColor(col);
+ if (horz) {
+ c = lightenColor(c, (startOrBefore ? 1 : -1) * colFactor);
+ gen.useLineWidth(h);
+ float ym1 = y1 + (h / 2);
+ gen.useRGBColor(c);
+ drawLine(x1, ym1, x2, ym1);
+ } else {
+ c = lightenColor(c, (startOrBefore ? 1 : -1) * colFactor);
+ gen.useLineWidth(w);
+ float xm1 = x1 + (w / 2);
+ gen.useRGBColor(c);
+ drawLine(xm1, y1, xm1, y2);
+ }
+ break;
+ case Constants.EN_HIDDEN:
+ break;
+ default:
+ useColor(col);
+ gen.useDash(null);
+ gen.useLineCap(0);
+ if (horz) {
+ gen.useLineWidth(h);
+ float ym = y1 + (h / 2);
+ drawLine(x1, ym, x2, ym);
+ } else {
+ gen.useLineWidth(w);
+ float xm = x1 + (w / 2);
+ drawLine(xm, y1, xm, y2);
+ }
+ }
+ } catch (IOException ioe) {
+ handleIOTrouble(ioe);
+ }
+ }
+
/**
* @see org.apache.fop.render.Renderer#startRenderer(OutputStream)
*/
+ Math.round(pspageheight) + "]");
gen.writeln("/ImagingBBox null");
gen.writeln(">> setpagedevice");
- gen.writeln("0.001 0.001 scale");
- concatMatrix(1, 0, 0, -1, 0, pageheight);
+ //gen.writeln("0.001 0.001 scale");
+ concatMatrix(1, 0, 0, -1, 0, pageheight / 1000f);
gen.writeDSCComment(DSCConstants.END_PAGE_SETUP);
gen.writeDSCComment(DSCConstants.END_PAGE);
}
+ /** @see org.apache.fop.render.AbstractRenderer */
+ protected void renderRegionViewport(RegionViewport port) {
+ if (port != null) {
+ comment("%FOPBeginRegionViewport: " + port.getRegionReference().getRegionName());
+ super.renderRegionViewport(port);
+ comment("%FOPEndRegionViewport");
+ }
+ }
+
/**
* Paints text.
* @param rx X coordinate
*/
protected void paintText(int rx, int bl, String text, Typeface font) {
saveGraphicsState();
- writeln("1 0 0 -1 " + rx + " " + bl + " Tm");
+ beginTextObject();
+ writeln("1 0 0 -1 " + gen.formatDouble(rx / 1000f)
+ + " " + gen.formatDouble(bl / 1000f) + " Tm");
int initialSize = text.length();
initialSize += initialSize / 2;
useFont(fontname, fontsize);
ColorType ct = (ColorType)area.getTrait(Trait.COLOR);
if (ct != null) {
- useColor(ct);
+ try {
+ useColor(ct);
+ } catch (IOException ioe) {
+ handleIOTrouble(ioe);
+ }
}
paintText(rx, bl, area.getTextArea(), f);
super.renderText(area); //Updates IPD
}
-
- /**
- * @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;
- String saveFontName = currentFontName;
-
- CTM ctm = bv.getCTM();
-
- if (bv.getPositioning() == Block.ABSOLUTE) {
-
- currentIPPosition = 0;
- currentBPPosition = 0;
-
- //closeText();
- endTextObject();
-
- if (bv.getClip()) {
- saveGraphicsState();
- int x = bv.getXOffset() + containingIPPosition;
- int y = bv.getYOffset() + containingBPPosition;
- int width = bv.getIPD();
- int height = bv.getBPD();
- clip(x, y, width, height);
- }
-
- CTM tempctm = new CTM(containingIPPosition, containingBPPosition);
- ctm = tempctm.multiply(ctm);
-
- startVParea(ctm);
- handleBlockTraits(bv);
- renderBlocks(bv, children);
- endVParea();
-
- if (bv.getClip()) {
- restoreGraphicsState();
- }
- beginTextObject();
-
- // clip if necessary
-
- currentIPPosition = saveIP;
- currentBPPosition = saveBP;
- } else {
-
- if (ctm != null) {
- currentIPPosition = 0;
- currentBPPosition = 0;
-
- //closeText();
- endTextObject();
-
- double[] vals = ctm.toArray();
- //boolean aclock = vals[2] == 1.0;
- if (vals[2] == 1.0) {
- ctm = ctm.translate(-saveBP - bv.getBPD(), -saveIP);
- } else if (vals[0] == -1.0) {
- ctm = ctm.translate(-saveIP - bv.getIPD(), -saveBP - bv.getBPD());
- } else {
- ctm = ctm.translate(saveBP, saveIP - bv.getIPD());
- }
- }
-
- // clip if necessary
- if (bv.getClip()) {
- if (ctm == null) {
- //closeText();
- endTextObject();
+ /** @see org.apache.fop.render.AbstractPathOrientedRenderer#breakOutOfStateStack() */
+ protected List breakOutOfStateStack() {
+ try {
+ List breakOutList = new java.util.ArrayList();
+ PSState state;
+ while (true) {
+ if (breakOutList.size() == 0) {
+ comment("------ break out!");
}
- saveGraphicsState();
- int x = bv.getXOffset();
- int y = bv.getYOffset();
- int width = bv.getIPD();
- int height = bv.getBPD();
- clip(x, y, width, height);
- }
-
- if (ctm != null) {
- startVParea(ctm);
- }
- handleBlockTraits(bv);
- renderBlocks(bv, children);
- if (ctm != null) {
- endVParea();
- }
-
- if (bv.getClip()) {
- restoreGraphicsState();
- if (ctm == null) {
- beginTextObject();
+ state = gen.getCurrentState();
+ if (!gen.restoreGraphicsState()) {
+ break;
}
+ breakOutList.add(0, state); //Insert because of stack-popping
}
- if (ctm != null) {
- beginTextObject();
+ return breakOutList;
+ } catch (IOException ioe) {
+ handleIOTrouble(ioe);
+ return null;
+ }
+ }
+
+ /** @see org.apache.fop.render.AbstractPathOrientedRenderer */
+ protected void restoreStateStackAfterBreakOut(List breakOutList) {
+ try {
+ comment("------ restoring context after break-out...");
+ PSState state;
+ Iterator i = breakOutList.iterator();
+ while (i.hasNext()) {
+ state = (PSState)i.next();
+ saveGraphicsState();
+ state.reestablish(gen);
}
-
- currentIPPosition = saveIP;
- currentBPPosition = saveBP;
- currentBPPosition += (int)(bv.getAllocBPD());
+ comment("------ done.");
+ } catch (IOException ioe) {
+ handleIOTrouble(ioe);
}
- currentFontName = saveFontName;
}
-
+
/**
* @see org.apache.fop.render.AbstractRenderer#startVParea(CTM)
*/
protected void startVParea(CTM ctm) {
- // Set the given CTM in the graphics state
- //currentState.push();
- //currentState.setTransform(new AffineTransform(CTMHelper.toPDFArray(ctm)));
saveGraphicsState();
// multiply with current CTM
- //writeln(CTMHelper.toPDFString(ctm) + " cm\n");
final double[] matrix = ctm.toArray();
+ matrix[4] /= 1000f;
+ matrix[5] /= 1000f;
concatMatrix(matrix);
// Set clip?
- beginTextObject();
}
/**
protected void endVParea() {
endTextObject();
restoreGraphicsState();
- //currentState.pop();
}
- /**
- * Handle the traits for a region
- * This is used to draw the traits for the given page region.
- * (See Sect. 6.4.1.2 of XSL-FO spec.)
- * @param region the RegionViewport whose region is to be drawn
- */
- protected void handleRegionTraits(RegionViewport region) {
- currentFontName = "";
- float startx = 0;
- float starty = 0;
- Rectangle2D viewArea = region.getViewArea();
- float width = (float)(viewArea.getWidth());
- float height = (float)(viewArea.getHeight());
- /*
- Trait.Background back;
- back = (Trait.Background)region.getTrait(Trait.BACKGROUND);
- */
- drawBackAndBorders(region, startx, starty, width, height);
+ /** @see org.apache.fop.render.AbstractRenderer */
+ protected void renderBlockViewport(BlockViewport bv, List children) {
+ comment("%FOPBeginBlockViewport: " + bv.toString());
+ super.renderBlockViewport(bv, children);
+ comment("%FOPEndBlockViewport");
}
+
+ /** @see org.apache.fop.render.AbstractRenderer */
+ protected void renderInlineParent(InlineParent ip) {
+ float start = currentIPPosition / 1000f;
+ float top = (ip.getOffset() + currentBPPosition) / 1000f;
+ float width = ip.getIPD() / 1000f;
+ float height = ip.getBPD() / 1000f;
+ drawBackAndBorders(ip, start, top, width, height);
- /**
- * 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) {
- float startx = currentIPPosition;
- float starty = currentBPPosition;
- drawBackAndBorders(block, startx, starty,
- block.getIPD(), block.getBPD());
+ super.renderInlineParent(ip);
}
-
+
/**
- * Draw the background and borders.
- * This draws the background and border traits for an area given
- * the position.
- *
- * @param block the area to get the traits from
- * @param startx the start x position
- * @param starty the start y position
- * @param width the width of the area
- * @param height the height of the area
+ * @see org.apache.fop.render.AbstractRenderer#renderImage(Image, Rectangle2D)
*/
- protected void drawBackAndBorders(Area block,
- float startx, float starty,
- float width, float height) {
- // draw background then border
-
- boolean started = false;
- Trait.Background back;
- back = (Trait.Background)block.getTrait(Trait.BACKGROUND);
- if (back != null) {
- started = true;
-// closeText();
- endTextObject();
- //saveGraphicsState();
-
- if (back.getColor() != null) {
- fillRect(startx, starty, width, height, back.getColor());
- }
- if (back.getURL() != null) {
- ImageFactory fact = ImageFactory.getInstance();
- FopImage fopimage = fact.getImage(back.getURL(), userAgent);
- if (fopimage != null && fopimage.load(FopImage.DIMENSIONS)) {
- if (back.getRepeat() == EN_REPEAT) {
- // create a pattern for the image
- } else {
- // place once
- Rectangle2D pos;
- pos = new Rectangle2D.Float((startx + back.getHoriz()) * 1000,
- (starty + back.getVertical()) * 1000,
- fopimage.getWidth() * 1000,
- fopimage.getHeight() * 1000);
- // putImage(back.url, pos);
- }
- }
- }
- }
-
- BorderProps bps = (BorderProps)block.getTrait(Trait.BORDER_BEFORE);
- if (bps != null) {
- float endx = startx + width;
-
- if (!started) {
- started = true;
-// closeText();
- endTextObject();
- //saveGraphicsState();
- }
-
- float bwidth = bps.width;
- useColor(bps.color);
- writeln(bwidth + " setlinewidth");
-
- drawLine(startx, starty + bwidth / 2, endx, starty + bwidth / 2);
- }
- bps = (BorderProps)block.getTrait(Trait.BORDER_START);
- if (bps != null) {
- float endy = starty + height;
-
- if (!started) {
- started = true;
-// closeText();
- endTextObject();
- //saveGraphicsState();
- }
-
- float bwidth = bps.width;
- useColor(bps.color);
- writeln(bwidth + " setlinewidth");
-
- drawLine(startx + bwidth / 2, starty, startx + bwidth / 2, endy);
- }
- bps = (BorderProps)block.getTrait(Trait.BORDER_AFTER);
- if (bps != null) {
- float sy = starty + height;
- float endx = startx + width;
-
- if (!started) {
- started = true;
-// closeText();
- endTextObject();
- //saveGraphicsState();
- }
-
- float bwidth = bps.width;
- useColor(bps.color);
- writeln(bwidth + " setlinewidth");
-
- drawLine(startx, sy - bwidth / 2, endx, sy - bwidth / 2);
- }
- bps = (BorderProps)block.getTrait(Trait.BORDER_END);
- if (bps != null) {
- float sx = startx + width;
- float endy = starty + height;
-
- if (!started) {
- started = true;
- // closeText();
- endTextObject();
- //saveGraphicsState();
- }
-
- float bwidth = bps.width;
- useColor(bps.color);
- writeln(bwidth + " setlinewidth");
- drawLine(sx - bwidth / 2, starty, sx - bwidth / 2, endy);
- }
- if (started) {
- //restoreGraphicsState();
- beginTextObject();
- // font last set out of scope in text section
- currentFontName = "";
- }
+ public void renderImage(Image image, Rectangle2D pos) {
+ drawImage(image.getURL(), pos);
}
- /**
- * Draw a line.
- *
- * @param startx the start x position
- * @param starty the start y position
- * @param endx the x end position
- * @param endy the y end position
- */
- private void drawLine(float startx, float starty, float endx, float endy) {
- writeln(startx + " " + starty + " M ");
- writeln(endx + " " + endy + " lineto");
- }
-
/**
* @see org.apache.fop.render.AbstractRenderer#renderForeignObject(ForeignObject, Rectangle2D)
*/
/*
- * Copyright 1999-2004 The Apache Software Foundation.
+ * Copyright 1999-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.
package org.apache.fop.render.ps;
+import java.io.IOException;
import java.io.Serializable;
+import java.util.List;
+import java.awt.Color;
import java.awt.geom.AffineTransform;
/**
* This class holds the current state of the PostScript interpreter.
*
* @author <a href="mailto:fop-dev@xml.apache.org">Apache XML FOP Development Team</a>
- * @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a>
- * @version $Id: PSState.java,v 1.2 2003/03/07 09:46:30 jeremias Exp $
+ * @version $Id$
*/
-public class PSState implements Serializable, Cloneable {
+public class PSState implements Serializable {
+ /** Default for setdash */
+ public static final String DEFAULT_DASH = "[] 0";
+ /** Default color in PostScript */
+ public static final Color DEFAULT_RGB_COLOR = Color.black;
+
private AffineTransform transform = new AffineTransform();
+ private List transformConcatList = new java.util.ArrayList();
-
+ private int linecap = 0;
+ private double linewidth = 1.0f;
+ private String dashpattern = DEFAULT_DASH;
+ private Color rgbColor = DEFAULT_RGB_COLOR;
+
+ //Font state
+ private String fontname;
+ private float fontsize;
+
+ /**
+ * Default constructor
+ */
+ public PSState() {
+ //nop
+ }
+
+ /**
+ * Copy constructor
+ * @param org the original to copy from
+ * @param copyTransforms true if the list of matrix concats should be cloned, too
+ */
+ public PSState(PSState org, boolean copyTransforms) {
+ this.transform = (AffineTransform)org.transform.clone();
+ if (copyTransforms) {
+ this.transformConcatList.addAll(org.transformConcatList);
+ }
+ this.linecap = org.linecap;
+ this.linewidth = org.linewidth;
+ this.dashpattern = org.dashpattern;
+ this.rgbColor = org.rgbColor;
+ this.fontname = org.fontname;
+ this.fontsize = org.fontsize;
+ }
/**
* Returns the transform.
return this.transform;
}
+ /**
+ * 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 the check against
+ * @return true if the new transform is different then the current transform
+ */
+ public boolean checkTransform(AffineTransform tf) {
+ return !tf.equals(this.transform);
+ }
+
/**
* Concats the given transformation matrix with the current one.
* @param transform The new transformation matrix
*/
public void concatMatrix(AffineTransform transform) {
+ this.transformConcatList.add(transform);
this.transform.concatenate(transform);
}
/**
- * @see java.lang.Object#clone()
+ * Establishes the specified line cap.
+ * @param value line cap (0, 1 or 2) as defined by the setlinecap command
+ * @return true if the line cap changed compared to the previous setting
*/
- public Object clone() {
- try {
- return super.clone();
- } catch (CloneNotSupportedException e) {
- // this shouldn't happen, since we are Cloneable
- throw new InternalError();
+ public boolean useLineCap(int value) {
+ if (linecap != value) {
+ linecap = value;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Establishes the specified line width.
+ * @param value line width as defined by the setlinewidth command
+ * @return true if the line width changed compared to the previous setting
+ */
+ public boolean useLineWidth(double value) {
+ if (linewidth != value) {
+ linewidth = value;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Establishes the specified dash.
+ * @param pattern dash pattern as defined by the setdash command
+ * @return true if the dash pattern changed compared to the previous setting
+ */
+ public boolean useDash(String pattern) {
+ if (!dashpattern.equals(pattern)) {
+ dashpattern = pattern;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Establishes the specified color (RGB).
+ * @param value color as defined by the setrgbcolor command
+ * @return true if the color changed compared to the previous setting
+ */
+ public boolean useColor(Color value) {
+ if (!rgbColor.equals(value)) {
+ rgbColor = value;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Establishes the specified font and size.
+ * @param name name of the font for the "F" command (see FOP Std Proc Set)
+ * @param size size of the font
+ * @return true if the font changed compared to the previous setting
+ */
+ public boolean useFont(String name, float size) {
+ if (name == null) {
+ throw new NullPointerException("font name must not be null");
+ }
+ if (fontname == null || !fontname.equals(name) || fontsize != size) {
+ fontname = name;
+ fontsize = size;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Reestablishes the graphics state represented by this instance by issueing the
+ * necessary commands.
+ * @param gen The generator to use for output
+ * @exception IOException In case of an I/O problem
+ */
+ public void reestablish(PSGenerator gen) throws IOException {
+ for (int i = 0, len = transformConcatList.size(); i < len; i++) {
+ gen.concatMatrix((AffineTransform)transformConcatList.get(i));
+ }
+ gen.useLineCap(linecap);
+ gen.useLineWidth(linewidth);
+ gen.useDash(dashpattern);
+ gen.useRGBColor(rgbColor);
+ if (fontname != null) {
+ gen.useFont(fontname, fontsize);
}
}
import org.apache.commons.logging.LogFactory;
/**
- * PostScript XML handler.
+ * PostScript XML handler for SVG. Uses Apache Batik for SVG processing.
* This handler handles XML for foreign objects when rendering to PostScript.
* It renders SVG to the PostScript document using the PSGraphics2D.
* The properties from the PostScript renderer are subject to change.
*
* @author <a href="mailto:fop-dev@xml.apache.org">Apache XML FOP Development Team</a>
- * @version $Id: PSXMLHandler.java,v 1.4 2003/03/11 08:42:24 jeremias Exp $
+ * @version $Id$
*/
public class PSXMLHandler implements XMLHandler {
builder = null;
try {
- gen.writeln("%SVG graphic start ---");
+ gen.commentln("%FOPBeginSVG");
gen.saveGraphicsState();
/*
* Clip to the svg area.
* an fo:block-container
*/
gen.writeln("newpath");
- gen.defineRect(xOffset, yOffset, w, h);
+ gen.defineRect(xOffset / 1000f, yOffset / 1000f,
+ psInfo.getWidth() / 1000f, psInfo.getWidth() / 1000f);
gen.writeln("clip");
// transform so that the coordinates (0,0) is from the top left
// and positive is down and to the right. (0,0) is where the
// viewBox puts it.
- gen.concatMatrix(sx, 0, 0, sy, xOffset, yOffset);
+ gen.concatMatrix(sx, 0, 0, sy, xOffset / 1000f, yOffset / 1000f);
SVGSVGElement svg = ((SVGDocument)doc).getRootElement();
AffineTransform at = ViewBox.getPreserveAspectRatioTransform(svg,
- w / 1000f, h / 1000f);
- if (!at.isIdentity()) {
+ psInfo.getWidth() / 1000f, psInfo.getHeight() / 1000f);
+ if (false && !at.isIdentity()) {
double[] vals = new double[6];
at.getMatrix(vals);
gen.concatMatrix(vals);
psInfo.psGenerator.restoreGraphicsState();
//psInfo.pdfState.pop();
- gen.writeln("%SVG graphic end ---");
+ gen.commentln("%FOPEndSVG");
} catch (IOException ioe) {
log.error("SVG graphic could not be rendered: "
+ ioe.getMessage(), ioe);