/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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: GraphicsObject.java 1761021 2016-09-16 11:40:57Z ssteiner $ */

package org.apache.fop.afp.modca;

import java.awt.Color;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;

import org.apache.xmlgraphics.java2d.color.ColorConverter;
import org.apache.xmlgraphics.java2d.color.ColorUtil;

import org.apache.fop.afp.AFPDataObjectInfo;
import org.apache.fop.afp.AFPObjectAreaInfo;
import org.apache.fop.afp.Factory;
import org.apache.fop.afp.StructuredData;
import org.apache.fop.afp.fonts.CharacterSet;
import org.apache.fop.afp.goca.GraphicsAreaBegin;
import org.apache.fop.afp.goca.GraphicsAreaEnd;
import org.apache.fop.afp.goca.GraphicsBox;
import org.apache.fop.afp.goca.GraphicsChainedSegment;
import org.apache.fop.afp.goca.GraphicsCharacterString;
import org.apache.fop.afp.goca.GraphicsData;
import org.apache.fop.afp.goca.GraphicsEndProlog;
import org.apache.fop.afp.goca.GraphicsFillet;
import org.apache.fop.afp.goca.GraphicsFullArc;
import org.apache.fop.afp.goca.GraphicsImage;
import org.apache.fop.afp.goca.GraphicsLine;
import org.apache.fop.afp.goca.GraphicsSetArcParameters;
import org.apache.fop.afp.goca.GraphicsSetCharacterSet;
import org.apache.fop.afp.goca.GraphicsSetCurrentPosition;
import org.apache.fop.afp.goca.GraphicsSetFractionalLineWidth;
import org.apache.fop.afp.goca.GraphicsSetLineType;
import org.apache.fop.afp.goca.GraphicsSetLineWidth;
import org.apache.fop.afp.goca.GraphicsSetPatternSymbol;
import org.apache.fop.afp.goca.GraphicsSetProcessColor;

Top-level GOCA graphics object. Acts as container and factory of all other graphic objects
/** * Top-level GOCA graphics object. * * Acts as container and factory of all other graphic objects */
public class GraphicsObject extends AbstractDataObject {
the graphics data
/** the graphics data */
private GraphicsData currentData;
list of objects contained within this container
/** list of objects contained within this container */
protected List<GraphicsData> objects = new java.util.ArrayList<GraphicsData>();
the graphics state
/** the graphics state */
private final GraphicsState graphicsState = new GraphicsState();
color converter
/** color converter */
private ColorConverter colorConverter;
Default constructor
Params:
  • factory – the object factory
  • name – the name of graphics object
/** * Default constructor * * @param factory the object factory * @param name the name of graphics object */
public GraphicsObject(Factory factory, String name) { super(factory, name); }
{@inheritDoc}
/** {@inheritDoc} */
@Override public void setViewport(AFPDataObjectInfo dataObjectInfo) { super.setViewport(dataObjectInfo); AFPObjectAreaInfo objectAreaInfo = dataObjectInfo.getObjectAreaInfo(); int width = objectAreaInfo.getWidth(); int height = objectAreaInfo.getHeight(); int widthRes = objectAreaInfo.getWidthRes(); int heightRes = objectAreaInfo.getHeightRes(); final int leftEdge = 0; final int topEdge = 0; GraphicsDataDescriptor graphicsDataDescriptor = factory.createGraphicsDataDescriptor( leftEdge, width, topEdge, height, widthRes, heightRes); getObjectEnvironmentGroup().setDataDescriptor(graphicsDataDescriptor); }
Params:
  • object – the structured data
/** @param object the structured data */
public void addObject(StructuredData object) { if (currentData == null) { newData(); } else if (currentData.getDataLength() + object.getDataLength() >= GraphicsData.MAX_DATA_LEN) { // graphics data full so transfer current incomplete segment to new data GraphicsChainedSegment currentSegment = (GraphicsChainedSegment)currentData.removeCurrentSegment(); currentSegment.setName(newData().createSegmentName()); currentData.addSegment(currentSegment); } currentData.addObject(object); }
Gets the current graphics data, creating a new one if necessary
Returns:the current graphics data
/** * Gets the current graphics data, creating a new one if necessary * * @return the current graphics data */
private GraphicsData getData() { if (this.currentData == null) { return newData(); } return this.currentData; }
Creates a new graphics data
Returns:a newly created graphics data
/** * Creates a new graphics data * * @return a newly created graphics data */
private GraphicsData newData() { if (currentData != null) { currentData.setComplete(true); } this.currentData = factory.createGraphicsData(); objects.add(currentData); return currentData; }
Sets the current color
Params:
  • color – the active color to use
/** * Sets the current color * * @param color the active color to use */
public void setColor(Color color) { if (!ColorUtil.isSameColor(color, graphicsState.color)) { addObject(new GraphicsSetProcessColor(colorConverter.convert(color))); graphicsState.color = color; } }
Sets the color converter
Params:
  • colorConverter – ColorConverter to filter the color when creating a GraphicsSetProcessColor.
/** * Sets the color converter * * @param colorConverter ColorConverter to filter the color * when creating a GraphicsSetProcessColor. */
public void setColorConverter(ColorConverter colorConverter) { this.colorConverter = colorConverter; }
Sets the current position
Params:
  • coords – the x and y coordinates of the current position
/** * Sets the current position * * @param coords the x and y coordinates of the current position */
public void setCurrentPosition(int[] coords) { addObject(new GraphicsSetCurrentPosition(coords)); }
Sets the line width
Params:
  • lineWidth – the line width multiplier
/** * Sets the line width * * @param lineWidth the line width multiplier */
public void setLineWidth(int lineWidth) { if ((float) lineWidth != graphicsState.lineWidth) { addObject(new GraphicsSetLineWidth(lineWidth)); graphicsState.lineWidth = (float) lineWidth; } }
Sets the line width
Params:
  • lineWidth – the line width multiplier
/** * Sets the line width * * @param lineWidth the line width multiplier */
public void setLineWidth(float lineWidth) { float epsilon = Float.intBitsToFloat(0x00800000); // Float.MIN_NORMAL (JDK1.6) if (Math.abs(graphicsState.lineWidth - lineWidth) > epsilon) { addObject(new GraphicsSetFractionalLineWidth(lineWidth)); graphicsState.lineWidth = lineWidth; } }
Sets the line type
Params:
  • lineType – the line type
/** * Sets the line type * * @param lineType the line type */
public void setLineType(byte lineType) { if (lineType != graphicsState.lineType) { addObject(new GraphicsSetLineType(lineType)); graphicsState.lineType = lineType; } }
Sets whether the following shape is to be filled.
Params:
  • fill – true if the following shape is to be filled
/** * Sets whether the following shape is to be filled. * * @param fill true if the following shape is to be filled */
public void setFill(boolean fill) { setPatternSymbol(fill ? GraphicsSetPatternSymbol.SOLID_FILL : GraphicsSetPatternSymbol.NO_FILL); }
Sets the fill pattern of the next shape.
Params:
  • patternSymbol – the fill pattern of the next shape
/** * Sets the fill pattern of the next shape. * * @param patternSymbol the fill pattern of the next shape */
public void setPatternSymbol(byte patternSymbol) { if (patternSymbol != graphicsState.patternSymbol) { addObject(new GraphicsSetPatternSymbol(patternSymbol)); graphicsState.patternSymbol = patternSymbol; } }
Sets the character set to use
Params:
  • characterSet – the character set (font) reference
/** * Sets the character set to use * * @param characterSet the character set (font) reference */
public void setCharacterSet(int characterSet) { if (characterSet != graphicsState.characterSet) { graphicsState.characterSet = characterSet; } addObject(new GraphicsSetCharacterSet(characterSet)); }
Adds a line at the given x/y coordinates
Params:
  • coords – the x/y coordinates (can be a series)
/** * Adds a line at the given x/y coordinates * * @param coords the x/y coordinates (can be a series) */
public void addLine(int[] coords) { addLine(coords, false); }
Adds a line at the given x/y coordinates
Params:
  • coords – the x/y coordinates (can be a series)
  • relative – relative true for a line at current position (relative to)
/** * Adds a line at the given x/y coordinates * * @param coords the x/y coordinates (can be a series) * @param relative relative true for a line at current position (relative to) */
public void addLine(int[] coords, boolean relative) { addObject(new GraphicsLine(coords, relative)); }
Adds a box at the given coordinates
Params:
  • coords – the x/y coordinates
/** * Adds a box at the given coordinates * * @param coords the x/y coordinates */
public void addBox(int[] coords) { addObject(new GraphicsBox(coords)); }
Adds a fillet (curve) at the given coordinates
Params:
  • coords – the x/y coordinates
/** * Adds a fillet (curve) at the given coordinates * * @param coords the x/y coordinates */
public void addFillet(int[] coords) { addFillet(coords, false); }
Adds a fillet (curve) at the given coordinates
Params:
  • coords – the x/y coordinates
  • relative – relative true for a fillet (curve) at current position (relative to)
/** * Adds a fillet (curve) at the given coordinates * * @param coords the x/y coordinates * @param relative relative true for a fillet (curve) at current position (relative to) */
public void addFillet(int[] coords, boolean relative) { addObject(new GraphicsFillet(coords, relative)); }
Sets the arc parameters
Params:
  • xmaj – the maximum value of the x coordinate
  • ymin – the minimum value of the y coordinate
  • xmin – the minimum value of the x coordinate
  • ymaj – the maximum value of the y coordinate
/** * Sets the arc parameters * * @param xmaj the maximum value of the x coordinate * @param ymin the minimum value of the y coordinate * @param xmin the minimum value of the x coordinate * @param ymaj the maximum value of the y coordinate */
public void setArcParams(int xmaj, int ymin, int xmin, int ymaj) { addObject(new GraphicsSetArcParameters(xmaj, ymin, xmin, ymaj)); }
Adds a full arc
Params:
  • x – the x coordinate
  • y – the y coordinate
  • mh – the integer portion of the multiplier
  • mhr – the fractional portion of the multiplier
/** * Adds a full arc * * @param x the x coordinate * @param y the y coordinate * @param mh the integer portion of the multiplier * @param mhr the fractional portion of the multiplier */
public void addFullArc(int x, int y, int mh, int mhr) { addObject(new GraphicsFullArc(x, y, mh, mhr)); }
Adds an image
Params:
  • x – the x coordinate
  • y – the y coordinate
  • width – the image width
  • height – the image height
  • imgData – the image data
/** * Adds an image * * @param x the x coordinate * @param y the y coordinate * @param width the image width * @param height the image height * @param imgData the image data */
public void addImage(int x, int y, int width, int height, byte[] imgData) { addObject(new GraphicsImage(x, y, width, height, imgData)); }
Adds a string
Params:
  • str – the string
  • x – the x coordinate
  • y – the y coordinate
  • charSet – the character set associated with the string
/** * Adds a string * * @param str the string * @param x the x coordinate * @param y the y coordinate * @param charSet the character set associated with the string */
public void addString(String str, int x, int y, CharacterSet charSet) { addObject(new GraphicsCharacterString(str, x, y, charSet)); }
Begins a graphics area (start of fill)
/** * Begins a graphics area (start of fill) */
public void beginArea() { addObject(new GraphicsAreaBegin()); }
Ends a graphics area (end of fill)
/** * Ends a graphics area (end of fill) */
public void endArea() { addObject(new GraphicsAreaEnd()); }
Ends the prolog.
/** * Ends the prolog. */
public void endProlog() { addObject(new GraphicsEndProlog()); }
{@inheritDoc}
/** {@inheritDoc} */
@Override public String toString() { return "GraphicsObject: " + getName(); }
Creates a new graphics segment
/** * Creates a new graphics segment */
public void newSegment() { getData().newSegment(); graphicsState.lineWidth = 0; //Looks like a new segment invalidates the graphics state }
{@inheritDoc}
/** {@inheritDoc} */
@Override public void setComplete(boolean complete) { for (GraphicsData completedObject : objects) { completedObject.setComplete(true); } super.setComplete(complete); }
{@inheritDoc}
/** {@inheritDoc} */
@Override protected void writeStart(OutputStream os) throws IOException { super.writeStart(os); byte[] data = new byte[17]; copySF(data, Type.BEGIN, Category.GRAPHICS); os.write(data); }
{@inheritDoc}
/** {@inheritDoc} */
@Override protected void writeContent(OutputStream os) throws IOException { super.writeContent(os); writeObjects(objects, os); }
{@inheritDoc}
/** {@inheritDoc} */
@Override protected void writeEnd(OutputStream os) throws IOException { byte[] data = new byte[17]; copySF(data, Type.END, Category.GRAPHICS); os.write(data); }
the internal graphics state
/** the internal graphics state */
private static final class GraphicsState { private GraphicsState() { }
the current color
/** the current color */
private Color color;
the current line type
/** the current line type */
private byte lineType;
the current line width
/** the current line width */
private float lineWidth;
the current fill pattern
/** the current fill pattern */
private byte patternSymbol;
the current character set
/** the current character set */
private int characterSet; } }