浏览代码

AFP Renderer as per IP clearance (http://mail-archives.apache.org/mod_mbox/xmlgraphics-general/200604.mbox/%3c20060426085421.B456.DEV@jeremias-maerki.ch%3e) plus some further corrections and changes made by manuel@apache.org since

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@397562 13f79535-47bb-0310-9956-ffa450edef68
tags/fop-0_93
Manuel Mall 18 年前
父节点
当前提交
0040a29ecc
共有 63 个文件被更改,包括 12948 次插入0 次删除
  1. 1
    0
      src/sandbox/META-INF/services/org.apache.fop.render.Renderer
  2. 110
    0
      src/sandbox/org/apache/fop/render/afp/AFPFontAttributes.java
  3. 169
    0
      src/sandbox/org/apache/fop/render/afp/AFPFontColor.java
  4. 1796
    0
      src/sandbox/org/apache/fop/render/afp/AFPRenderer.java
  5. 51
    0
      src/sandbox/org/apache/fop/render/afp/AFPRendererMaker.java
  6. 45
    0
      src/sandbox/org/apache/fop/render/afp/exceptions/FontRuntimeException.java
  7. 108
    0
      src/sandbox/org/apache/fop/render/afp/exceptions/NestedRuntimeException.java
  8. 45
    0
      src/sandbox/org/apache/fop/render/afp/exceptions/RendererRuntimeException.java
  9. 60
    0
      src/sandbox/org/apache/fop/render/afp/extensions/AFPAttribute.java
  10. 109
    0
      src/sandbox/org/apache/fop/render/afp/extensions/AFPElementMapping.java
  11. 90
    0
      src/sandbox/org/apache/fop/render/afp/extensions/AFPPageSetup.java
  12. 47
    0
      src/sandbox/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java
  13. 120
    0
      src/sandbox/org/apache/fop/render/afp/extensions/AbstractAFPExtensionObject.java
  14. 91
    0
      src/sandbox/org/apache/fop/render/afp/fonts/AFPFont.java
  15. 58
    0
      src/sandbox/org/apache/fop/render/afp/fonts/AFPFontInfo.java
  16. 608
    0
      src/sandbox/org/apache/fop/render/afp/fonts/AFPFontReader.java
  17. 322
    0
      src/sandbox/org/apache/fop/render/afp/fonts/CharacterSet.java
  18. 275
    0
      src/sandbox/org/apache/fop/render/afp/fonts/CharacterSetOrientation.java
  19. 138
    0
      src/sandbox/org/apache/fop/render/afp/fonts/FopCharacterSet.java
  20. 193
    0
      src/sandbox/org/apache/fop/render/afp/fonts/OutlineFont.java
  21. 243
    0
      src/sandbox/org/apache/fop/render/afp/fonts/RasterFont.java
  22. 37
    0
      src/sandbox/org/apache/fop/render/afp/modca/AFPConstants.java
  23. 650
    0
      src/sandbox/org/apache/fop/render/afp/modca/AFPDataStream.java
  24. 65
    0
      src/sandbox/org/apache/fop/render/afp/modca/AbstractAFPObject.java
  25. 409
    0
      src/sandbox/org/apache/fop/render/afp/modca/AbstractPageObject.java
  26. 345
    0
      src/sandbox/org/apache/fop/render/afp/modca/ActiveEnvironmentGroup.java
  27. 213
    0
      src/sandbox/org/apache/fop/render/afp/modca/Document.java
  28. 74
    0
      src/sandbox/org/apache/fop/render/afp/modca/EndPageGroup.java
  29. 190
    0
      src/sandbox/org/apache/fop/render/afp/modca/IMImageObject.java
  30. 193
    0
      src/sandbox/org/apache/fop/render/afp/modca/ImageCellPosition.java
  31. 294
    0
      src/sandbox/org/apache/fop/render/afp/modca/ImageContent.java
  32. 108
    0
      src/sandbox/org/apache/fop/render/afp/modca/ImageDataDescriptor.java
  33. 146
    0
      src/sandbox/org/apache/fop/render/afp/modca/ImageInputDescriptor.java
  34. 271
    0
      src/sandbox/org/apache/fop/render/afp/modca/ImageObject.java
  35. 207
    0
      src/sandbox/org/apache/fop/render/afp/modca/ImageOutputControl.java
  36. 91
    0
      src/sandbox/org/apache/fop/render/afp/modca/ImageRasterData.java
  37. 762
    0
      src/sandbox/org/apache/fop/render/afp/modca/ImageRasterPattern.java
  38. 225
    0
      src/sandbox/org/apache/fop/render/afp/modca/ImageSegment.java
  39. 94
    0
      src/sandbox/org/apache/fop/render/afp/modca/ImageSizeParameter.java
  40. 171
    0
      src/sandbox/org/apache/fop/render/afp/modca/IncludeObject.java
  41. 156
    0
      src/sandbox/org/apache/fop/render/afp/modca/IncludePageOverlay.java
  42. 114
    0
      src/sandbox/org/apache/fop/render/afp/modca/IncludePageSegment.java
  43. 81
    0
      src/sandbox/org/apache/fop/render/afp/modca/InvokeMediumMap.java
  44. 298
    0
      src/sandbox/org/apache/fop/render/afp/modca/MapCodedFont.java
  45. 157
    0
      src/sandbox/org/apache/fop/render/afp/modca/MapPageOverlay.java
  46. 31
    0
      src/sandbox/org/apache/fop/render/afp/modca/MaximumSizeExceededException.java
  47. 106
    0
      src/sandbox/org/apache/fop/render/afp/modca/ObjectAreaDescriptor.java
  48. 111
    0
      src/sandbox/org/apache/fop/render/afp/modca/ObjectAreaPosition.java
  49. 194
    0
      src/sandbox/org/apache/fop/render/afp/modca/ObjectEnvironmentGroup.java
  50. 130
    0
      src/sandbox/org/apache/fop/render/afp/modca/Overlay.java
  51. 97
    0
      src/sandbox/org/apache/fop/render/afp/modca/PageDescriptor.java
  52. 207
    0
      src/sandbox/org/apache/fop/render/afp/modca/PageGroup.java
  53. 185
    0
      src/sandbox/org/apache/fop/render/afp/modca/PageObject.java
  54. 598
    0
      src/sandbox/org/apache/fop/render/afp/modca/PresentationTextData.java
  55. 113
    0
      src/sandbox/org/apache/fop/render/afp/modca/PresentationTextDescriptor.java
  56. 330
    0
      src/sandbox/org/apache/fop/render/afp/modca/PresentationTextObject.java
  57. 151
    0
      src/sandbox/org/apache/fop/render/afp/modca/ResourceGroup.java
  58. 148
    0
      src/sandbox/org/apache/fop/render/afp/modca/TagLogicalElement.java
  59. 60
    0
      src/sandbox/org/apache/fop/render/afp/modca/TagLogicalElementBean.java
  60. 131
    0
      src/sandbox/org/apache/fop/render/afp/tools/BinaryUtils.java
  61. 112
    0
      src/sandbox/org/apache/fop/render/afp/tools/DTDEntityResolver.java
  62. 80
    0
      src/sandbox/org/apache/fop/render/afp/tools/StringUtils.java
  63. 134
    0
      src/sandbox/org/apache/fop/render/afp/tools/StructuredFieldReader.java

+ 1
- 0
src/sandbox/META-INF/services/org.apache.fop.render.Renderer 查看文件

@@ -1,2 +1,3 @@
org.apache.fop.render.afp.AFPRendererMaker
org.apache.fop.render.pcl.PCLRendererMaker
org.apache.fop.render.svg.SVGRendererMaker

+ 110
- 0
src/sandbox/org/apache/fop/render/afp/AFPFontAttributes.java 查看文件

@@ -0,0 +1,110 @@
/*
* Copyright 2006 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.afp;

import org.apache.fop.render.afp.fonts.AFPFont;
import org.apache.fop.render.afp.tools.BinaryUtils;

/**
* This class encapsulates the font atributes that need to be included
* in the AFP data stream. This class does not assist in converting the
* font attributes to AFP code pages and character set values.
*
*/
public class AFPFontAttributes {

/**
* The font reference byte
*/
private byte _fontReference;

/**
* The font key
*/
private String _fontKey;

/**
* The font
*/
private AFPFont _font;

/**
* The point size
*/
private int _pointSize;

/**
* Constructor for the AFPFontAttributes
* @param fontKey the font key
* @param font the font
* @param pointSize the point size
*/
public AFPFontAttributes(

String fontKey,
AFPFont font,
int pointSize) {

_fontKey = fontKey;
_font = font;
_pointSize = pointSize;

}
/**
* @return the font
*/
public AFPFont getFont() {
return _font;
}

/**
* @return the FontKey attribute
*/
public String getFontKey() {

return _fontKey + _pointSize;

}

/**
* @return the point size attribute
*/
public int getPointSize() {
return _pointSize;
}

/**
* @return the FontReference attribute
*/
public byte getFontReference() {
return _fontReference;
}

/**
* Sets the FontReference attribute
* @param fontReference the FontReference to set
*/
public void setFontReference(int fontReference) {

String id = String.valueOf(fontReference);
_fontReference = BinaryUtils.convert(id)[0];

}

}

+ 169
- 0
src/sandbox/org/apache/fop/render/afp/AFPFontColor.java 查看文件

@@ -0,0 +1,169 @@
/*
* Copyright 2006 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.afp;

import java.awt.Color;
import org.apache.fop.datatypes.ColorType;

/**
* AFP only supports very basic colours and this object provides a simple
* bean for the colour attributes.
*
*/
public class AFPFontColor {

/**
* Red value.
*/
private int _red = 0;

/**
* Green value.
*/
private int _green = 0;

/**
* Blue value.
*/
private int _blue = 0;

/**
* Constructor for the AFPColor Object
* @param red The red color intensity (0-255)
* @param green The green color intensity (0-255)
* @param blue The blue color intensity (0-255)
*/
public AFPFontColor(int red, int green, int blue) {

_red = red;
_green = green;
_blue = blue;

}

/**
* Constructor for the AFPColor Object
* @param col the org.apache.fop.datatypes.ColorType object
*/
public AFPFontColor(ColorType col) {

_red = (int)(col.getRed() * 255);
_green = (int)(col.getGreen() * 255);
_blue = (int)(col.getBlue() * 255);

}

/**
* Constructor for the AFPColor Object
* @param col The java.awt.Color object
*/
public AFPFontColor(Color col) {

_red = col.getRed();
_green = col.getGreen();
_blue = col.getBlue();

}

/**
* Returns the blue attribute
* @return int
*/
public int getBlue() {
return _blue;
}

/**
* Returns the green attribute
* @return int
*/
public int getGreen() {
return _green;
}

/**
* Returns the red attribute
* @return int
*/
public int getRed() {
return _red;
}

/**
* Sets the blue attribute
* @param blue The blue value to set
*/
public void setBlue(int blue) {
_blue = blue;
}

/**
* Sets the green attribute
* @param green The green value to set
*/
public void setGreen(int green) {
_green = green;
}

/**
* Sets the red attribute
* @param red The red value to set
*/
public void setRed(int red) {
_red = red;
}

/**
* Sets this color object to the same values
* as the given object.
* @param col the source color
*/
public void setTo(AFPFontColor col) {
_red = col.getRed();
_green = col.getGreen();
_blue = col.getBlue();
}

/**
* Checks whether this object is equal to the parameter passed
* as an argument. If the parameter is an instance of AFPColor
* then the value are compared, otherwise the generalized equals
* method is invoked on the parent class.
*
* @param obj the object to compare
* @return boolean true if the object is equal
*/
public boolean equals(Object obj) {

if (obj instanceof AFPFontColor) {
AFPFontColor c = (AFPFontColor) obj;
if (c.getRed() == _red
&& c.getGreen() == _green
&& c.getBlue() == _blue) {
return true;
} else {
return false;
}
} else {
return super.equals(obj);
}

}

}

+ 1796
- 0
src/sandbox/org/apache/fop/render/afp/AFPRenderer.java
文件差异内容过多而无法显示
查看文件


+ 51
- 0
src/sandbox/org/apache/fop/render/afp/AFPRendererMaker.java 查看文件

@@ -0,0 +1,51 @@
/*
* Copyright 2006 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.afp;

import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.MimeConstants;
import org.apache.fop.render.AbstractRendererMaker;
import org.apache.fop.render.Renderer;

/**
* RendererMaker for the AFP Renderer.
*/
public class AFPRendererMaker extends AbstractRendererMaker {

private static final String[] MIMES = new String[] {
MimeConstants.MIME_AFP,
MimeConstants.MIME_AFP_ALT};


/**@see org.apache.fop.render.AbstractRendererMaker */
public Renderer makeRenderer(FOUserAgent ua) {
return new AFPRenderer();
}

/** @see org.apache.fop.render.AbstractRendererMaker#needsOutputStream() */
public boolean needsOutputStream() {
return true;
}

/** @see org.apache.fop.render.AbstractRendererMaker#getSupportedMimeTypes() */
public String[] getSupportedMimeTypes() {
return MIMES;
}

}

+ 45
- 0
src/sandbox/org/apache/fop/render/afp/exceptions/FontRuntimeException.java 查看文件

@@ -0,0 +1,45 @@
/*
* Copyright 2006 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.afp.exceptions;

/**
* A runtime exception for handling fatal errors in processing fonts.
* <p/>
*/
public class FontRuntimeException extends NestedRuntimeException {

/**
* Constructs a FontRuntimeException with the specified message.
* @param msg the exception mesaage
*/
public FontRuntimeException(String msg) {
super(msg);
}

/**
* Constructs a FontRuntimeException with the specified message
* wrapping the underlying exception.
* @param msg the exception mesaage
* @param t the underlying exception
*/
public FontRuntimeException(String msg, Throwable t) {
super(msg, t);
}

}

+ 108
- 0
src/sandbox/org/apache/fop/render/afp/exceptions/NestedRuntimeException.java 查看文件

@@ -0,0 +1,108 @@
/*
* Copyright 2006 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.afp.exceptions;

import java.io.PrintStream;
import java.io.PrintWriter;

/**
* Handy class for wrapping runtime Exceptions with a root cause.
* This technique is no longer necessary in Java 1.4, which provides
* built-in support for exception nesting. Thus exceptions in applications
* written to use Java 1.4 need not extend this class.
*
*/
public abstract class NestedRuntimeException extends RuntimeException {

/** Root cause of this nested exception */
private Throwable _underlyingException;

/**
* Construct a <code>NestedRuntimeException</code> with the specified detail message.
* @param msg The detail message.
*/
public NestedRuntimeException(String msg) {
super(msg);
}

/**
* Construct a <code>NestedRuntimeException</code> with the specified
* detail message and nested exception.
* @param msg The detail message.
* @param t The nested exception.
*/
public NestedRuntimeException(String msg, Throwable t) {
super(msg);
_underlyingException = t;

}

/**
* Gets the original triggering exception
* @return The original exception as a throwable.
*/
public Throwable getUnderlyingException() {

return _underlyingException;

}

/**
* Return the detail message, including the message from the nested
* exception if there is one.
* @return The detail message.
*/
public String getMessage() {

if (_underlyingException == null) {
return super.getMessage();
} else {
return super.getMessage()
+ "; nested exception is "
+ _underlyingException.getClass().getName();
}

}

/**
* Print the composite message and the embedded stack trace to the specified stream.
* @param ps the print stream
*/
public void printStackTrace(PrintStream ps) {
if (_underlyingException == null) {
super.printStackTrace(ps);
} else {
ps.println(this);
_underlyingException.printStackTrace(ps);
}
}

/**
* Print the composite message and the embedded stack trace to the specified writer.
* @param pw the print writer
*/
public void printStackTrace(PrintWriter pw) {
if (_underlyingException == null) {
super.printStackTrace(pw);
} else {
pw.println(this);
_underlyingException.printStackTrace(pw);
}
}

}

+ 45
- 0
src/sandbox/org/apache/fop/render/afp/exceptions/RendererRuntimeException.java 查看文件

@@ -0,0 +1,45 @@
/*
* Copyright 2006 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.afp.exceptions;

/**
* A runtime exception for handling fatal errors in rendering.
* <p/>
*/
public class RendererRuntimeException extends NestedRuntimeException {

/**
* Constructs a RendererRuntimeException with the specified message.
* @param msg the exception mesaage
*/
public RendererRuntimeException(String msg) {
super(msg);
}

/**
* Constructs a RendererRuntimeException with the specified message
* wrapping the underlying exception.
* @param msg the exception mesaage
* @param t the underlying exception
*/
public RendererRuntimeException(String msg, Throwable t) {
super(msg, t);
}

}

+ 60
- 0
src/sandbox/org/apache/fop/render/afp/extensions/AFPAttribute.java 查看文件

@@ -0,0 +1,60 @@
/*
* Copyright 2006 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.afp.extensions;

import org.apache.fop.apps.FOPException;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.properties.Property;
import org.apache.fop.fo.properties.StringProperty;

/**
* This class extends the org.apache.fop.fo.StringProperty.Maker inner class
* in order to provide a static property maker. The object faciliates
* extraction of attributes from formatted objects based on the static list
* as defined in the AFPElementMapping implementation.
* <p/>
*/
public class AFPAttribute extends StringProperty.Maker {

/**
* The attribute property.
*/
private Property _property;

/**
* Constructor for the AFPAttribute.
* @param name The attribute name
*/
protected AFPAttribute(String name) {
super(0);
_property = null;
}

/**
* Overide the make method to return the property object
* @return property The property object.
*/
public Property make(PropertyList propertyList) {
if (_property == null) {
_property = make(propertyList, "", propertyList.getParentFObj());
}
return _property;
}

}

+ 109
- 0
src/sandbox/org/apache/fop/render/afp/extensions/AFPElementMapping.java 查看文件

@@ -0,0 +1,109 @@
/*
* Copyright 2006 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.afp.extensions;

import java.util.HashMap;

import org.apache.fop.fo.ElementMapping;
import org.apache.fop.fo.FONode;


/**
* AFPElementMapping object provides the ability to extract information
* from the formatted object that reside in the afp namespace. This is used
* for custom AFP extensions not supported by the FO schema. Examples include
* adding overlays or indexing a document using the tag logical element
* structured field.
* <p/>
*/
public class AFPElementMapping extends ElementMapping {

public static final String PAGE = "page";

public static final String PAGE_GROUP = "page-group";

public static final String TAG_LOGICAL_ELEMENT = "tag-logical-element";

public static final String INCLUDE_PAGE_OVERLAY = "include-page-overlay";

public static final String INCLUDE_PAGE_SEGMENT = "include-page-segment";

/**
* The namespace used for AFP extensions
*/
public static final String NAMESPACE = "http://org.apache.fop/extensions/afp";

/**
* The usual namespace prefix used for AFP extensions
*/
public static final String NAMESPACE_PREFIX = "afp";

/** Main constructor */
public AFPElementMapping() {
this.namespaceURI = NAMESPACE;
}

/**
* Private static synchronized method to set up the element and atribute
* HashMaps, this defines what elements and attributes are extracted.
*/
protected void initialize() {

if (foObjs == null) {
foObjs = new HashMap();
foObjs.put(PAGE, new AFPPageSetupMaker());
// foObjs.put(PAGE_GROUP, new AFPMaker());
foObjs.put(
TAG_LOGICAL_ELEMENT,
new AFPTagLogicalElementMaker());
foObjs.put(
INCLUDE_PAGE_SEGMENT,
new AFPIncludePageSegmentMaker());
foObjs.put(
INCLUDE_PAGE_OVERLAY,
new AFPIncludePageOverlayMaker());
}

}

static class AFPPageSetupMaker extends ElementMapping.Maker {
public FONode make(FONode parent) {
return new AFPPageSetupElement(parent);
}
}

static class AFPIncludePageOverlayMaker extends ElementMapping.Maker {
public FONode make(FONode parent) {
return new AFPElement(parent, INCLUDE_PAGE_OVERLAY);
}
}

static class AFPIncludePageSegmentMaker extends ElementMapping.Maker {
public FONode make(FONode parent) {
return new AFPElement(parent, INCLUDE_PAGE_SEGMENT);
}
}

static class AFPTagLogicalElementMaker extends ElementMapping.Maker {
public FONode make(FONode parent) {
return new AFPElement(parent, TAG_LOGICAL_ELEMENT);
}
}

}

+ 90
- 0
src/sandbox/org/apache/fop/render/afp/extensions/AFPPageSetup.java 查看文件

@@ -0,0 +1,90 @@
/*
* Copyright 2006 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.afp.extensions;

import java.io.Serializable;

import org.apache.fop.fo.extensions.ExtensionAttachment;

/**
* This is the pass-through value object for the PostScript extension.
*/
public class AFPPageSetup implements ExtensionAttachment, Serializable {

/** The category URI for this extension attachment. */
public static final String CATEGORY = "apache:fop:extensions:afp";

private String elementName;

private String name;

private String value;

/**
* Default constructor.
* @param name the name of the setup code object, may be null
*/
public AFPPageSetup(String name) {
this.elementName = name;
}

/** @return the name */
public String getElementName() {
return elementName;
}

/** @return the name */
public String getName() {
return name;
}

/**
* Sets the name of the setup code object.
* @param name The name to set.
*/
public void setName(String name) {
this.name = name;
}

/**
* @return the value
*/
public String getValue() {
return value;
}

/**
* Sets the value
* @param value The value name to set.
*/
public void setValue(String source) {
this.value = source;
}

/** @see org.apache.fop.fo.extensions.ExtensionAttachment#getCategory() */
public String getCategory() {
return CATEGORY;
}

/** @see java.lang.Object#toString() */
public String toString() {
return "AFPPageSetup(element-name=" + getElementName() + " name=" + getName() + ")";
}

}

+ 47
- 0
src/sandbox/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java 查看文件

@@ -0,0 +1,47 @@
/*
* Copyright 2006 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.afp.extensions;

import org.apache.fop.apps.FOPException;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.ValidationException;

/**
* Extension element for fox:ps-page-setup-code.
*/
public class AFPPageSetupElement extends AbstractAFPExtensionObject {

/**
* Main constructor
* @param parent parent FO node
*/
public AFPPageSetupElement(FONode parent) {
super(parent, "page");
}

/** @see org.apache.fop.fo.FONode#startOfNode() */
protected void startOfNode() throws FOPException {
super.startOfNode();
if (parent.getNameId() != Constants.FO_SIMPLE_PAGE_MASTER) {
throw new ValidationException(getName() + " must be a child of fo:simple-page-master.");
}
}

}

+ 120
- 0
src/sandbox/org/apache/fop/render/afp/extensions/AbstractAFPExtensionObject.java 查看文件

@@ -0,0 +1,120 @@
/*
* Copyright 2006 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.afp.extensions;

// FOP
import org.apache.fop.apps.FOPException;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.ValidationException;
import org.apache.fop.fo.extensions.ExtensionAttachment;
import org.xml.sax.Attributes;
import org.xml.sax.Locator;

/**
* Base class for the AFP-specific extension elements.
*/
public abstract class AbstractAFPExtensionObject extends FONode {

private AFPPageSetup setupCode = null;

private String _name = null;
/**
* @see org.apache.fop.fo.FONode#FONode(FONode)
* @param parent the parent formatting object
* @param name the name of the afp element
*/
public AbstractAFPExtensionObject(FONode parent, String name) {
super(parent);
_name = name;
setupCode = new AFPPageSetup(name);
}

/**
* @see org.apache.fop.fo.FONode#validateChildNode(Locator, String, String)
* here, blocks XSL FO's from having non-FO parents.
*/
protected void validateChildNode(Locator loc, String nsURI, String localName)
throws ValidationException {
if (FO_URI.equals(nsURI)) {
invalidChildError(loc, nsURI, localName);
}
}

/** @see org.apache.fop.fo.FONode */
protected void addCharacters(char[] data, int start, int length,
PropertyList pList, Locator locator) {
}

/** @see org.apache.fop.fo.FONode#getNamespaceURI() */
public String getNamespaceURI() {
return AFPElementMapping.NAMESPACE;
}

/**@see org.apache.fop.fo.FONode#getNormalNamespacePrefix() */
public String getNormalNamespacePrefix() {
return AFPElementMapping.NAMESPACE_PREFIX;
}

/** @see org.apache.fop.fo.FONode#processNode */
public void processNode(String elementName, Locator locator,
Attributes attlist, PropertyList propertyList)
throws FOPException {
String name = attlist.getValue("name");
if (name != null && name.length() > 0) {
setupCode.setName(name);
} else {
throw new FOPException(elementName + " must have a name attribute.");
}
if (AFPElementMapping.INCLUDE_PAGE_SEGMENT.equals(elementName)) {
name = attlist.getValue("src");
if (name != null && name.length() > 0) {
setupCode.setValue(name);
} else {
throw new FOPException(elementName + " must have a src attribute.");
}
}
if (AFPElementMapping.TAG_LOGICAL_ELEMENT.equals(elementName)) {
name = attlist.getValue("value");
if (name != null && name.length() > 0) {
setupCode.setValue(name);
} else {
throw new FOPException(elementName + " must have a value attribute.");
}
}
}

/** @see org.apache.fop.fo.FONode#endOfNode() */
protected void endOfNode() throws FOPException {
super.endOfNode();
}

/** @see org.apache.fop.fo.FONode#getExtensionAttachment() */
public ExtensionAttachment getExtensionAttachment() {
return this.setupCode;
}

/** @see org.apache.fop.fo.FONode#getLocalName() */
public String getLocalName() {
return _name;
}

}


+ 91
- 0
src/sandbox/org/apache/fop/render/afp/fonts/AFPFont.java 查看文件

@@ -0,0 +1,91 @@
/*
* Copyright 2006 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.afp.fonts;
import java.util.Map;
import org.apache.fop.fonts.FontType;
import org.apache.fop.fonts.Typeface;


/**
* All implemenations of AFP fonts should extend this base class,
* the object implements the FontMetrics information.
* <p/>
*/
public abstract class AFPFont extends Typeface {

/** The font name */
protected String _name;

/**
* Constructor for the base font requires the name.
* @param name the name of the font
*/
public AFPFont(String name) {

_name = name;

}

/**
* @return the name of the font.
*/
public String getFontName() {
return _name;
}

/**
* Returns the type of the font.
* @return the font type
*/
public FontType getFontType() {
return FontType.OTHER;
}

/**
* Indicates if the font has kering information.
* @return True, if kerning is available.
*/
public boolean hasKerningInfo() {
return false;
}

/**
* Returns the kerning map for the font.
* @return the kerning map
*/
public Map getKerningInfo() {
return null;
}

/**
* Returns the character set for a given size
* @param size the font size
*/
public abstract CharacterSet getCharacterSet(int size);

/**
* Determines whether this font contains a particular character/glyph.
* @param c character to check
* @return True if the character is supported, Falso otherwise
*/
public boolean hasChar(char c) {
return true;
}

}

+ 58
- 0
src/sandbox/org/apache/fop/render/afp/fonts/AFPFontInfo.java 查看文件

@@ -0,0 +1,58 @@
/*
* Copyright 2006 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.afp.fonts;

import java.util.List;

/**
* FontInfo contains meta information on fonts
*/
public class AFPFontInfo {

private AFPFont font;
private List fontTriplets;

/**
* Main constructor
* @param afpFont The AFP Font
* @param fontTriplets List of font triplets to associate with this font
*/
public AFPFontInfo(AFPFont afpFont, List fontTriplets) {
this.font = afpFont;
this.fontTriplets = fontTriplets;
}

/**
* Returns the afp font
* @return the afp font
*/
public AFPFont getAFPFont() {
return font;
}

/**
* Returns the list of font triplets associated with this font.
* @return List of font triplets
*/
public List getFontTriplets() {
return fontTriplets;
}

}


+ 608
- 0
src/sandbox/org/apache/fop/render/afp/fonts/AFPFontReader.java 查看文件

@@ -0,0 +1,608 @@
/*
* Copyright 2006 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.afp.fonts;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.render.afp.exceptions.FontRuntimeException;
import org.apache.fop.render.afp.modca.AFPConstants;
import org.apache.fop.render.afp.tools.StructuredFieldReader;

/**
* The AFPFontReader is responsible for reading the font attributes from binary
* code page files and the character set metric files. In IBM font structure, a
* code page maps each character of text to the characters in a character set.
* Each character is translated into a code point. When the character is
* printed, each code point is matched to a character ID on the code page
* specified. The character ID is then matched to the image (raster pattern or
* outline pattern) of the character in the character set specified. The image
* in the character set is the image that is printed in the document. To be a
* valid code page for a particular character set, all character IDs in the code
* page must be included in that character set. <p/>This class will read the
* font information from the binary code page files and character set metric
* files in order to determine the correct metrics to use when rendering the
* formatted object. <p/>
*
* @author <a href="mailto:pete@townsend.uk.com">Pete Townsend </a>
*/
public final class AFPFontReader {

/**
* Static logging instance
*/
protected static final Log log = LogFactory.getLog("org.apache.fop.render.afp.fonts");

/**
* Template used to convert lists to arrays.
*/
private static final CharacterSetOrientation[] EMPTY_CSO_ARRAY = new CharacterSetOrientation[0];

/** Codepage MO:DCA structured field. */
private static final byte[] CODEPAGE_SF = new byte[] { (byte) 0xD3,
(byte) 0xA8, (byte) 0x87 };

/** Character table MO:DCA structured field. */
private static final byte[] CHARACTER_TABLE_SF = new byte[] { (byte) 0xD3,
(byte) 0x8C, (byte) 0x87 };

/** Font control MO:DCA structured field. */
private static final byte[] FONT_CONTROL_SF = new byte[] { (byte) 0xD3,
(byte) 0xA7, (byte) 0x89 };

/** Font orientation MO:DCA structured field. */
private static final byte[] FONT_ORIENTATION_SF = new byte[] { (byte) 0xD3,
(byte) 0xAE, (byte) 0x89 };

/** Font position MO:DCA structured field. */
private static final byte[] FONT_POSITION_SF = new byte[] { (byte) 0xD3,
(byte) 0xAC, (byte) 0x89 };

/** Font index MO:DCA structured field. */
private static final byte[] FONT_INDEX_SF = new byte[] { (byte) 0xD3,
(byte) 0x8C, (byte) 0x89 };

/**
* The conversion factor to millipoints for 240 dpi
*/
private static final int FOP_100_DPI_FACTOR = 1;

/**
* The conversion factor to millipoints for 240 dpi
*/
private static final int FOP_240_DPI_FACTOR = 300000;

/**
* The conversion factor to millipoints for 300 dpi
*/
private static final int FOP_300_DPI_FACTOR = 240000;

/**
* The encoding to use to convert from EBCIDIC to ASCII
*/
private static final String ASCII_ENCODING = "UTF8";

/**
* The collection of code pages
*/
private static HashMap _codePages = new HashMap();

/**
* Load the font details and metrics into the CharacterSetMetric object,
* this will use the actual afp code page and character set files to load
* the object with the necessary metrics.
*
* @param characterSet the CharacterSetMetric object to populate
*/
public static void loadCharacterSetMetric(CharacterSet characterSet) {

InputStream inputStream = null;

try {

/**
* Get the code page which contains the character mapping
* information to map the unicode character id to the graphic
* chracter global identifier.
*/
String cp = new String(characterSet.getCodePage());
String path = characterSet.getPath();

HashMap codepage = (HashMap) _codePages.get(cp);

if (codepage == null) {
codepage = loadCodePage(cp, characterSet.getEncoding(), path);
_codePages.put(cp, codepage);
}

/**
* Load the character set metric information, no need to cache this
* information as it should be cached by the objects that wish to
* load character set metric information.
*/
final String characterset = characterSet.getName();

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if (classLoader == null) {
classLoader = AFPFontReader.class.getClassLoader();
}

URL url = classLoader.getResource(path);
if (url == null) {
try {
File file = new File(path);
url = file.toURL();
if (url == null) {
String msg = "CharacterSet file not found for "
+ characterset + " in classpath: " + path;
log.error(msg);
throw new FileNotFoundException(msg);
}
} catch (MalformedURLException ex) {
String msg = "CharacterSet file not found for "
+ characterset + " in classpath: " + path;
log.error(msg);
throw new FileNotFoundException(msg);
}

}

File directory = new File(url.getPath());

final String filterpattern = characterset.trim();
FilenameFilter filter = new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.startsWith(filterpattern);
}
};

File[] csfont = directory.listFiles(filter);
if (csfont.length < 1) {
String msg = "CharacterSet file search for " + characterset
+ " located " + csfont.length + " files";
log.error(msg);
throw new FileNotFoundException(msg);
} else if (csfont.length > 1) {
String msg = "CharacterSet file search for " + characterset
+ " located " + csfont.length + " files";
log.warn(msg);
}

inputStream = inputStream = csfont[0].toURL().openStream();
if (inputStream == null) {
String msg = "Failed to open character set resource "
+ characterset;
log.error(msg);
throw new FileNotFoundException(msg);
}

StructuredFieldReader sfr = new StructuredFieldReader(inputStream);

// Process D3A789 Font Control
FontControl fnc = processFontControl(sfr);

//process D3AE89 Font Orientation
CharacterSetOrientation[] csoArray = processFontOrientation(sfr);

//process D3AC89 Font Position
processFontPosition(sfr, csoArray, fnc.getDpi());

//process D38C89 Font Index (per orientation)
for (int i = 0; i < csoArray.length; i++) {
processFontIndex(sfr, csoArray[i], codepage, fnc.getDpi());
characterSet.addCharacterSetOrientation(csoArray[i]);
}

} catch (Exception ex) {
throw new FontRuntimeException(
"Failed to load the character set metrics for code page "
+ characterSet.getCodePage(), ex);
} finally {
try {
inputStream.close();
} catch (Exception ex) {
// Ignore
}
}

}

/**
* Load the code page information from the appropriate file. The file name
* to load is determined by the code page name and the file extension 'CDP'.
*
* @param codePage
* the code page identifier
* @param encoding
* the encoding to use for the character decoding
*/
private static HashMap loadCodePage(String codePage, String encoding,
String path) throws IOException, FileNotFoundException {

// Create the HashMap to store code page information
HashMap codepages = new HashMap();

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if (classLoader == null) {
classLoader = AFPFontReader.class.getClassLoader();
}

URL url = classLoader.getResource(path);

if (url == null) {
try {
File file = new File(path);
url = file.toURL();
if (url == null) {
String msg = "CodePage file not found for " + codePage
+ " in classpath: " + path;
log.error(msg);
throw new FileNotFoundException(msg);
}
} catch (MalformedURLException ex) {
String msg = "CodePage file not found for " + codePage
+ " in classpath: " + path;
log.error(msg);
throw new FileNotFoundException(msg);
}

}

File directory = new File(url.getPath());

final String filterpattern = codePage.trim();
FilenameFilter filter = new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.startsWith(filterpattern);
}
};

File[] codepage = directory.listFiles(filter);

if (codepage.length < 1) {
String msg = "CodePage file search for " + codePage + " located "
+ codepage.length + " files";
log.error(msg);
throw new FileNotFoundException(msg);
} else if (codepage.length > 1) {
String msg = "CodePage file search for " + codePage + " located "
+ codepage.length + " files";
log.warn(msg);
}

InputStream is = codepage[0].toURL().openStream();

if (is == null) {
String msg = "AFPFontReader:: loadCodePage(String):: code page file not found for "
+ codePage;
log.error(msg);
throw new FileNotFoundException(msg);
}

StructuredFieldReader sfr = new StructuredFieldReader(is);
byte[] data = sfr.getNext(CHARACTER_TABLE_SF);

int position = 0;
byte[] gcgiBytes = new byte[8];
byte[] charBytes = new byte[1];

// Read data, ignoring bytes 0 - 2
for (int index = 3; index < data.length; index++) {
if (position < 8) {
// Build the graphic character global identifier key
gcgiBytes[position] = data[index];
position++;
} else if (position == 9) {
position = 0;
// Set the character
charBytes[0] = data[index];
String gcgiString = new String(gcgiBytes,
AFPConstants.EBCIDIC_ENCODING);
String charString = new String(charBytes, encoding);
int value = charString.charAt(0);
codepages.put(gcgiString, charString);
} else {
position++;
}
}

try {
is.close();
} catch (Exception ex) {
// Ignore
}

return codepages;

}

/**
* Process the font control details using the structured field reader.
*
* @param sfr
* the structured field reader
*/
private static FontControl processFontControl(StructuredFieldReader sfr)
throws IOException {

byte[] fncData = sfr.getNext(FONT_CONTROL_SF);

int position = 0;

FontControl fontControl = new AFPFontReader().new FontControl();

if (fncData[7] == (byte) 0x02) {
fontControl.setRelative(true);
}

int dpi = (((fncData[9] & 0xFF) << 8) + (fncData[10] & 0xFF)) / 10;

fontControl.setDpi(dpi);

return fontControl;

}

/**
* Process the font orientation details from using the structured field
* reader.
*
* @param sfr
* the structured field reader
*/
private static CharacterSetOrientation[] processFontOrientation(
StructuredFieldReader sfr) throws IOException {

byte[] data = sfr.getNext(FONT_ORIENTATION_SF);

int position = 0;
byte[] fnoData = new byte[26];

ArrayList orientations = new ArrayList();

// Read data, ignoring bytes 0 - 2
for (int index = 3; index < data.length; index++) {
// Build the font orientation record
fnoData[position] = data[index];
position++;

if (position == 26) {

position = 0;

int orientation = 0;

switch (fnoData[2]) {
case 0x00:
orientation = 0;
break;
case 0x2D:
orientation = 90;
break;
case 0x5A:
orientation = 180;
break;
case (byte) 0x87:
orientation = 270;
break;
default:
System.out.println("ERROR: Oriantation");
}

CharacterSetOrientation cso = new CharacterSetOrientation(
orientation);
orientations.add(cso);

}
}

return (CharacterSetOrientation[]) orientations
.toArray(EMPTY_CSO_ARRAY);
}

/**
* Populate the CharacterSetOrientation object in the suplied array with the
* font position details using the supplied structured field reader.
*
* @param sfr
* the structured field reader
* @param csoArray
* the array of CharacterSetOrientation objects
*/
private static void processFontPosition(StructuredFieldReader sfr,
CharacterSetOrientation[] csoArray, int dpi) throws IOException {

byte[] data = sfr.getNext(FONT_POSITION_SF);

int position = 0;
byte[] fpData = new byte[26];

int csoIndex = 0;
int fopFactor = 0;

switch (dpi) {
case 100:
fopFactor = FOP_100_DPI_FACTOR;
break;
case 240:
fopFactor = FOP_240_DPI_FACTOR;
break;
case 300:
fopFactor = FOP_300_DPI_FACTOR;
break;
default:
String msg = "Unsupported font resolution of " + dpi + " dpi.";
log.error(msg);
throw new IOException(msg);
}

// Read data, ignoring bytes 0 - 2
for (int index = 3; index < data.length; index++) {
if (position < 22) {
// Build the font orientation record
fpData[position] = data[index];
} else if (position == 22) {

position = 0;

CharacterSetOrientation cso = csoArray[csoIndex];

int xHeight = ((fpData[2] & 0xFF) << 8) + (fpData[3] & 0xFF);
int capHeight = ((fpData[4] & 0xFF) << 8) + (fpData[5] & 0xFF);
int ascHeight = ((fpData[6] & 0xFF) << 8) + (fpData[7] & 0xFF);
int dscHeight = ((fpData[8] & 0xFF) << 8) + (fpData[9] & 0xFF);

dscHeight = dscHeight * -1;

cso.setXHeight(xHeight * fopFactor);
cso.setCapHeight(capHeight * fopFactor);
cso.setAscender(ascHeight * fopFactor);
cso.setDescender(dscHeight * fopFactor);

csoIndex++;

fpData[position] = data[index];

}

position++;
}

}

/**
* Process the font index details for the character set orientation.
*
* @param sfr
* the structured field reader
* @param cso
* the CharacterSetOrientation object to populate
* @param codepage
* the map of code pages
*/
private static void processFontIndex(StructuredFieldReader sfr,
CharacterSetOrientation cso, HashMap codepage, int dpi)
throws IOException {

byte[] data = sfr.getNext(FONT_INDEX_SF);

int fopFactor = 0;

switch (dpi) {
case 100:
fopFactor = FOP_100_DPI_FACTOR;
break;
case 240:
fopFactor = FOP_240_DPI_FACTOR;
break;
case 300:
fopFactor = FOP_300_DPI_FACTOR;
break;
default:
String msg = "Unsupported font resolution of " + dpi + " dpi.";
log.error(msg);
throw new IOException(msg);
}

int position = 0;

byte[] gcgid = new byte[8];
byte[] fiData = new byte[20];

int lowest = 255;
int highest = 0;

// Read data, ignoring bytes 0 - 2
for (int index = 3; index < data.length; index++) {
if (position < 8) {
gcgid[position] = (byte) data[index];
position++;
} else if (position < 27) {
fiData[position - 8] = (byte) data[index];
position++;
} else if (position == 27) {

fiData[position - 8] = (byte) data[index];

position = 0;

String gcgiString = new String(gcgid, AFPConstants.EBCIDIC_ENCODING);

String idx = (String) codepage.get(gcgiString);

if (idx != null) {

int cidx = idx.charAt(0);
int width = ((fiData[0] & 0xFF) << 8) + (fiData[1] & 0xFF);

if (cidx < lowest) {
lowest = cidx;
}

if (cidx > highest) {
highest = cidx;
}

int a = (width * fopFactor);

cso.setWidth(cidx, a);

}

}
}

cso.setFirstChar(lowest);
cso.setLastChar(highest);

}

private class FontControl {

private int _dpi;

private boolean isRelative = false;

public int getDpi() {
return _dpi;
}

public void setDpi(int i) {
_dpi = i;
}

public boolean isRelative() {
return isRelative;
}

public void setRelative(boolean b) {
isRelative = b;
}
}

}

+ 322
- 0
src/sandbox/org/apache/fop/render/afp/fonts/CharacterSet.java 查看文件

@@ -0,0 +1,322 @@
/*
* Copyright 2006 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.afp.fonts;

import java.io.UnsupportedEncodingException;
import java.util.HashMap;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.render.afp.modca.AFPConstants;
import org.apache.fop.render.afp.tools.StringUtils;

/**
* The IBM Font Object Content Architecture (FOCA) supports presentation
* of character shapes by defining their characteristics, which include
* font description information for identifying the characters, font metric
* information for positioning the characters, and character shape information
* for presenting the character images.
* <p/>
* Presenting a graphic character on a presentation surface requires
* information on the rotation and position of character on the physical
* or logical page.
* <p/>
* This class proivdes font metric information for a particular font
* as identified by the character set name. This information is obtained
* directly from the AFP font files which must be installed in the path
* specified in the afp-fonts xml definition file.
* <p/>
*/
public class CharacterSet {

/**
* Static logging instance
*/
protected static final Log log = LogFactory.getLog(CharacterSet.class.getName());

/**
* The code page to which the character set relates
*/
protected String _codePage;

/**
* The encoding used for the code page
*/
protected String _encoding;

/**
* The character set relating to the font
*/
protected String _name;

/**
* The name of the character set as EBCIDIC bytes
*/
private byte[] _nameBytes;

/**
* The path to the installed fonts
*/
protected String _path;

/**
* Indicator as to whether to metrics have been loaded
*/
private boolean _isMetricsLoaded = false;

/**
* The current orientation (currently only 0 is suppoted by FOP)
*/
private String _currentOrientation = "0";

/**
* The collection of objects for each orientation
*/
private HashMap _characterSetOrientations;

/**
* Constructor for the CharacterSetMetric object, the character set is used
* to load the font information from the actual AFP font.
* @param codePage the code page identifier
* @param encoding the encoding of the font
* @param name the character set name
* @param path the path to the installed afp fonts
*/
public CharacterSet(
String codePage,
String encoding,
String name,
String path) {

if (name.length() > 8) {
String msg = "Character set name must be a maximum of 8 characters " + name;
log.error("Constructor:: " + msg);
throw new IllegalArgumentException(msg);
}

if (name.length() < 8) {
_name = StringUtils.rpad(name, ' ', 8);
} else {
_name = name;
}

try {

_nameBytes = name.getBytes(AFPConstants.EBCIDIC_ENCODING);

} catch (UnsupportedEncodingException usee) {

_nameBytes = name.getBytes();
log.warn(
"Constructor:: UnsupportedEncodingException translating the name "
+ name);

}

_codePage = codePage;
_encoding = encoding;
_path = path;
_characterSetOrientations = new HashMap(4);

}

/**
* Add character set metric information for the different orientations
* @param cso the metrics for the orientation
*/
public void addCharacterSetOrientation(CharacterSetOrientation cso) {

_characterSetOrientations.put(
String.valueOf(cso.getOrientation()),
cso);

}

/**
* Ascender height is the distance from the character baseline to the
* top of the character box. A negative ascender height signifies that
* all of the graphic character is below the character baseline. For
* a character rotation other than 0, ascender height loses its
* meaning when the character is lying on its side or is upside down
* with respect to normal viewing orientation. For the general case,
* Ascender Height is the character�s most positive y-axis value.
* For bounded character boxes, for a given character having an
* ascender, ascender height and baseline offset are equal.
* @return the ascender value in millipoints
*/
public int getAscender() {
load();
return getCharacterSetOrientation().getAscender();
}

/**
* Cap height is the average height of the uppercase characters in
* a font. This value is specified by the designer of a font and is
* usually the height of the uppercase M.
* @return the cap height value in millipoints
*/
public int getCapHeight() {
load();
return getCharacterSetOrientation().getCapHeight();
}

/**
* Descender depth is the distance from the character baseline to
* the bottom of a character box. A negative descender depth signifies
* that all of the graphic character is above the character baseline.
* @return the descender value in millipoints
*/
public int getDescender() {
load();
return getCharacterSetOrientation().getDescender();
}

/**
* The first character in the character set
* @return the first character
*/
public int getFirstChar() {
load();
return getCharacterSetOrientation().getFirstChar();
}

/**
* The last character in the character set
* @return the last character
*/
public int getLastChar() {
load();
return getCharacterSetOrientation().getLastChar();
}

/**
* @return the path where the font resources are installed
*/
public String getPath() {
return _path;
}

/**
* Get the width (in 1/1000ths of a point size) of all characters
* @return the widths of all characters
*/
public int[] getWidths() {
load();
return getCharacterSetOrientation().getWidths();
}

/**
* XHeight refers to the height of the lower case letters above the baseline.
* @return the typical height of characters
*/
public int getXHeight() {
load();
return getCharacterSetOrientation().getXHeight();
}

/**
* Get the width (in 1/1000ths of a point size) of the character
* identified by the parameter passed.
* @param character the character from which the width will be calculated
* @return the width of the character
*/
public int width(int character) {
load();
return getCharacterSetOrientation().width(character);
}

/**
* Lazy creation of the character metrics, the afp font file will only
* be processed on a method call requiring the metric information.
*/
private void load() {

if (!_isMetricsLoaded) {

AFPFontReader.loadCharacterSetMetric(this);
_isMetricsLoaded = true;

}

}

/**
* Returns the AFP character set identifier
* @return String
*/
public String getName() {
return _name;
}

/**
* Returns the AFP character set identifier
* @return byte[]
*/
public byte[] getNameBytes() {
return _nameBytes;
}

/**
* Returns the AFP code page identifier
* @return String
*/
public String getCodePage() {
return _codePage;
}

/**
* Returns the AFP code page encoding
* @return String
*/
public String getEncoding() {
return _encoding;
}

/**
* Helper method to return the current CharacterSetOrientation, note
* that FOP does not yet implement the "reference-orientation"
* attribute therefore we always use the orientation zero degrees,
* Other orientation information is captured for use by a future
* implementation (whenever FOP implement the mechanism). This is also
* the case for landscape prints which use an orientation of 270 degrees,
* in 99.9% of cases the font metrics will be the same as the 0 degrees
* therefore the implementation currely will always use 0 degrees.
* @return characterSetOrentation The current orientation metrics.
*/
private CharacterSetOrientation getCharacterSetOrientation() {

CharacterSetOrientation c =
(CharacterSetOrientation) _characterSetOrientations.get(
_currentOrientation);
return c;

}

/**
* Map a Unicode character to a code point in the font.
* The code tables are already converted to Unicode therefore
* we can use the identity mapping.
* @param c character to map
* @return the mapped character
*/
public char mapChar(char c) {
return c;
}

}

+ 275
- 0
src/sandbox/org/apache/fop/render/afp/fonts/CharacterSetOrientation.java 查看文件

@@ -0,0 +1,275 @@
/*
* Copyright 2006 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.afp.fonts;


/**
* The IBM Font Object Content Architecture (FOCA) supports presentation
* of character shapes by defining their characteristics, which include
* Font-Description information for identifying the characters, Font-Metric
* information for positioning the characters, and Character-Shape
* information for presenting the character images.
*
* Presenting a graphic character on a presentation surface requires
* that you communicate this information clearly to rotate and position
* characters correctly on the physical or logical page.
*
* This class proivdes font metric information for a particular font
* as by the orientation.
*
* This informtaion is obtained directly from the AFP font files which must
* be installed in the classpath under in the location specified by the path
* attribute in the afp-font.xml file.
* <p/>
*/
public class CharacterSetOrientation {

/**
* The code page to which the character set relates
*/
private String _codePage;

/**
* The encoding used for the code page
*/
private String _encoding;

/**
* The ascender height for the character set
*/
private int _ascender;

/**
* The descender depth for the character set
*/
private int _descender;

/**
* The height of capital letters
*/
private int _capHeight;

/**
* The characters in the charcater set
*/
private int[] _characters = new int[256];

/**
* The height of lowercase letters
*/
private int _xHeight;

/**
* The first character
*/
private int _firstCharacter;

/**
* The last character
*/
private int _lastCharacter;


/**
* The character set orientation
*/
private int _orientation = 0;

/**
* Constructor for the CharacterSetOrientation, the orientation is
* expressed as the degrees rotation (i.e 0, 90, 180, 270)
* @param orientation the character set orientation
*/
public CharacterSetOrientation(int orientation) {

_orientation = orientation;

}

/**
* Ascender height is the distance from the character baseline to the
* top of the character box. A negative ascender height signifies that
* all of the graphic character is below the character baseline. For
* a character rotation other than 0, ascender height loses its
* meaning when the character is lying on its side or is upside down
* with respect to normal viewing orientation. For the general case,
* Ascender Height is the character�s most positive y-axis value.
* For bounded character boxes, for a given character having an
* ascender, ascender height and baseline offset are equal.
* @return the ascender value in millipoints
*/
public int getAscender() {
return _ascender;
}

/**
* Cap height is the average height of the uppercase characters in
* a font. This value is specified by the designer of a font and is
* usually the height of the uppercase M.
* @return the cap height value in millipoints
*/
public int getCapHeight() {
return _capHeight;
}

/**
* Descender depth is the distance from the character baseline to
* the bottom of a character box. A negative descender depth signifies
* that all of the graphic character is above the character baseline.
* @return the descender value in millipoints
*/
public int getDescender() {
return _descender;
}

/**
* The first character in the character set
* @return the first character
*/
public int getFirstChar() {
return _firstCharacter;
}

/**
* The last character in the character set
* @return the last character
*/
public int getLastChar() {
return _lastCharacter;
}

/**
* The orientation for these metrics in the character set
* @return the orientation
*/
public int getOrientation() {
return _orientation;
}

/**
* Get the width (in 1/1000ths of a point size) of all characters
* in this character set.
* @return the widths of all characters
*/
public int[] getWidths() {

int arr[] = new int[(getLastChar() - getFirstChar()) + 1];
System.arraycopy(_characters, getFirstChar(), arr, 0, (getLastChar() - getFirstChar()) + 1);
return arr;

}

/**
* XHeight refers to the height of the lower case letters above
* the baseline.
* @return heightX the typical height of characters
*/
public int getXHeight() {
return _xHeight;
}

/**
* Get the width (in 1/1000ths of a point size) of the character
* identified by the parameter passed.
* @param character the character to evaluate
* @return the widths of the character
*/
public int width(int character) {
return _characters[character];
}

/**
* Ascender height is the distance from the character baseline to the
* top of the character box. A negative ascender height signifies that
* all of the graphic character is below the character baseline. For
* a character rotation other than 0, ascender height loses its
* meaning when the character is lying on its side or is upside down
* with respect to normal viewing orientation. For the general case,
* Ascender Height is the character�s most positive y-axis value.
* For bounded character boxes, for a given character having an
* ascender, ascender height and baseline offset are equal.
* @param ascender the ascender to set
*/
public void setAscender(int ascender) {
_ascender = ascender;
}

/**
* Cap height is the average height of the uppercase characters in
* a font. This value is specified by the designer of a font and is
* usually the height of the uppercase M.
* @param capHeight the cap height to set
*/
public void setCapHeight(int capHeight) {
_capHeight = capHeight;
}

/**
* Descender depth is the distance from the character baseline to
* the bottom of a character box. A negative descender depth signifies
* that all of the graphic character is above the character baseline.
* @param descender the descender value in millipoints
*/
public void setDescender(int descender) {
_descender = descender;
}

/**
* The first character in the character set
* @param firstCharacter the first character
*/
public void setFirstChar(int firstCharacter) {
_firstCharacter = firstCharacter;
}

/**
* The last character in the character set
* @param lastCharacter the last character
*/
public void setLastChar(int lastCharacter) {
_lastCharacter = lastCharacter;
}

/**
* Set the width (in 1/1000ths of a point size) of the character
* identified by the parameter passed.
* @param character the character for which the width is being set
* @param width the widths of the character
*/
public void setWidth(int character, int width) {

if (character >= _characters.length) {
// Increase the size of the array if necessary
int arr[] = new int[(character - _firstCharacter) + 1];
System.arraycopy(_characters, 0, arr, 0, _characters.length);
_characters = arr;
}
_characters[character] = width;

}

/**
* XHeight refers to the height of the lower case letters above
* the baseline.
* @param xHeight the typical height of characters
*/
public void setXHeight(int xHeight) {
_xHeight = xHeight;
}
}

+ 138
- 0
src/sandbox/org/apache/fop/render/afp/fonts/FopCharacterSet.java 查看文件

@@ -0,0 +1,138 @@
/*
* Copyright 2006 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.afp.fonts;

import org.apache.fop.fonts.Typeface;

/**
* A Character set for a normal FOP font<p/>
*/
public class FopCharacterSet extends CharacterSet {

/** The character set for this font */
private Typeface _characterSet = null;
private int _size = 0;

/**
* Constructor for the CharacterSetMetric object, the character set is used
* to load the font information from the actual AFP font.
* @param codePage the code page identifier
* @param encoding the encoding of the font
* @param name the character set name
* @param size the font size
* @param Typeface the fop character set
*/
public FopCharacterSet(
String codePage,
String encoding,
String name,
int size,
Typeface characterSet) {
super(codePage, encoding, name, null);
_characterSet = characterSet;
_size = size * 1000;
}

/**
* Ascender height is the distance from the character baseline to the
* top of the character box. A negative ascender height signifies that
* all of the graphic character is below the character baseline. For
* a character rotation other than 0, ascender height loses its
* meaning when the character is lying on its side or is upside down
* with respect to normal viewing orientation. For the general case,
* Ascender Height is the character�s most positive y-axis value.
* For bounded character boxes, for a given character having an
* ascender, ascender height and baseline offset are equal.
* @return the ascender value in millipoints
*/
public int getAscender() {
return _characterSet.getAscender(_size);
}

/**
* Cap height is the average height of the uppercase characters in
* a font. This value is specified by the designer of a font and is
* usually the height of the uppercase M.
* @return the cap height value in millipoints
*/
public int getCapHeight() {
return _characterSet.getCapHeight(_size);
}

/**
* Descender depth is the distance from the character baseline to
* the bottom of a character box. A negative descender depth signifies
* that all of the graphic character is above the character baseline.
* @return the descender value in millipoints
*/
public int getDescender() {
return _characterSet.getDescender(_size);
}

/**
* The first character in the character set
* @return the first character
*/
public int getFirstChar() {
return 0;
}

/**
* The last character in the character set
* @return the last character
*/
public int getLastChar() {
return 0;
}

/**
* Get the width (in 1/1000ths of a point size) of all characters
* @return the widths of all characters
*/
public int[] getWidths() {
return _characterSet.getWidths();
}

/**
* XHeight refers to the height of the lower case letters above the baseline.
* @return the typical height of characters
*/
public int getXHeight() {
return _characterSet.getXHeight(_size);
}

/**
* Get the width (in 1/1000ths of a point size) of the character
* identified by the parameter passed.
* @param character the character from which the width will be calculated
* @return the width of the character
*/
public int width(int character) {
return _characterSet.getWidth(character, _size);
}

/**
* Map a Unicode character to a code point in the font.
* @param c character to map
* @return the mapped character
*/
public char mapChar(char c) {
return _characterSet.mapChar(c);
}

}

+ 193
- 0
src/sandbox/org/apache/fop/render/afp/fonts/OutlineFont.java 查看文件

@@ -0,0 +1,193 @@
/*
* Copyright 2006 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.afp.fonts;


/**
* A font defined as a set of lines and curves as opposed to a bitmap font. An
* outline font can be scaled to any size and otherwise transformed more easily
* than a bitmap font, and with more attractive results. <p/>
*
*/
public class OutlineFont extends AFPFont {

/** The character set for this font */
private CharacterSet _characterSet = null;

/**
* Constructor for an outline font.
*
* @param name
* the name of the font
* @param characterSet
* the chracter set
*/
public OutlineFont(String name, CharacterSet characterSet) {
super(name);
_characterSet = characterSet;
}

/**
* Get the character set metrics.
*
* @return the character set
*/
public CharacterSet getCharacterSet() {

return _characterSet;

}

/**
* Get the character set metrics.
* @param size ignored
* @return the character set
*/
public CharacterSet getCharacterSet(int size) {

return _characterSet;

}

/**
* Get the first character in this font.
*/
public int getFirstChar() {

return _characterSet.getFirstChar();

}

/**
* Get the last character in this font.
*/
public int getLastChar() {

return _characterSet.getLastChar();

}

/**
* The ascender is the part of a lowercase letter that extends above the
* "x-height" (the height of the letter "x"), such as "d", "t", or "h". Also
* used to denote the part of the letter extending above the x-height.
*
* @param size
* the point size
*/
public int getAscender(int size) {

return _characterSet.getAscender() / 1000 * size;

}

/**
* Obtains the height of capital letters for the specified point size.
*
* @param size
* the point size
*/
public int getCapHeight(int size) {

return _characterSet.getCapHeight() / 1000 * size;

}

/**
* The descender is the part of a lowercase letter that extends below the
* base line, such as "g", "j", or "p". Also used to denote the part of the
* letter extending below the base line.
*
* @param size
* the point size
*/
public int getDescender(int size) {

return _characterSet.getDescender() / 1000 * size;

}

/**
* The "x-height" (the height of the letter "x").
*
* @param size
* the point size
*/
public int getXHeight(int size) {

return _characterSet.getXHeight() / 1000 * size;

}

/**
* Obtain the width of the character for the specified point size.
*/
public int getWidth(int character, int size) {

return _characterSet.width(character) / 1000 * size;

}

/**
* Get the getWidth (in 1/1000ths of a point size) of all characters in this
* character set.
*
* @param size
* the point size
* @return the widths of all characters
*/
public int[] getWidths(int size) {

int[] widths = _characterSet.getWidths();
for (int i = 0 ; i < widths.length; i++) {
widths[i] = widths[i] / 1000 * size;
}
return widths;

}

/**
* Get the getWidth (in 1/1000ths of a point size) of all characters in this
* character set.
*
* @return the widths of all characters
*/
public int[] getWidths() {

return getWidths(1000);

}

/**
* Map a Unicode character to a code point in the font.
* @param c character to map
* @return the mapped character
*/
public char mapChar(char c) {
return _characterSet.mapChar(c);
}

/**
* Get the encoding of the font.
* @return the encoding
*/
public String getEncoding() {
return _characterSet.getEncoding();
}

}

+ 243
- 0
src/sandbox/org/apache/fop/render/afp/fonts/RasterFont.java 查看文件

@@ -0,0 +1,243 @@
/*
* Copyright 2006 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.afp.fonts;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.render.afp.exceptions.FontRuntimeException;

/**
* A font where each character is stored as an array of pixels (a bitmap). Such
* fonts are not easily scalable, in contrast to vectored fonts. With this type
* of font, the font metrics information is held in character set files (one for
* each size and style). <p/>
*
*/
public class RasterFont extends AFPFont {

/** Static logging instance */
protected static final Log log = LogFactory.getLog("org.apache.fop.render.afp.fonts");

private HashMap _characterSets = new HashMap();

private CharacterSet _characterSet = null;

/**
* Constructor for the raster font requires the name, weight and style
* attribute to be available as this forms the key to the font.
*
* @param name
* the name of the font
*/
public RasterFont(String name) {
super(name);
}

public void addCharacterSet(int size, CharacterSet characterSet) {

_characterSets.put(String.valueOf(size), characterSet);

_characterSet = characterSet;

}

/**
* Get the character set metrics for the specified point size.
*
* @param size the point size
* @return the character set metrics
*/
public CharacterSet getCharacterSet(int size) {

String pointsize = String.valueOf(size / 1000);
CharacterSet csm = (CharacterSet) _characterSets.get(pointsize);
if (csm == null) {
csm = (CharacterSet) _characterSets.get(size + "mpt");
}
if (csm == null) {
// Get char set with nearest font size
int distance = Integer.MAX_VALUE;
for (Iterator it = _characterSets.entrySet().iterator(); it.hasNext(); ) {
Map.Entry me = (Map.Entry)it.next();
String key = (String)me.getKey();
if (!key.endsWith("mpt")) {
int mpt = Integer.parseInt(key) * 1000;
if (Math.abs(size - mpt) < distance) {
distance = Math.abs(size - mpt);
pointsize = (String)me.getKey();
csm = (CharacterSet)me.getValue();
}
}
}
if (csm != null) {
_characterSets.put(size + "mpt", csm);
String msg = "No " + (size / 1000) + "pt font " + _name
+ " found, substituted with " + pointsize + "pt font";
log.warn(msg);
}
}
if (csm == null) {
String msg = "No font found for font " + _name
+ " with point size " + pointsize;
log.error(msg);
throw new FontRuntimeException(msg);
}
return csm;

}

/**
* Get the first character in this font.
*/
public int getFirstChar() {

Iterator i = _characterSets.values().iterator();
if (i.hasNext()) {
CharacterSet csm = (CharacterSet) i.next();
return csm.getFirstChar();
} else {
String msg = "getFirstChar() - No character set found for font:" + _name;
log.error(msg);
throw new FontRuntimeException(msg);
}

}

/**
* Get the last character in this font.
*/
public int getLastChar() {

Iterator i = _characterSets.values().iterator();
if (i.hasNext()) {
CharacterSet csm = (CharacterSet) i.next();
return csm.getLastChar();
} else {
String msg = "getLastChar() - No character set found for font:" + _name;
log.error(msg);
throw new FontRuntimeException(msg);
}

}

/**
* The ascender is the part of a lowercase letter that extends above the
* "x-height" (the height of the letter "x"), such as "d", "t", or "h". Also
* used to denote the part of the letter extending above the x-height.
*
* @param size the point size
*/
public int getAscender(int size) {

return getCharacterSet(size).getAscender();

}

/**
* Obtains the height of capital letters for the specified point size.
*
* @param size the point size
*/
public int getCapHeight(int size) {

return getCharacterSet(size).getCapHeight();

}

/**
* The descender is the part of a lowercase letter that extends below the
* base line, such as "g", "j", or "p". Also used to denote the part of the
* letter extending below the base line.
*
* @param size the point size
*/
public int getDescender(int size) {

return getCharacterSet(size).getDescender();

}

/**
* The "x-height" (the height of the letter "x").
*
* @param size the point size
*/
public int getXHeight(int size) {

return getCharacterSet(size).getXHeight();

}

/**
* Obtain the width of the character for the specified point size.
*/
public int getWidth(int character, int size) {

return getCharacterSet(size).width(character);

}

/**
* Get the getWidth (in 1/1000ths of a point size) of all characters in this
* character set.
*
* @param size
* the point size
* @return the widths of all characters
*/
public int[] getWidths(int size) {

return getCharacterSet(size).getWidths();

}

/**
* Get the getWidth (in 1/1000ths of a point size) of all characters in this
* character set.
*
* @return the widths of all characters
*/
public int[] getWidths() {

return getWidths(1000);

}

/**
* Map a Unicode character to a code point in the font.
* @param c character to map
* @return the mapped character
*/
public char mapChar(char c) {
return _characterSet.mapChar(c);
}

/**
* Get the encoding of the font.
* @return the encoding
*/
public String getEncoding() {
return _characterSet.getEncoding();
}

}

+ 37
- 0
src/sandbox/org/apache/fop/render/afp/modca/AFPConstants.java 查看文件

@@ -0,0 +1,37 @@
/*
* Copyright 2006 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.afp.modca;

/**
* Constants used by the AFP renderer.
*
*/
public interface AFPConstants {

/**
* The encoding to use to convert to EBCIDIC
*/
public String EBCIDIC_ENCODING = "Cp1146";

/**
* The encoding to use to convert to ASCII
*/
public String ASCII_ENCODING = "Cp1252";

}

+ 650
- 0
src/sandbox/org/apache/fop/render/afp/modca/AFPDataStream.java 查看文件

@@ -0,0 +1,650 @@
/*
* Copyright 2006 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.afp.modca;

import java.io.IOException;
import java.io.OutputStream;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.render.afp.AFPFontColor;
import org.apache.fop.render.afp.fonts.AFPFont;
import org.apache.fop.render.afp.tools.StringUtils;

/**
* A data stream is a continuous ordered stream of data elements and objects
* conforming to a given format. Application programs can generate data streams
* destined for a presentation service, archive library, presentation device or
* another application program. The strategic presentation data stream
* architectures used is Mixed Object Document Content Architecture (MO:DCA�).
*
* The MO:DCA architecture defines the data stream used by applications to
* describe documents and object envelopes for interchange with other
* applications and application services. Documents defined in the MO:DCA format
* may be archived in a database, then later retrieved, viewed, annotated and
* printed in local or distributed systems environments. Presentation fidelity
* is accommodated by including resource objects in the documents that reference
* them.
*
*/
public class AFPDataStream {

/**
* Static logging instance
*/
protected static final Log log = LogFactory.getLog("org.apache.fop.render.afp.modca");

/**
* Boolean completion indicator
*/
private boolean _complete = false;

/**
* The application producing the AFP document
*/
private String _producer = null;

/**
* The AFP document object
*/
private Document _document = null;

/**
* The current page group object
*/
private PageGroup _currentPageGroup = null;

/**
* The current page object
*/
private PageObject _currentPageObject = null;

/**
* The current overlay object
*/
private Overlay _currentOverlay = null;

/**
* The current page
*/
private AbstractPageObject _currentPage = null;

/**
* The page count
*/
private int _pageCount = 0;

/**
* The page group count
*/
private int _pageGroupCount = 0;

/**
* The overlay count
*/
private int _ovlCount = 0;

/**
* The portrait rotation
*/
private int _portraitRotation = 0;

/**
* The landscape rotation
*/
private int _landscapeRotation = 270;

/**
* The x offset
*/
private int _xOffset = 0;

/**
* The y offset
*/
private int _yOffset = 0;

/**
* The rotation
*/
private int _rotation;

/**
* The outputstream for the data stream
*/
private OutputStream _outputStream = null;

/**
* Default constructor for the AFPDataStream.
*/
public AFPDataStream() {
}

/**
* The document is started by invoking this method which creates an instance
* of the AFP Document object.
*/
public void startDocument(OutputStream outputStream) {

if (_document != null) {
String msg = "Invalid state - document already started.";
log.warn("startDocument():: " + msg);
throw new IllegalStateException(msg);
}

_document = new Document();
_outputStream = outputStream;

}

/**
* The document is ended by invoking this method which creates an instance
* of the AFP Document object and registers the start with a validation map
* which ensures that methods are not invoked out of the correct sequence.
*/
public void endDocument()
throws IOException {

if (_complete) {
String msg = "Invalid state - document already ended.";
log.warn("endDocument():: " + msg);
throw new IllegalStateException(msg);
}

if (_currentPageObject != null) {
// End the current page if necessary
endPage();
}

if (_currentPageGroup != null) {
// End the current page group if necessary
endPageGroup();
}

_document.endDocument();
_document.writeDataStream(_outputStream);
_outputStream.flush();

_complete = true;

_document = null;

_outputStream = null;
}

/**
* Start a new page. When processing has finished on the current page, the
* {@link #endPage()}method must be invoked to mark the page ending.
*
* @param pageWidth
* the width of the page
* @param pageHeight
* the height of the page
* @param pageRotation
* the rotation of the page
*/
public void startPage(int pageWidth, int pageHeight, int pageRotation) {

String pageName = "PGN"
+ StringUtils.lpad(String.valueOf(_pageCount++), '0', 5);

_currentPageObject = new PageObject(pageName, pageWidth, pageHeight, pageRotation);
_currentPage = _currentPageObject;
_currentOverlay = null;
setOffsets(0, 0, 0);
}

/**
* Start a new overlay. When processing has finished on the current overlay, the
* {@link #endOverlay()}method must be invoked to mark the overlay ending.
*
* @param overlayX
* the x position of the overlay on the page
* @param overlayY
* the y position of the overlay on the page
* @param overlayWidth
* the width of the overlay
* @param overlayHeight
* the height of the overlay
* @param overlayRotation
* the rotation of the overlay
*/
public void startOverlay(int overlayX, int overlayY, int overlayWidth, int overlayHeight, int overlayRotation) {

String overlayName = "OVL"
+ StringUtils.lpad(String.valueOf(_ovlCount++), '0', 5);

_currentOverlay = new Overlay(overlayName, overlayWidth, overlayHeight, overlayRotation);
_currentPageObject.addOverlay(_currentOverlay);
_currentPageObject.createIncludePageOverlay(overlayName, overlayX, overlayY, 0);
_currentPage = _currentOverlay;
setOffsets(0, 0, 0);
}

/**
* Helper method to mark the end of the current overlay.
*/
public void endOverlay() {

_currentOverlay.endPage();
_currentOverlay = null;
_currentPage = _currentPageObject;

}

/**
* Helper method to save the current page.
*/
public PageObject savePage() {

PageObject pageObject = _currentPageObject;
if (_currentPageGroup != null) {
_currentPageGroup.addPage(_currentPageObject);
} else {
_document.addPage(_currentPageObject);
}
_currentPageObject = null;
_currentPage = null;
return pageObject;

}

/**
* Helper method to restore the current page.
*/
public void restorePage(PageObject pageObject) {

_currentPageObject = pageObject;
_currentPage = pageObject;

}

/**
* Helper method to mark the end of the current page.
*/
public void endPage()
throws IOException {

_currentPageObject.endPage();
if (_currentPageGroup != null) {
_currentPageGroup.addPage(_currentPageObject);
} else {
_document.addPage(_currentPageObject);
_document.writeDataStream(_outputStream);
}

_currentPageObject = null;
_currentPage = null;

}

/**
* Sets the offsets to be used for element positioning
*
* @param xOffset
* the offset in the x direction
* @param yOffset
* the offset in the y direction
* @param rotation
* the rotation
*/
public void setOffsets(int xOffset, int yOffset, int rotation) {
_xOffset = xOffset;
_yOffset = yOffset;
_rotation = rotation;
}

/**
* Helper method to create a map coded font object on the current page, this
* method delegates the construction of the map coded font object to the
* active environment group on the current page.
*
* @param fontReference
* the font number used as the resource identifier
* @param font
* the font
* @param size
* the point size of the font
*/
public void createFont(byte fontReference, AFPFont font, int size) {

_currentPage.createFont(fontReference, font, size);

}

/**
* Helper method to create text on the current page, this method delegates
* to the current presentation text object in order to construct the text.
*
* @param fontNumber
* the font number used as the resource identifier
* @param x
* the x coordinate of the text
* @param y
* the y coordinate of the text
* @param col
* the text color
* @param vsci
* The variable space character increment.
* @param ica
* The inter character adjustment.
* @param data
* the text data to create
*/
public void createText(int fontNumber, int x, int y, AFPFontColor col, int vsci, int ica, byte[] data) {

_currentPage.createText(fontNumber, x + _xOffset, y + _yOffset, _rotation, col, vsci, ica, data);

}

/**
* Returns an ImageObject used to create an image in the datastream.
*
* @param x
* the x position of the image
* @param y
* the y position of the image
* @param w
* the width of the image
* @param h
* the height of the image
*/
public ImageObject getImageObject(int x, int y, int w, int h) {

int xOrigin;
int yOrigin;
int width;
int height;
switch (_rotation) {
case 90:
xOrigin = _currentPage.getWidth() - y - _yOffset;
yOrigin = x + _xOffset;
width = h;
height = w;
break;
case 180:
xOrigin = _currentPage.getWidth() - x - _xOffset;
yOrigin = _currentPage.getHeight() - y - _yOffset;
width = w;
height = h;
break;
case 270:
xOrigin = y + _yOffset;
yOrigin = _currentPage.getHeight() - x - _xOffset;
width = h;
height = w;
break;
default:
xOrigin = x + _xOffset;
yOrigin = y + _yOffset;
width = w;
height = h;
break;
}
ImageObject io = _currentPage.getImageObject();
io.setImageViewport(xOrigin, yOrigin, width, height, _rotation);
return io;

}

/**
* Method to create a line on the current page.
*
* @param x1
* the first x coordinate of the line
* @param y1
* the first y coordinate of the line
* @param x2
* the second x coordinate of the line
* @param y2
* the second y coordinate of the line
* @param thickness
* the thickness of the line
* @param col
* The text color.
*/
public void createLine(int x1, int y1, int x2, int y2, int thickness, AFPFontColor col) {

_currentPage.createLine(x1 + _xOffset, y1 + _yOffset, x2 + _xOffset, y2 + _yOffset, thickness, _rotation, col);

}

/**
* Sets the application producing the AFP.
*
* @param producer
* the application producing the AFP datastream
*/
public void setProducer(String producer) {
_producer = producer;
}

/**
* This method will create shading on the page using the specified
* coordinates (the shading contrast is controlled via the red, green, blue
* parameters, by converting this to grey scale).
*
* @param x
* the x coordinate of the shading
* @param y
* the y coordinate of the shading
* @param w
* the width of the shaded area
* @param h
* the height of the shaded area
* @param red
* the red value
* @param green
* the green value
* @param blue
* the blue value
*/
public void createShading(int x, int y, int w, int h, int red, int green,
int blue) {

_currentPage.createShading(x + _xOffset, y + _xOffset, w, h, red, green, blue);

}

/**
* Helper method which allows creation of the MPO object, via the AEG. And
* the IPO via the Page. (See actual object for descriptions.)
*
* @param name
* the name of the static overlay
*/
public void createIncludePageOverlay(String name) {

_currentPageObject.createIncludePageOverlay(name, 0, 0, _rotation);
ActiveEnvironmentGroup aeg = _currentPageObject.getActiveEnvironmentGroup();
aeg.createOverlay(name);

}

/**
* Helper method which allows creation of the IMM object.
*
* @param name
* the name of the medium map
*/
public void createInvokeMediumMap(String name) {

if (_currentPageGroup == null) {
startPageGroup();
}
_currentPageGroup.createInvokeMediumMap(name);

}

/**
* Creates an IncludePageSegment on the current page.
*
* @param name
* the name of the include page segment
* @param x
* the x coordinate for the overlay
* @param y
* the y coordinate for the overlay
*/
public void createIncludePageSegment(String name, int x, int y) {

int xOrigin;
int yOrigin;
switch (_rotation) {
case 90:
xOrigin = _currentPage.getWidth() - y - _yOffset;
yOrigin = x + _xOffset;
break;
case 180:
xOrigin = _currentPage.getWidth() - x - _xOffset;
yOrigin = _currentPage.getHeight() - y - _yOffset;
break;
case 270:
xOrigin = y + _yOffset;
yOrigin = _currentPage.getHeight() - x - _xOffset;
break;
default:
xOrigin = x + _xOffset;
yOrigin = y + _yOffset;
break;
}
_currentPage.createIncludePageSegment(name, xOrigin, yOrigin);

}

/**
* Creates a TagLogicalElement on the current page.
*
* @param attributes
* the array of key value pairs.
*/
public void createPageTagLogicalElement(TagLogicalElementBean[] attributes) {

for (int i = 0; i < attributes.length; i++) {
String name = (String) attributes[i].getKey();
String value = (String) attributes[i].getValue();
_currentPage.createTagLogicalElement(name, value);
}

}

/**
* Creates a TagLogicalElement on the current page group.
*
* @param attributes
* the array of key value pairs.
*/
public void createPageGroupTagLogicalElement(
TagLogicalElementBean[] attributes) {

for (int i = 0; i < attributes.length; i++) {
String name = (String) attributes[i].getKey();
String value = (String) attributes[i].getValue();
_currentPageGroup.createTagLogicalElement(name, value);
}

}

/**
* Creates a TagLogicalElement on the current page or page group
*
* @param name
* The tag name
* @param value
* The tag value
*/
public void createTagLogicalElement(String name, String value) {

if (_currentPageGroup != null) {
_currentPageGroup.createTagLogicalElement(name, value);
} else {
_currentPage.createTagLogicalElement(name, value);
}

}

/**
* Start a new page group. When processing has finished on the current page
* group the {@link #endPageGroup()}method must be invoked to mark the page
* group ending.
*
* @param name
* the name of the page group
*/
public void startPageGroup() {

String pageGroupName = "PGP"
+ StringUtils.lpad(String.valueOf(_pageCount++), '0', 5);

_currentPageGroup = new PageGroup(pageGroupName);

}

/**
* Helper method to mark the end of the page group.
*/
public void endPageGroup()
throws IOException {

_currentPageGroup.endPageGroup();
_document.addPageGroup(_currentPageGroup);
_document.writeDataStream(_outputStream);
_currentPageGroup = null;

}

/**
* Sets the rotation to be used for portrait pages, valid values are 0
* (default), 90, 180, 270.
*
* @param rotation
* The rotation in degrees.
*/
public void setPortraitRotation(int rotation) {

if (rotation == 0 || rotation == 90 || rotation == 180
|| rotation == 270) {
_portraitRotation = rotation;
} else {
throw new IllegalArgumentException(
"The portrait rotation must be one of the values 0, 90, 180, 270");
}

}

/**
* Sets the rotation to be used for landscape pages, valid values are 0, 90,
* 180, 270 (default).
*
* @param rotation
* The rotation in degrees.
*/
public void setLandscapeRotation(int rotation) {

if (rotation == 0 || rotation == 90 || rotation == 180
|| rotation == 270) {
_landscapeRotation = rotation;
} else {
throw new IllegalArgumentException(
"The landscape rotation must be one of the values 0, 90, 180, 270");
}

}

}

+ 65
- 0
src/sandbox/org/apache/fop/render/afp/modca/AbstractAFPObject.java 查看文件

@@ -0,0 +1,65 @@
/*
* Copyright 2006 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.afp.modca;

import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
* This is the base class for all data stream objects. Page objects are
* responsible for building and generating the binary datastream in an
* AFP format.
*
*/
public abstract class AbstractAFPObject {

/**
* Static logging instance
*/
protected static final Log log = LogFactory.getLog("org.apache.fop.render.afp.modca");

/**
* DataStream objects must implement the writeDataStream()
* method to write its data to the given OutputStream
* @param os The outputsteam stream
* @throws java.io.IOException
*/
public abstract void writeDataStream(OutputStream os) throws IOException;

/**
* Help method to write a set of AFPObjects to the AFP datastream.
* @afpObjects a list of AFPObjects
* @param os The stream to write to
* @throws java.io.IOException
*/
protected void writeObjectList(List afpObjects, OutputStream os)
throws IOException {

for (Iterator it = afpObjects.iterator(); it.hasNext(); ) {
((AbstractAFPObject)it.next()).writeDataStream(os);
}

}

}

+ 409
- 0
src/sandbox/org/apache/fop/render/afp/modca/AbstractPageObject.java 查看文件

@@ -0,0 +1,409 @@
/*
* Copyright 2006 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.afp.modca;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

import org.apache.fop.render.afp.AFPFontColor;
import org.apache.fop.render.afp.fonts.AFPFont;
import org.apache.fop.render.afp.tools.StringUtils;

/**
* Pages contain the data objects that comprise a presentation document. Each
* page has a set of data objects associated with it. Each page within a
* document is independent from any other page, and each must establish its own
* environment parameters.
*
* The page is the level in the document component hierarchy that is used for
* printing or displaying a document's content. The data objects contained in
* the page envelope in the data stream are presented when the page is
* presented. Each data object has layout information associated with it that
* directs the placement and orientation of the data on the page. In addition,
* each page contains layout information that specifies the measurement units,
* page width, and page depth.
*
* A page is initiated by a begin page structured field and terminated by an end
* page structured field. Structured fields that define objects and active
* environment groups or that specify attributes of the page may be encountered
* in page state.
*
*/
public abstract class AbstractPageObject extends AbstractNamedAFPObject {

/**
* The active environment group for the page
*/
protected ActiveEnvironmentGroup _activeEnvironmentGroup = null;

/**
* The presentation text object, we only have one per page
*/
private PresentationTextObject _presentationTextObject = null;

/**
* The list of objects within the page
*/
protected List _objects = new ArrayList();

/**
* The list of tag logical elements
*/
protected ArrayList _tagLogicalElements = new ArrayList();

/**
* The list of the include page segments
*/
protected ArrayList _segments = new ArrayList();

/**
* The page width
*/
private int _width;

/**
* The page height
*/
private int _height;

/**
* The page rotation
*/
private int _rotation = 0;

/**
* The page state
*/
private boolean _complete = false;

/**
* Construct a new page object for the specified name argument, the page
* name should be an 8 character identifier.
*
* @param name
* the name of the page.
* @param width
* the width of the page.
* @param height
* the height of the page.
* @param rotation
* the rotation of the page.
*/
public AbstractPageObject(String name, int width, int height, int rotation) {

super(name);

_name = name;

_rotation = rotation;
_width = width;
_height = height;

/**
* Every page object must have an ActiveEnvironmentGroup
*/
_activeEnvironmentGroup = new ActiveEnvironmentGroup(_width, _height);

if (_rotation != 0) {
switch (_rotation) {
case 90:
_activeEnvironmentGroup.setPosition(_width, 0, _rotation);
break;
case 180:
_activeEnvironmentGroup.setPosition(_width, _height, _rotation);
break;
case 270:
_activeEnvironmentGroup.setPosition(0, _height, _rotation);
break;
}
}

/**
* We have a presentation text object per page
*/
_presentationTextObject = new PresentationTextObject();
_objects.add(_presentationTextObject);

}

/**
* Helper method to create a map coded font object on the current page, this
* method delegates the construction of the map coded font object to the
* active environment group on the page.
*
* @param fontReference
* the font number used as the resource identifier
* @param font
* the font
* @param size
* the point size of the font
*/
public void createFont(byte fontReference, AFPFont font, int size) {

_activeEnvironmentGroup.createFont(fontReference, font, size, 0);

}

/**
* Helper method to create a line on the current page, this method delegates
* to the presentation text object in order to construct the line.
*
* @param x1
* the first x coordinate of the line
* @param y1
* the first y coordinate of the line
* @param x2
* the second x coordinate of the line
* @param y2
* the second y coordinate of the line
* @param thickness
* the thickness of the line
* @param rotation
* the rotation of the line
* @param col
* The text color.
*/
public void createLine(int x1, int y1, int x2, int y2, int thickness, int rotation, AFPFontColor col) {

if (_presentationTextObject == null) {
_presentationTextObject = new PresentationTextObject();
_objects.add(_presentationTextObject);
}
_presentationTextObject.createLineData(x1, y1, x2, y2, thickness, rotation, col);

}

/**
* Helper method to create text on the current page, this method delegates
* to the presentation text object in order to construct the text.
*
* @param fontNumber
* the font number used as the resource identifier
* @param x
* the x coordinate of the text data
* @param y
* the y coordinate of the text data
* @param rotation
* the rotation of the text data
* @param col
* the text color
* @param vsci
* The variable space character increment.
* @param ica
* The inter character adjustment.
* @param data
* the text data to create
*/
public void createText(int fontNumber, int x, int y, int rotation, AFPFontColor col, int vsci, int ica, byte[] data) {

if (_presentationTextObject == null) {
_presentationTextObject = new PresentationTextObject();
_objects.add(_presentationTextObject);
}
_presentationTextObject.createTextData(fontNumber, x, y, rotation, col, vsci, ica, data);

}

/**
* Helper method to mark the end of the page. This should end the control
* sequence on the current presenation text object.
*/
public void endPage() {

_presentationTextObject.endControlSequence();

_complete = true;

}

/**
* This method will create shading on the page using the specified
* coordinates (the shading contrast is controlled via the red, green blue
* parameters, by converting this to grey scale).
*
* @param x
* the x coordinate of the shading
* @param y
* the y coordinate of the shading
* @param w
* the width of the shaded area
* @param h
* the height of the shaded area
* @param red
* the red value
* @param green
* the green value
* @param blue
* the blue value
*/
public void createShading(int x, int y, int w, int h, int red, int green,
int blue) {

int xCoord = 0;
int yCoord = 0;
int width = 0;
int height = 0;

switch (_rotation) {
case 90:
xCoord = _width - y - h;
yCoord = x;
width = h;
height = w;
break;
case 180:
xCoord = _width - x - w;
yCoord = _height - y - h;
width = w;
height = h;
break;
case 270:
xCoord = y;
yCoord = _height - x - w;
width = h;
height = w;
break;
default:
xCoord = x;
yCoord = y;
width = w;
height = h;
break;
}

// Convert the color to grey scale
float shade = (float) ((red * 0.3) + (green * 0.59) + (blue * 0.11));

int greyscale = Math.round((shade / 255) * 16);

String imageName = "IMG"
+ StringUtils.lpad(String.valueOf(_objects.size() + 1),
'0', 5);

IMImageObject io = new IMImageObject(imageName);
ImageOutputControl ioc = new ImageOutputControl(0, 0);
ImageInputDescriptor iid = new ImageInputDescriptor();
ImageCellPosition icp = new ImageCellPosition(xCoord, yCoord);
icp.setXFillSize(width);
icp.setYFillSize(height);
icp.setXSize(64);
icp.setYSize(8);

//defing this as a resource
ImageRasterData ird = new ImageRasterData(ImageRasterPattern
.getRasterData(greyscale));

io.setImageOutputControl(ioc);
io.setImageInputDescriptor(iid);
io.setImageCellPosition(icp);
io.setImageRasterData(ird);
_objects.add(io);

}

/**
* Helper method to create an image on the current page and to return
* the object.
*/
public ImageObject getImageObject() {

if (_presentationTextObject != null) {
_presentationTextObject.endControlSequence();
}
_presentationTextObject = null;

String imageName = "IMG"
+ StringUtils.lpad(String.valueOf(_objects.size() + 1),
'0', 5);

ImageObject io = new ImageObject(imageName);
_objects.add(io);
return io;
}

/**
* Creates a TagLogicalElement on the page.
*
* @param name
* the name of the tag
* @param value
* the value of the tag
*/
public void createTagLogicalElement(String name, String value) {

TagLogicalElement tle = new TagLogicalElement(name, value);
_tagLogicalElements.add(tle);

}

/**
* Creates an IncludePageSegment on the current page.
*
* @param name
* the name of the page segment
* @param xCoor
* the x cooridinate of the page segment.
* @param yCoor
* the y cooridinate of the page segment.
*/
public void createIncludePageSegment(String name, int xCoor, int yCoor) {

IncludePageSegment ips = new IncludePageSegment(name, xCoor, yCoor);
_segments.add(ips);

}

/**
* Returns the ActiveEnvironmentGroup associated with this page.
*
* @return the ActiveEnvironmentGroup object
*/
public ActiveEnvironmentGroup getActiveEnvironmentGroup() {
return _activeEnvironmentGroup;
}

/**
* Returns an indication if the page is complete
*/
public boolean isComplete() {
return _complete;
}

/**
* Returns the height of the page
*/
public int getHeight() {
return _height;
}

/**
* Returns the width of the page
*/
public int getWidth() {
return _width;
}

/**
* Returns the rotation of the page
*/
public int getRotation() {
return _rotation;
}

}

+ 345
- 0
src/sandbox/org/apache/fop/render/afp/modca/ActiveEnvironmentGroup.java 查看文件

@@ -0,0 +1,345 @@
/*
* Copyright 2006 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.afp.modca;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import org.apache.fop.render.afp.fonts.AFPFont;

/**
* An Active Environment Group (AEG) is associated with each page,
* and is contained in the page's begin-end envelope in the data stream.
* The active environment group contains layout and formatting information
* that defines the measurement units and size of the page, and may contain
* resource information.
*
* Any objects that are required for page presentation and that are to be
* treated as resource objects must be mapped with a map structured field
* in the AEG. The scope of an active environment group is the scope of its
* containing page or overlay.
*
*/
public final class ActiveEnvironmentGroup extends AbstractNamedAFPObject {

/**
* Default name for the active environment group
*/
private static final String DEFAULT_NAME = "AEG00001";

/**
* The collection of MapCodedFont objects
*/
private ArrayList _mapCodedFonts = new ArrayList();

/**
* The Object Area Descriptor for the active environment group
*/
private ObjectAreaDescriptor _objectAreaDescriptor = null;

/**
* The Object Area Position for the active environment group
*/
private ObjectAreaPosition _objectAreaPosition = null;

/**
* The PresentationTextDescriptor for the active environment group
*/
private PresentationTextDescriptor _presentationTextDataDescriptor = null;

/**
* The PageDescriptor for the active environment group
*/
private PageDescriptor _pageDescriptor = null;

/**
* The collection of MapPageOverlay objects
*/
private ArrayList _mapPageOverlays = new ArrayList();

/**
* Default constructor for the ActiveEnvironmentGroup.
* @param width the page width
* @param height the page height
*/
public ActiveEnvironmentGroup(int width, int height) {

this(DEFAULT_NAME, width, height);

}

/**
* Constructor for the ActiveEnvironmentGroup, this takes a
* name parameter which must be 8 characters long.
* @param name the active environment group name
* @param width the page width
* @param height the page height
*/
public ActiveEnvironmentGroup(String name, int width, int height) {

super(name);

// Create PageDescriptor
_pageDescriptor = new PageDescriptor(width, height);

// Create ObjectAreaDescriptor
_objectAreaDescriptor = new ObjectAreaDescriptor(width, height);

// Create PresentationTextDataDescriptor
_presentationTextDataDescriptor =
new PresentationTextDescriptor(width, height);

}

/**
* Set the position of the object area
* @param x the x offset
* @param y the y offset
* @param rotation the rotation
*/
public void setPosition(int x, int y, int rotation) {

// Create ObjectAreaPosition
_objectAreaPosition = new ObjectAreaPosition(x, y, rotation);

}

/**
* Accessor method to obtain the PageDescriptor object of the
* active environment group.
* @return the page descriptor object
*/
public PageDescriptor getPageDescriptor() {

return _pageDescriptor;

}

/**
* Accessor method to obtain the PresentationTextDataDescriptor object of
* the active environment group.
* @return the presentation text descriptor
*/
public PresentationTextDescriptor getPresentationTextDataDescriptor() {

return _presentationTextDataDescriptor;

}

/**
* Accessor method to write the AFP datastream for the active environment group.
* @param os The stream to write to
* @throws java.io.IOException
*/
public void writeDataStream(OutputStream os)
throws IOException {

writeStart(os);

writeObjectList(_mapCodedFonts, os);

writeObjectList(_mapPageOverlays, os);

_pageDescriptor.writeDataStream(os);

if (_objectAreaDescriptor != null && _objectAreaPosition != null) {
_objectAreaDescriptor.writeDataStream(os);
_objectAreaPosition.writeDataStream(os);
}

_presentationTextDataDescriptor.writeDataStream(os);

writeEnd(os);

}

/**
* Helper method to write the start of the active environment group.
* @param os The stream to write to
*/
private void writeStart(OutputStream os)
throws IOException {

byte[] data = new byte[17];

data[0] = 0x5A; // Structured field identifier
data[1] = 0x00; // Length byte 1
data[2] = 0x10; // Length byte 2
data[3] = (byte) 0xD3; // Structured field id byte 1
data[4] = (byte) 0xA8; // Structured field id byte 2
data[5] = (byte) 0xC9; // Structured field id byte 3
data[6] = 0x00; // Flags
data[7] = 0x00; // Reserved
data[8] = 0x00; // Reserved

for (int i = 0; i < _nameBytes.length; i++) {

data[9 + i] = _nameBytes[i];

}

os.write(data);

}

/**
* Helper method to write the end of the active environment group.
* @param os The stream to write to
*/
private void writeEnd(OutputStream os)
throws IOException {

byte[] data = new byte[17];

data[0] = 0x5A; // Structured field identifier
data[1] = 0x00; // Length byte 1
data[2] = 0x10; // Length byte 2
data[3] = (byte) 0xD3; // Structured field id byte 1
data[4] = (byte) 0xA9; // Structured field id byte 2
data[5] = (byte) 0xC9; // Structured field id byte 3
data[6] = 0x00; // Flags
data[7] = 0x00; // Reserved
data[8] = 0x00; // Reserved

for (int i = 0; i < _nameBytes.length; i++) {

data[9 + i] = _nameBytes[i];

}

os.write(data);

}

/**
* Method to create a map coded font object
* @param fontReference the font number used as the resource identifier
* @param font the font
* @param size the point size of the font
* @param orientation the orientation of the font (e.g. 0, 90, 180, 270)
*/
public void createFont(
byte fontReference,
AFPFont font,
int size,
int orientation) {

MapCodedFont mcf = getCurrentMapCodedFont();

if (mcf == null) {
mcf = new MapCodedFont();
_mapCodedFonts.add(mcf);
}

try {

mcf.addFont(
fontReference,
font,
size,
orientation);

} catch (MaximumSizeExceededException msee) {

mcf = new MapCodedFont();
_mapCodedFonts.add(mcf);

try {

mcf.addFont(
fontReference,
font,
size,
orientation);

} catch (MaximumSizeExceededException ex) {

// Should never happen (but log just in case)
log.error("createFont():: resulted in a MaximumSizeExceededException");

}

}

}

/**
* Actually creates the MPO object.
* Also creates the supporting object (an IPO)
* @param name the name of the overlay to be used
*/
public void createOverlay(String name) {

MapPageOverlay mpo = getCurrentMapPageOverlay();

if (mpo == null) {
mpo = new MapPageOverlay();
_mapPageOverlays.add(mpo);
}

try {

mpo.addOverlay(name);

} catch (MaximumSizeExceededException msee) {
mpo = new MapPageOverlay();
_mapPageOverlays.add(mpo);
try {
mpo.addOverlay(name);
} catch (MaximumSizeExceededException ex) {
// Should never happen (but log just in case)
log.error("createOverlay():: resulted in a MaximumSizeExceededException");
}
}
}

/**
* Getter method for the most recent MapCodedFont added to the
* Active Environment Group (returns null if no MapCodedFonts exist)
* @return the most recent Map Coded Font.
*/
private MapCodedFont getCurrentMapCodedFont() {

int size = _mapCodedFonts.size();
if (size > 0) {
return (MapCodedFont) _mapCodedFonts.get(_mapCodedFonts.size() - 1);
} else {
return null;
}

}

/**
* Getter method for the most recent MapPageOverlay added to the
* Active Environment Group (returns null if no MapPageOverlay exist)
* @return the most recent Map Coded Font
*/
private MapPageOverlay getCurrentMapPageOverlay() {

int size = _mapPageOverlays.size();
if (size > 0) {
return (MapPageOverlay) _mapPageOverlays.get(
_mapPageOverlays.size() - 1);
} else {
return null;
}

}

}

+ 213
- 0
src/sandbox/org/apache/fop/render/afp/modca/Document.java 查看文件

@@ -0,0 +1,213 @@
/*
* Copyright 2006 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.afp.modca;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Iterator;


/**
* The document is the highest level of the MO:DCA data-stream document
* component hierarchy. Documents can be made up of pages, and the pages,
* which are at the intermediate level, can be made up of objects. Objects
* are at the lowest level, and can be bar codes, graphics, images, and
* presentation text.
*
* At each level of the hierarchy certain sets of MO:DCA data structures,
* called structured fields, are permissible. The document, pages and objects
* are bounded by structured fields that define their beginnings and their ends.
* These structured fields, called begin-end pairs, provide an envelope for the
* data-stream components. This feature enables a processor of the data stream
* that is not fully compliant with the architecture to bypass those objects
* that are beyond its scope, and to process the data stream to the best of its
* abilities.
*
* A presentation document is one that has been formatted and is intended for
* presentation, usually on a printer or display device. A data stream containing
* a presentation document should produce the same document content in the
* same format on different printers or display devices dependent, however,
* on the capabilities of each of the printers or display devices. A presentation
* document can reference resources that are to be included as part of the
* document to be presented.
*
*/
public final class Document extends AbstractNamedAFPObject {

/**
* Ststic default name reference
*/
private final static String DEFAULT_NAME = "DOC00001";

/**
* A list of the objects in the document
*/
private ArrayList _objects = new ArrayList();

/**
* The document started state
*/
private boolean _started = false;

/**
* The document completion state
*/
private boolean _complete = false;

/**
* Default constructor for the document object.
*/
public Document() {
this(DEFAULT_NAME);
}

/**
* Constructor for the document object.
* @param name The name of the document
*/
public Document(String name) {

super(name);

}

/**
* Adds a page to the document.
* @param page - the Page object
*/
public void addPage(PageObject page) {
if (!_objects.contains(page)) {
_objects.add(page);
}
}

/**
* Adds a PageGroup to the document.
* @param pageGroup the PageGroup object
*/
public void addPageGroup(PageGroup pageGroup) {
_objects.add(pageGroup);
}

/**
* Method to mark the end of the page group.
*/
public void endDocument() {

_complete = true;

}

/**
* Returns an indication if the page group is complete
*/
public boolean isComplete() {
return _complete;
}

/**
* Accessor method to write the AFP datastream for document.
* @param os The stream to write to
* @throws java.io.IOException
*/
public void writeDataStream(OutputStream os)
throws IOException {

if (!_started) {
writeStart(os);
_started = true;
}

for (Iterator it = _objects.iterator(); it.hasNext(); ) {
AbstractAFPObject ao = (AbstractAFPObject)it.next();
if (ao instanceof PageObject && ((PageObject)ao).isComplete()
|| ao instanceof PageGroup && ((PageGroup)ao).isComplete()) {
ao.writeDataStream(os);
it.remove();
} else {
break;
}
}

if (_complete) {
writeEnd(os);
}

}

/**
* Helper method to write the start of the Document
* @param os The stream to write to
*/
private void writeStart(OutputStream os)
throws IOException {

byte[] data = new byte[17];

data[0] = 0x5A; // Structured field identifier
data[1] = 0x00; // Length byte 1
data[2] = 0x10; // Length byte 2
data[3] = (byte) 0xD3; // Structured field id byte 1
data[4] = (byte) 0xA8; // Structured field id byte 2
data[5] = (byte) 0xA8; // Structured field id byte 3
data[6] = 0x00; // Flags
data[7] = 0x00; // Reserved
data[8] = 0x00; // Reserved

for (int i = 0; i < _nameBytes.length; i++) {

data[9 + i] = _nameBytes[i];

}

os.write(data);

}

/**
* Helper method to write the end of the Document.
* @param os The stream to write to
*/
private void writeEnd(OutputStream os)
throws IOException {

byte[] data = new byte[17];

data[0] = 0x5A; // Structured field identifier
data[1] = 0x00; // Length byte 1
data[2] = 0x10; // Length byte 2
data[3] = (byte) 0xD3; // Structured field id byte 1
data[4] = (byte) 0xA9; // Structured field id byte 2
data[5] = (byte) 0xA8; // Structured field id byte 3
data[6] = 0x00; // Flags
data[7] = 0x00; // Reserved
data[8] = 0x00; // Reserved

for (int i = 0; i < _nameBytes.length; i++) {

data[9 + i] = _nameBytes[i];

}

os.write(data);

}

}

+ 74
- 0
src/sandbox/org/apache/fop/render/afp/modca/EndPageGroup.java 查看文件

@@ -0,0 +1,74 @@
/*
* Copyright 2006 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.afp.modca;

import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;

/**
* The End Named Page Group (ENG) structured field terminates a page group that was
* initiated by a Begin Named Page Group structured field.
*
* Note :This object will be used to represent an ENG
* structured field. It is necessary as you can't end
* a PageGroup because you don't know where the group
* will end (as this is controlled by the tags in the FO).
* <p>
*
*/
public class EndPageGroup extends AbstractNamedAFPObject {

public EndPageGroup(String groupId) {

super(groupId);

log.debug("A ENG is being created for group: " + groupId);

}

/**
* Accessor method to write the AFP datastream for the End Page Group.
* @param os The stream to write to
* @throws java.io.IOException
*/
public void writeDataStream(OutputStream os)
throws IOException {
byte[] data = new byte[17];

data[0] = 0x5A; // Structured field identifier
data[1] = 0x00; // Length byte 1
data[2] = 0x10; // Length byte 2
data[3] = (byte) 0xD3; // Structured field id byte 1
data[4] = (byte) 0xA9; // Structured field id byte 2
data[5] = (byte) 0xAD; // Structured field id byte 3
data[6] = 0x00; // Flags
data[7] = 0x00; // Reserved
data[8] = 0x00; // Reserved

for (int i = 0; i < _nameBytes.length; i++) {

data[9 + i] = _nameBytes[i];

}

os.write(data);
}

}

+ 190
- 0
src/sandbox/org/apache/fop/render/afp/modca/IMImageObject.java 查看文件

@@ -0,0 +1,190 @@
/*
* Copyright 2006 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.afp.modca;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;

/**
* An IM image data object specifies the contents of a raster image and
* its placement on a page, overlay, or page segment. An IM image can be
* either simple or complex. A simple image is composed of one or more Image
* Raster Data (IRD) structured fields that define the raster pattern for the
* entire image. A complex image is divided into regions called image cells.
* Each image cell is composed of one or more IRD structured fields that define
* the raster pattern for the image cell, and one Image Cell Position (ICP)
* structured field that defines the position of the image cell relative to
* the origin of the entire image. Each ICP also specifies the size of the
* image cell and a fill rectangle into which the cell is replicated.
* <p/>
*/
public class IMImageObject extends AbstractNamedAFPObject {

/**
* The image output control
*/
private ImageOutputControl _imageOutputControl = null;

/**
* The image input descriptor
*/
private ImageInputDescriptor _imageInputDescriptor = null;

/**
* The image cell position
*/
private ImageCellPosition _imageCellPosition = null;

/**
* The image rastor data
*/
private ImageRasterData _imageRastorData = null;

/**
* Constructor for the image object with the specified name,
* the name must be a fixed length of eight characters.
* @param name The name of the image.
*/
public IMImageObject(String name) {

super(name);

}

/**
* Sets the ImageOutputControl.
* @param imageOutputControl The imageOutputControl to set
*/
public void setImageOutputControl(ImageOutputControl imageOutputControl) {
_imageOutputControl = imageOutputControl;
}

/**
* Sets the ImageCellPosition.
* @param imageCellPosition The imageCellPosition to set
*/
public void setImageCellPosition(ImageCellPosition imageCellPosition) {
_imageCellPosition = imageCellPosition;
}

/**
* Sets the ImageInputDescriptor.
* @param imageInputDescriptor The imageInputDescriptor to set
*/
public void setImageInputDescriptor(ImageInputDescriptor imageInputDescriptor) {
_imageInputDescriptor = imageInputDescriptor;
}

/**
* Sets the ImageRastorData.
* @param imageRastorData The imageRastorData to set
*/
public void setImageRasterData(ImageRasterData imageRastorData) {
_imageRastorData = imageRastorData;
}

/**
* Accessor method to write the AFP datastream for the IM Image Objetc
* @param os The stream to write to
* @throws java.io.IOException
*/
public void writeDataStream(OutputStream os)
throws IOException {

writeStart(os);

if (_imageOutputControl != null) {
_imageOutputControl.writeDataStream(os);
}

if (_imageInputDescriptor != null) {
_imageInputDescriptor.writeDataStream(os);
}

if (_imageCellPosition != null) {
_imageCellPosition.writeDataStream(os);
}

if (_imageRastorData != null) {
_imageRastorData.writeDataStream(os);
}

writeEnd(os);

}

/**
* Helper method to write the start of the IM Image Object.
* @param os The stream to write to
*/
private void writeStart(OutputStream os)
throws IOException {

byte[] data = new byte[17];

data[0] = 0x5A; // Structured field identifier
data[1] = 0x00; // Length byte 1
data[2] = 0x10; // Length byte 2
data[3] = (byte) 0xD3; // Structured field id byte 1
data[4] = (byte) 0xA8; // Structured field id byte 2
data[5] = (byte) 0x7B; // Structured field id byte 3
data[6] = 0x00; // Flags
data[7] = 0x00; // Reserved
data[8] = 0x00; // Reserved

for (int i = 0; i < _nameBytes.length; i++) {

data[9 + i] = _nameBytes[i];

}

os.write(data);

}

/**
* Helper method to write the end of the IM Image Object.
* @param os The stream to write to
*/
private void writeEnd(OutputStream os)
throws IOException {

byte[] data = new byte[17];

data[0] = 0x5A; // Structured field identifier
data[1] = 0x00; // Length byte 1
data[2] = 0x10; // Length byte 2
data[3] = (byte) 0xD3; // Structured field id byte 1
data[4] = (byte) 0xA9; // Structured field id byte 2
data[5] = (byte) 0x7B; // Structured field id byte 3
data[6] = 0x00; // Flags
data[7] = 0x00; // Reserved
data[8] = 0x00; // Reserved

for (int i = 0; i < _nameBytes.length; i++) {

data[9 + i] = _nameBytes[i];

}

os.write(data);

}

}

+ 193
- 0
src/sandbox/org/apache/fop/render/afp/modca/ImageCellPosition.java 查看文件

@@ -0,0 +1,193 @@
/*
* Copyright 2006 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.afp.modca;

import java.io.IOException;
import java.io.OutputStream;
import org.apache.fop.render.afp.tools.BinaryUtils;

/**
* The IM Image Cell Position structured field specifies the placement,
* size, and replication of IM image cells.
*/
public class ImageCellPosition extends AbstractAFPObject {

/**
* Offset of image cell in X direction
*/
private int _XcoSet = 0;

/**
* Offset of image cell in Y direction
*/
private int _YcoSet = 0;

/**
* Size of image cell in X direction
*/
private byte[] _XcSize = new byte[] { (byte)0xFF, (byte)0xFF };

/**
* Size of image cell in Y direction
*/
private byte[] _YcSize = new byte[] { (byte)0xFF, (byte)0xFF };

/**
* Size of fill rectangle in X direction
*/
private byte[] _XFillSize = new byte[] { (byte)0xFF, (byte)0xFF };

/**
* Size of fill rectangle in Y direction
*/
private byte[] _YFillSize = new byte[] { (byte)0xFF, (byte)0xFF };

/**
* Constructor for the ImageCellPosition
* @param x The offset of image cell in X direction
* @param y The offset of image cell in Y direction
*/
public ImageCellPosition(int x, int y) {

_XcoSet = x;
_YcoSet = y;

}

/**
* Accessor method to write the AFP datastream for the Image Cell Position
* @param os The stream to write to
* @throws java.io.IOException
*/
public void writeDataStream(OutputStream os)
throws IOException {

byte[] data = new byte[21];

data[0] = 0x5A;

data[1] = 0x00;
data[2] = 0x14;

data[3] = (byte) 0xD3;
data[4] = (byte) 0xAC;
data[5] = (byte) 0x7B;
data[6] = 0x00;
data[7] = 0x00;
data[8] = 0x00;

/**
* Specifies the offset along the Xp direction, in image points,
* of this image cell from the IM image object area origin.
*/
byte[] x1 = BinaryUtils.convert(_XcoSet, 2);
data[9] = x1[0];
data[10] = x1[1];

/**
* Specifies the offset along the Yp direction, in image points,
* of this image cell from the IM image object area origin.
*/
byte[] x2 = BinaryUtils.convert(_YcoSet, 2);
data[11] = x2[0];
data[12] = x2[1];

data[13] = _XcSize[0];
data[14] = _XcSize[1];

data[15] = _YcSize[0];
data[16] = _YcSize[1];

data[17] = _XFillSize[0];
data[18] = _XFillSize[1];

data[19] = _YFillSize[0];
data[20] = _YFillSize[1];

os.write(data);

}

/**
* Specifies the extent in the X direction, in image points,
* of this image cell. A value of X'FFFF' indicates that the
* default extent specified in bytes 28 and 29 of the Image
* Input Descriptor (IID) is to be used.
* @param xcSize The size to set.
*/
public void setXSize(int xcSize) {

byte[] x = BinaryUtils.convert(xcSize, 2);
_XcSize[0] = x[0];
_XcSize[1] = x[1];

}

/**
* Specifies the extent of the fill rectangle in the X direction,
* in image points. This value can be smaller than, equal to, or
* larger than the image cell extent in the X direction (XCSize).
* A value of X'FFFF' indicates that the image cell X-extent should
* be used as the fill rectangle X-extent. The fill rectangle is
* filled in the X direction by repeating the image cell in the
* X direction. The image cell can be truncated to fit the rectangle.
* @param xFillSize The size to set.
*/
public void setXFillSize(int xFillSize) {

byte[] x = BinaryUtils.convert(xFillSize, 2);
_XFillSize[0] = x[0];
_XFillSize[1] = x[1];

}

/**
* Specifies the extent in the Y direction, in image points,
* of this image cell. A value of X'FFFF' indicates that the
* default extent specified in bytes 30 and 31 of the Image
* Input Descriptor (IID) is to be used.
* @param ycSize The size to set.
*/
public void setYSize(int ycSize) {

byte[] x = BinaryUtils.convert(ycSize, 2);
_YcSize[0] = x[0];
_YcSize[1] = x[1];

}

/**
* Specifies the extent of the fill rectangle in the Y direction,
* in image points. This value can be smaller than, equal to, or
* larger than the image cell extent in the Y direction (YCSize).
* A value of X'FFFF' indicates that the image cell Y-extent should
* be used as the fill rectangle Y-extent. The fill rectangle is
* filled in the Y direction by repeating the image cell in the
* Y direction. The image cell can be truncated to fit the rectangle.
* @param yFillSize The size to set.
*/
public void setYFillSize(int yFillSize) {

byte[] x = BinaryUtils.convert(yFillSize, 2);
_YFillSize[0] = x[0];
_YFillSize[1] = x[1];

}

}

+ 294
- 0
src/sandbox/org/apache/fop/render/afp/modca/ImageContent.java 查看文件

@@ -0,0 +1,294 @@
/*
* Copyright 2006 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.afp.modca;
import java.io.IOException;
import java.io.OutputStream;
import org.apache.fop.render.afp.tools.BinaryUtils;

/**
*/
public class ImageContent extends AbstractAFPObject {

/**
* The image size parameter
*/
private ImageSizeParameter _imageSizeParameter = null;

/**
* The image encoding
*/
private byte _encoding = 0x03;

/**
* The image ide size
*/
private byte _size = 1;

/**
* The image compression
*/
private byte _compression = (byte)0xC0;

/**
* The image color model
*/
private byte _colorModel = 0x01;

/**
* The image data
*/
private byte _data[] = null;

/**
* Constructor for the image content
*/
public ImageContent() {

}

/**
* Sets the image size parameters
* resolution, hsize and vsize.
* @param hresol The horizontal resolution of the image.
* @param vresol The vertical resolution of the image.
* @param hsize The horizontal size of the image.
* @param vsize The vertival size of the image.
*/
public void setImageSize(int hresol, int vresol, int hsize, int vsize) {
_imageSizeParameter = new ImageSizeParameter(hresol, vresol, hsize, vsize);
}

/**
* Sets the image encoding.
* @param encoding The image encoding.
*/
public void setImageEncoding(byte encoding) {
_encoding = encoding;
}

/**
* Sets the image compression.
* @param compression The image compression.
*/
public void setImageCompression(byte compression) {
_compression = compression;
}

/**
* Sets the image IDE size.
* @param size The IDE size.
*/
public void setImageIDESize(byte size) {
_size = size;
}

/**
* Sets the image IDE color model.
* @param size The IDE color model.
*/
public void setImageIDEColorModel(byte colorModel) {
_colorModel = colorModel;
}

/**
* Set the data of the image.
*/
public void setImageData(byte data[]) {
_data = data;
}

/**
* Accessor method to write the AFP datastream for the Image Content
* @param os The stream to write to
* @throws java.io.IOException
*/
public void writeDataStream(OutputStream os)
throws IOException {

writeStart(os);

if (_imageSizeParameter != null) {
_imageSizeParameter.writeDataStream(os);
}

os.write(getImageEncodingParameter());

os.write(getImageIDESizeParameter());

os.write(getIDEStructureParameter());

os.write(getExternalAlgorithmParameter());

if (_data != null) {
int off = 0;
while (off < _data.length) {
int len = Math.min(30000, _data.length - off);
os.write(getImageDataStart(len));
os.write(_data, off, len);
off += len;
}
}

writeEnd(os);

}

/**
* Helper method to write the start of the Image Content.
* @param os The stream to write to
*/
private void writeStart(OutputStream os)
throws IOException {

byte[] data = new byte[] {
(byte)0x91, // ID
0x01, // Length
(byte)0xff, // Object Type = IOCA Image Object
};

os.write(data);

}

/**
* Helper method to write the end of the Image Content.
* @param os The stream to write to
*/
private void writeEnd(OutputStream os)
throws IOException {

byte[] data = new byte[] {
(byte)0x93, // ID
0x00, // Length
};

os.write(data);

}

/**
* Helper method to return the start of the image segment.
* @return byte[] The data stream.
*/
private byte[] getImageDataStart(int len) {

byte[] data = new byte[] {
(byte)0xFE, // ID
(byte)0x92, // ID
0x00, // Length
0x00, // Length
};

byte[] l = BinaryUtils.convert(len, 2);
data[2] = l[0];
data[3] = l[1];


return data;

}

/**
* Helper method to return the image encoding parameter.
* @return byte[] The data stream.
*/
private byte[] getImageEncodingParameter() {

byte[] data = new byte[] {
(byte)0x95, // ID
0x02, // Length
_encoding,
0x01, // RECID
};

return data;

}

/**
* Helper method to return the external algorithm parameter.
* @return byte[] The data stream.
*/
private byte[] getExternalAlgorithmParameter() {

if (_encoding == (byte)0x83 && _compression != 0) {
byte[] data = new byte[] {
(byte)0x95, // ID
0x00, // Length
0x10, // ALGTYPE = Compression Algorithm
0x00, // Reserved
(byte)0x83, // COMPRID = JPEG
0x00, // Reserved
0x00, // Reserved
0x00, // Reserved
_compression, // MARKER
0x00, // Reserved
0x00, // Reserved
0x00, // Reserved
};
data[1] = (byte)(data.length - 2);
return data;
}
return new byte[0];
}

/**
* Helper method to return the image encoding parameter.
* @return byte[] The data stream.
*/
private byte[] getImageIDESizeParameter() {

byte[] data = new byte[] {
(byte)0x96, // ID
0x01, // Length
_size,
};

return data;

}

/**
* Helper method to return the external algorithm parameter.
* @return byte[] The data stream.
*/
private byte[] getIDEStructureParameter() {

if (_colorModel != 0 && _size == 24) {
byte bits = (byte)(_size / 3);
byte[] data = new byte[] {
(byte)0x9B, // ID
0x00, // Length
0x00, // FLAGS
0x00, // Reserved
_colorModel, // COLOR MODEL
0x00, // Reserved
0x00, // Reserved
0x00, // Reserved
bits,
bits,
bits,
};
data[1] = (byte)(data.length - 2);
return data;
}
return new byte[0];
}

}

+ 108
- 0
src/sandbox/org/apache/fop/render/afp/modca/ImageDataDescriptor.java 查看文件

@@ -0,0 +1,108 @@
/*
* Copyright 2006 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.afp.modca;

import java.io.IOException;
import java.io.OutputStream;
import org.apache.fop.render.afp.tools.BinaryUtils;

/**
*/
public class ImageDataDescriptor extends AbstractAFPObject {

private int _xresol = 0;
private int _yresol = 0;
private int _width = 0;
private int _height = 0;

/**
* Constructor for a ImageDataDescriptor for the specified
* resolution, width and height.
* @param xresol The horizontal resolution of the image.
* @param yresol The vertical resolution of the image.
* @param width The width of the image.
* @param height The height of the height.
*/
public ImageDataDescriptor(int xresol, int yresol, int width, int height) {

_xresol = xresol;
_yresol = yresol;
_width = width;
_height = height;

}

/**
* Accessor method to write the AFP datastream for the Image Data Descriptor
* @param os The stream to write to
* @throws java.io.IOException
*/
public void writeDataStream(OutputStream os)
throws IOException {

byte[] data = new byte[] {
0x5A,
0x00,
0x20,
(byte) 0xD3,
(byte) 0xA6,
(byte) 0xFB,
0x00, // Flags
0x00, // Reserved
0x00, // Reserved
0x00, // Unit base - 10 Inches
0x00, // XRESOL
0x00, //
0x00, // YRESOL
0x00, //
0x00, // XSIZE
0x00, //
0x00, // YSIZE
0x00, //
(byte)0xF7, // ID = Set IOCA Function Set
0x02, // Length
0x01, // Category = Function set identifier
0x0B, // FCNSET = IOCA FS 11
};

byte[] l = BinaryUtils.convert(data.length - 1, 2);
data[1] = l[0];
data[2] = l[1];

byte[] x = BinaryUtils.convert(_xresol, 2);
data[10] = x[0];
data[11] = x[1];

byte[] y = BinaryUtils.convert(_yresol, 2);
data[12] = y[0];
data[13] = y[1];

byte[] w = BinaryUtils.convert(_width, 2);
data[14] = w[0];
data[15] = w[1];

byte[] h = BinaryUtils.convert(_height, 2);
data[16] = h[0];
data[17] = h[1];

os.write(data);

}

}

+ 146
- 0
src/sandbox/org/apache/fop/render/afp/modca/ImageInputDescriptor.java 查看文件

@@ -0,0 +1,146 @@
/*
* Copyright 2006 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.afp.modca;

import java.io.IOException;
import java.io.OutputStream;
import org.apache.fop.render.afp.tools.BinaryUtils;

/**
* The IM Image Input Descriptor structured field contains the
* descriptor data for an IM image data object. This data specifies
* the resolution, size, and color of the IM image.
*/
public class ImageInputDescriptor extends AbstractAFPObject {

/**
* The resolution of the raster image (default 240)
*/
private int _resolution = 240;


/**
* Accessor method to write the AFP datastream for the Image Input Descriptor
* @param os The stream to write to
* @throws java.io.IOException
*/
public void writeDataStream(OutputStream os)
throws IOException {

byte[] data = new byte[45];

data[0] = 0x5A;
data[1] = 0x00;
data[2] = 0x2C;
data[3] = (byte) 0xD3;
data[4] = (byte) 0xA6;
data[5] = (byte) 0x7B;
data[6] = 0x00;
data[7] = 0x00;
data[8] = 0x00;

// Constant data.
data[9] = 0x00;
data[10] = 0x00;
data[11] = 0x09;
data[12] = 0x60;
data[13] = 0x09;
data[14] = 0x60;
data[15] = 0x00;
data[16] = 0x00;
data[17] = 0x00;
data[18] = 0x00;
data[19] = 0x00;
data[20] = 0x00;

// X Base (Fixed x00)
data[21] = 0x00;
// Y Base (Fixed x00)
data[22] = 0x00;

byte[] imagepoints = BinaryUtils.convert(_resolution * 10, 2);

/**
* Specifies the number of image points per unit base for the X axis
* of the image. This value is ten times the resolution of the image
* in the X direction.
*/
data[23] = imagepoints[0];
data[24] = imagepoints[1];

/**
* Specifies the number of image points per unit base for the Y axis
* of the image. This value is ten times the resolution of the image
* in the Y direction.
*/
data[25] = imagepoints[0];
data[26] = imagepoints[1];

/**
* Specifies the extent in the X direction, in image points, of an
* non-celled (simple) image.
*/
data[27] = 0x00;
data[28] = 0x01;

/**
* Specifies the extent in the Y direction, in image points, of an
* non-celled (simple) image.
*/
data[29] = 0x00;
data[30] = 0x01;

// Constant Data
data[31] = 0x00;
data[32] = 0x00;
data[33] = 0x00;
data[34] = 0x00;
data[35] = 0x2D;
data[36] = 0x00;

// Default size of image cell in X direction
data[37] = 0x00;
data[38] = 0x01;

// Default size of image cell in Y direction
data[39] = 0x00;
data[40] = 0x01;

// Constant Data
data[41] = 0x00;
data[42] = 0x01;

// Image Color
data[43] = (byte)0xFF;
data[44] = (byte)0xFF;

os.write(data);

}

/**
* Sets the resolution information for the raster image
* the default value is a resolution of 240 dpi.
* @param resolution The resolution value
*/
public void setResolution(int resolution) {
_resolution = resolution;
}

}

+ 271
- 0
src/sandbox/org/apache/fop/render/afp/modca/ImageObject.java 查看文件

@@ -0,0 +1,271 @@
/*
* Copyright 2006 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.afp.modca;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import org.apache.fop.render.afp.tools.BinaryUtils;

/**
* An IOCA Image Data Object
*/
public class ImageObject extends AbstractNamedAFPObject {

/**
* The object environment group
*/
private ObjectEnvironmentGroup _objectEnvironmentGroup = null;

/**
* The image segment
*/
private ImageSegment _imageSegment = null;

/**
* Constructor for the image object with the specified name,
* the name must be a fixed length of eight characters.
* @param name The name of the image.
*/
public ImageObject(String name) {

super(name);

}

/**
* Sets the image display area position and size.
*
* @param x
* the x position of the image
* @param y
* the y position of the image
* @param w
* the width of the image
* @param h
* the height of the image
* @param r
* the rotation of the image
*/
public void setImageViewport(int x, int y, int w, int h, int r) {
if (_objectEnvironmentGroup == null) {
_objectEnvironmentGroup = new ObjectEnvironmentGroup();
}
_objectEnvironmentGroup.setObjectArea(x, y, w, h, r);
}

/**
* Set the dimensions of the image.
* @param xresol the x resolution of the image
* @param yresol the y resolution of the image
* @param width the image width
* @param height the image height
*/
public void setImageParameters(int xresol, int yresol, int width, int height) {
if (_objectEnvironmentGroup == null) {
_objectEnvironmentGroup = new ObjectEnvironmentGroup();
}
_objectEnvironmentGroup.setImageData(xresol, yresol, width, height);
if (_imageSegment == null) {
_imageSegment = new ImageSegment();
}
_imageSegment.setImageSize(xresol, yresol, width, height);
}

/**
* Sets the image encoding.
* @param encoding The image encoding.
*/
public void setImageEncoding(byte encoding) {
if (_imageSegment == null) {
_imageSegment = new ImageSegment();
}
_imageSegment.setImageEncoding(encoding);
}

/**
* Sets the image compression.
* @param compression The image compression.
*/
public void setImageCompression(byte compression) {
if (_imageSegment == null) {
_imageSegment = new ImageSegment();
}
_imageSegment.setImageCompression(compression);
}

/**
* Sets the image IDE size.
* @param size The IDE size.
*/
public void setImageIDESize(byte size) {
if (_imageSegment == null) {
_imageSegment = new ImageSegment();
}
_imageSegment.setImageIDESize(size);
}

/**
* Sets the image IDE color model.
* @param size The IDE color model.
*/
public void setImageIDEColorModel(byte colorModel) {
if (_imageSegment == null) {
_imageSegment = new ImageSegment();
}
_imageSegment.setImageIDEColorModel(colorModel);
}

/**
* Set the data of the image.
* @param data The image data
*/
public void setImageData(byte data[]) {
if (_imageSegment == null) {
_imageSegment = new ImageSegment();
}
_imageSegment.setImageData(data);
}

/**
* Sets the ObjectEnvironmentGroup.
* @param objectEnvironmentGroup The objectEnvironmentGroup to set
*/
public void setObjectEnvironmentGroup(ObjectEnvironmentGroup objectEnvironmentGroup) {
_objectEnvironmentGroup = objectEnvironmentGroup;
}

/**
* Helper method to return the start of the image object.
* @return byte[] The data stream.
*/
private byte[] getIPDStart(int len) {

byte[] data = new byte[] {

0x5A, // Structured field identifier
0x00, // Length byte 1
0x10, // Length byte 2
(byte) 0xD3, // Structured field id byte 1
(byte) 0xEE, // Structured field id byte 2
(byte) 0xFB, // Structured field id byte 3
0x00, // Flags
0x00, // Reserved
0x00, // Reserved
};

byte[] l = BinaryUtils.convert(len + 8, 2);
data[1] = l[0];
data[2] = l[1];

return data;

}

/**
* Accessor method to write the AFP datastream for the Image Object
* @param os The stream to write to
* @throws java.io.IOException
*/
public void writeDataStream(OutputStream os)
throws IOException {

writeStart(os);

if (_objectEnvironmentGroup != null) {
_objectEnvironmentGroup.writeDataStream(os);
}

if (_imageSegment != null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
_imageSegment.writeDataStream(baos);
byte b[] = baos.toByteArray();
int off = 0;
while (off < b.length) {
int len = Math.min(30000, b.length - off);
os.write(getIPDStart(len));
os.write(b, off, len);
off += len;
}
}

writeEnd(os);

}

/**
* Helper method to write the start of the Image Object.
* @param os The stream to write to
*/
private void writeStart(OutputStream os)
throws IOException {

byte[] data = new byte[17];

data[0] = 0x5A; // Structured field identifier
data[1] = 0x00; // Length byte 1
data[2] = 0x10; // Length byte 2
data[3] = (byte) 0xD3; // Structured field id byte 1
data[4] = (byte) 0xA8; // Structured field id byte 2
data[5] = (byte) 0xFB; // Structured field id byte 3
data[6] = 0x00; // Flags
data[7] = 0x00; // Reserved
data[8] = 0x00; // Reserved

for (int i = 0; i < _nameBytes.length; i++) {

data[9 + i] = _nameBytes[i];

}

os.write(data);

}

/**
* Helper method to write the end of the Image Object.
* @param os The stream to write to
*/
private void writeEnd(OutputStream os)
throws IOException {

byte[] data = new byte[17];

data[0] = 0x5A; // Structured field identifier
data[1] = 0x00; // Length byte 1
data[2] = 0x10; // Length byte 2
data[3] = (byte) 0xD3; // Structured field id byte 1
data[4] = (byte) 0xA9; // Structured field id byte 2
data[5] = (byte) 0xFB; // Structured field id byte 3
data[6] = 0x00; // Flags
data[7] = 0x00; // Reserved
data[8] = 0x00; // Reserved

for (int i = 0; i < _nameBytes.length; i++) {

data[9 + i] = _nameBytes[i];

}

os.write(data);

}

}

+ 207
- 0
src/sandbox/org/apache/fop/render/afp/modca/ImageOutputControl.java 查看文件

@@ -0,0 +1,207 @@
/*
* Copyright 2006 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.afp.modca;

import java.io.IOException;
import java.io.OutputStream;
import org.apache.fop.render.afp.tools.BinaryUtils;

/**
* The IM Image Output Control structured field specifies the position and
* orientation of the IM image object area and the mapping of the image points
* to presentation device pels.
*
*/
public class ImageOutputControl extends AbstractAFPObject {

/**
* The orientation of the image
*/
private int _orientation = 0;

/**
* Specifies the offset, along the X-axis, of the IM image object area
* origin to the origin of the including page
*/
private int _Xcoordinate = 0;

/**
* Specifies the offset, along the Y-axis, of the IM image object area
* origin to the origin of the including page
*/
private int _Ycoordinate = 0;

/**
* Map an image point to a single presentation device pel
*/
private boolean _singlepoint = true;

/**
* Constructor for the ImageOutputControl The x parameter specifies the
* offset, along the X-axis, of the IM image object area origin to the
* origin of the including page and the y parameter specifies the offset
* along the Y-axis. The offset is specified in image points and is resolved
* using the units of measure specified for the image in the IID structured
* field.
*
* @param x
* The X-axis offset.
* @param y
* The Y-axis offset.
*/
public ImageOutputControl(int x, int y) {

_Xcoordinate = x;
_Ycoordinate = y;

}

/**
* Accessor method to write the AFP datastream for the Image Output Control
* @param os The stream to write to
* @throws java.io.IOException
*/
public void writeDataStream(OutputStream os)
throws IOException {

byte[] data = new byte[33];

data[0] = 0x5A;
data[1] = 0x00;
data[2] = 0x20;
data[3] = (byte) 0xD3;
data[4] = (byte) 0xA7;
data[5] = (byte) 0x7B;
data[6] = 0x00;
data[7] = 0x00;
data[8] = 0x00;

// XoaOset
byte[] x1 = BinaryUtils.convert(_Xcoordinate, 3);
data[9] = x1[0];
data[10] = x1[1];
data[11] = x1[2];

// YoaOset
byte[] x2 = BinaryUtils.convert(_Ycoordinate, 3);
data[12] = x2[0];
data[13] = x2[1];
data[14] = x2[2];

switch (_orientation) {
case 0:
// 0 and 90 degrees respectively
data[15] = 0x00;
data[16] = 0x00;
data[17] = 0x2D;
data[18] = 0x00;
break;
case 90:
// 90 and 180 degrees respectively
data[15] = 0x2D;
data[16] = 0x00;
data[17] = 0x5A;
data[18] = 0x00;
break;
case 180:
// 180 and 270 degrees respectively
data[15] = 0x5A;
data[16] = 0x00;
data[17] = (byte) 0x87;
data[18] = 0x00;
break;
case 270:
// 270 and 0 degrees respectively
data[15] = (byte) 0x87;
data[16] = 0x00;
data[17] = 0x00;
data[18] = 0x00;
break;
default:
// 0 and 90 degrees respectively
data[15] = 0x00;
data[16] = 0x00;
data[17] = 0x2D;
data[18] = 0x00;
break;

}

// Constant Data
data[19] = 0x00;
data[20] = 0x00;
data[21] = 0x00;
data[22] = 0x00;
data[23] = 0x00;
data[24] = 0x00;
data[25] = 0x00;
data[26] = 0x00;

if (_singlepoint) {
data[27] = 0x03;
data[28] = (byte) 0xE8;
data[29] = 0x03;
data[30] = (byte) 0xE8;
} else {
data[27] = 0x07;
data[28] = (byte) 0xD0;
data[29] = 0x07;
data[30] = (byte) 0xD0;
}

// Constant Data
data[31] = (byte) 0xFF;
data[32] = (byte) 0xFF;

os.write(data);

}

/**
* Sets the orientation which specifies the amount of clockwise rotation of
* the IM image object area.
*
* @param orientation
* The orientation to set.
*/
public void setOrientation(int orientation) {

if (orientation == 0 || orientation == 90 || orientation == 180
|| orientation == 270) {
_orientation = orientation;
} else {
throw new IllegalArgumentException(
"The orientation must be one of the values 0, 90, 180, 270");
}

}

/**
* Sets the singlepoint, if true map an image point to a single presentation
* device pel in the IM image object area. If false map an image point to
* two presentation device pels in the IM image object area (double-dot)
*
* @param singlepoint
* Use the singlepoint basis when true.
*/
public void setSinglepoint(boolean singlepoint) {
_singlepoint = singlepoint;
}

}

+ 91
- 0
src/sandbox/org/apache/fop/render/afp/modca/ImageRasterData.java 查看文件

@@ -0,0 +1,91 @@
/*
* Copyright 2006 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.afp.modca;

import java.io.IOException;
import java.io.OutputStream;
import org.apache.fop.render.afp.tools.BinaryUtils;

/**
* Contains the image points that define the IM image raster pattern.
*
* A raster pattern is the array of presentation device pels that forms
* the image. The image data is uncompressed. Bits are grouped into
* bytes and are ordered from left to right within each byte. Each bit
* in the image data represents an image point and is mapped to
* presentation device pels as specified in the IOC structured field.
* A bit with value B'1' indicates a significant image point; a bit
* with value B'0' indicates an insignificant image point.
* Image points are recorded from left to right in rows that represents
* scan lines (X direction), and rows representing scan lines are
* recorded from top to bottom (Y direction). When the image is
* presented, all image points in a row are presented before any
* image points in the next sequential row are presented, and all rows
* have the same number of image points. If the total number of image
* points is not a multiple of 8, the last byte of the image data is
* padded to a byte boundary. The padding bits do not represent image
* points and are ignored by presentation devices.
*/
public class ImageRasterData extends AbstractAFPObject {

/**
* The image raster data
*/
private byte[] _rasterdata;

/**
* Constructor for the image raster data object
* @param rasterdata The raster image data
*/
public ImageRasterData(byte[] rasterdata) {

_rasterdata = rasterdata;

}

/**
* Accessor method to write the AFP datastream for the Image Raster Data
* @param os The stream to write to
* @throws java.io.IOException
*/
public void writeDataStream(OutputStream os)
throws IOException {

byte[] data = new byte[9];

data[0] = 0x5A;

// The size of the structured field
byte[] x = BinaryUtils.convert(_rasterdata.length + 8, 2);
data[1] = x[0];
data[2] = x[1];

data[3] = (byte) 0xD3;
data[4] = (byte) 0xEE;
data[5] = (byte) 0x7B;
data[6] = 0x00;
data[7] = 0x00;
data[8] = 0x00;

os.write(data);
os.write(_rasterdata);

}

}

+ 762
- 0
src/sandbox/org/apache/fop/render/afp/modca/ImageRasterPattern.java 查看文件

@@ -0,0 +1,762 @@
/*
* Copyright 2006 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.afp.modca;

/**
* Raster data is a grid of cells covering an area of interest.
* Each pixel, the smallest unit of information in the grid, displays
* a unique attribute. This static class generates raster data for different
* shades of grey (betweeen 0 and 16) the lower the number being the
* darker the shade. The image data dimensions are 64 x 8.
*/
public class ImageRasterPattern {

/**
* The Raster Pattern for Greyscale 16
*/
private static final byte[] GREYSCALE16 = new byte[] {
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
};

/**
* The Raster Pattern for Greyscale 15
*/
private static final byte[] GREYSCALE15 = new byte[] {
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x11,
0x11,
0x11,
0x11,
0x11,
0x11,
0x11,
0x11,
};

/**
* The Raster Pattern for Greyscale 14
*/
private static final byte[] GREYSCALE14 = new byte[] {
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x11,
0x11,
0x11,
0x11,
0x11,
0x11,
0x11,
0x11,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x44,
0x44,
0x44,
0x44,
0x44,
0x44,
0x44,
0x44,
};


/**
* The Raster Pattern for Greyscale 13
*/
private static final byte[] GREYSCALE13 = new byte[] {
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x11,
0x11,
0x11,
0x11,
0x11,
0x11,
0x11,
0x11,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
};

/**
* The Raster Pattern for Greyscale 12
*/
private static final byte[] GREYSCALE12 = new byte[] {
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x55,
0x55,
0x55,
0x55,
0x55,
0x55,
0x55,
0x55,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
};

/**
* The Raster Pattern for Greyscale 11
*/
private static final byte[] GREYSCALE11 = new byte[] {
0x11,
0x11,
0x11,
0x11,
0x11,
0x11,
0x11,
0x11,
0x44,
0x44,
0x44,
0x44,
0x44,
0x44,
0x44,
0x44,
0x11,
0x11,
0x11,
0x11,
0x11,
0x11,
0x11,
0x11,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
};

/**
* The Raster Pattern for Greyscale 10
*/
private static final byte[] GREYSCALE10 = new byte[] {
0x11,
0x11,
0x11,
0x11,
0x11,
0x11,
0x11,
0x11,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
0x44,
0x44,
0x44,
0x44,
0x44,
0x44,
0x44,
0x44,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
};

/**
* The Raster Pattern for Greyscale 9
*/
private static final byte[] GREYSCALE09 = new byte[] {
0x11,
0x11,
0x11,
0x11,
0x11,
0x11,
0x11,
0x11,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
0x55,
0x55,
0x55,
0x55,
0x55,
0x55,
0x55,
0x55,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
};

/**
* The Raster Pattern for Greyscale 8
*/
private static final byte[] GREYSCALE08 = new byte[] {
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
};


/**
* The Raster Pattern for Greyscale 7
*/
private static final byte[] GREYSCALE07 = new byte[] {
0x55,
0x55,
0x55,
0x55,
0x55,
0x55,
0x55,
0x55,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
0x55,
0x55,
0x55,
0x55,
0x55,
0x55,
0x55,
0x55,
(byte)0xBB,
(byte)0xBB,
(byte)0xBB,
(byte)0xBB,
(byte)0xBB,
(byte)0xBB,
(byte)0xBB,
(byte)0xBB,
};


/**
* The Raster Pattern for Greyscale 6
*/
private static final byte[] GREYSCALE06 = new byte[] {
0x55,
0x55,
0x55,
0x55,
0x55,
0x55,
0x55,
0x55,
(byte)0xBB,
(byte)0xBB,
(byte)0xBB,
(byte)0xBB,
(byte)0xBB,
(byte)0xBB,
(byte)0xBB,
(byte)0xBB,
0x55,
0x55,
0x55,
0x55,
0x55,
0x55,
0x55,
0x55,
(byte)0xEE,
(byte)0xEE,
(byte)0xEE,
(byte)0xEE,
(byte)0xEE,
(byte)0xEE,
(byte)0xEE,
(byte)0xEE,
};

/**
* The Raster Pattern for Greyscale 5
*/
private static final byte[] GREYSCALE05 = new byte[] {
0x55,
0x55,
0x55,
0x55,
0x55,
0x55,
0x55,
0x55,
(byte)0xBB,
(byte)0xBB,
(byte)0xBB,
(byte)0xBB,
(byte)0xBB,
(byte)0xBB,
(byte)0xBB,
(byte)0xBB,
(byte)0xEE,
(byte)0xEE,
(byte)0xEE,
(byte)0xEE,
(byte)0xEE,
(byte)0xEE,
(byte)0xEE,
(byte)0xEE,
(byte)0xBB,
(byte)0xBB,
(byte)0xBB,
(byte)0xBB,
(byte)0xBB,
(byte)0xBB,
(byte)0xBB,
(byte)0xBB,
};


/**
* The Raster Pattern for Greyscale 4
*/
private static final byte[] GREYSCALE04 = new byte[] {
0x55,
0x55,
0x55,
0x55,
0x55,
0x55,
0x55,
0x55,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xAA,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
};

/**
* The Raster Pattern for Greyscale 3
*/
private static final byte[] GREYSCALE03 = new byte[] {
0x55,
0x55,
0x55,
0x55,
0x55,
0x55,
0x55,
0x55,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xBB,
(byte)0xBB,
(byte)0xBB,
(byte)0xBB,
(byte)0xBB,
(byte)0xBB,
(byte)0xBB,
(byte)0xBB,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
};

/**
* The Raster Pattern for Greyscale 2
*/
private static final byte[] GREYSCALE02 = new byte[] {
0x77,
0x77,
0x77,
0x77,
0x77,
0x77,
0x77,
0x77,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xDD,
(byte)0xDD,
(byte)0xDD,
(byte)0xDD,
(byte)0xDD,
(byte)0xDD,
(byte)0xDD,
(byte)0xDD,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
};


/**
* The Raster Pattern for Greyscale 1
*/
private static final byte[] GREYSCALE01 = new byte[] {
0x77,
0x77,
0x77,
0x77,
0x77,
0x77,
0x77,
0x77,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
};


/**
* The Raster Pattern for Greyscale 00
*/
private static final byte[] GREYSCALE00 = new byte[] {
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
(byte)0xFF,
};

/**
* Static method to return the raster image data for the
* grey scale specified. The scale should be between 0 (darkest)
* and 16 (lightest).
* @param greyscale The grey scale value (0 - 16)
*/
public static byte[] getRasterData(int greyscale) {

int repeat = 16;

byte[] greypattern = new byte[32];
byte[] rasterdata = new byte[32 * repeat];

switch (greyscale) {
case 0:
System.arraycopy(GREYSCALE00, 0, greypattern, 0, 32);
break;
case 1:
System.arraycopy(GREYSCALE01, 0, greypattern, 0, 32);
break;
case 2:
System.arraycopy(GREYSCALE02, 0, greypattern, 0, 32);
break;
case 3:
System.arraycopy(GREYSCALE03, 0, greypattern, 0, 32);
break;
case 4:
System.arraycopy(GREYSCALE04, 0, greypattern, 0, 32);
break;
case 5:
System.arraycopy(GREYSCALE05, 0, greypattern, 0, 32);
break;
case 6:
System.arraycopy(GREYSCALE06, 0, greypattern, 0, 32);
break;
case 7:
System.arraycopy(GREYSCALE07, 0, greypattern, 0, 32);
break;
case 8:
System.arraycopy(GREYSCALE08, 0, greypattern, 0, 32);
break;
case 9:
System.arraycopy(GREYSCALE09, 0, greypattern, 0, 32);
break;
case 10:
System.arraycopy(GREYSCALE10, 0, greypattern, 0, 32);
break;
case 11:
System.arraycopy(GREYSCALE11, 0, greypattern, 0, 32);
break;
case 12:
System.arraycopy(GREYSCALE12, 0, greypattern, 0, 32);
break;
case 13:
System.arraycopy(GREYSCALE13, 0, greypattern, 0, 32);
break;
case 14:
System.arraycopy(GREYSCALE14, 0, greypattern, 0, 32);
break;
case 15:
System.arraycopy(GREYSCALE15, 0, greypattern, 0, 32);
break;
case 16:
System.arraycopy(GREYSCALE16, 0, greypattern, 0, 32);
break;
default :
System.arraycopy(GREYSCALE00, 0, greypattern, 0, 32);
break;
}

for(int i = 0; i < repeat; i++) {

System.arraycopy(greypattern, 0, rasterdata, i * 32, 32);

}

return rasterdata;

}

}

+ 225
- 0
src/sandbox/org/apache/fop/render/afp/modca/ImageSegment.java 查看文件

@@ -0,0 +1,225 @@
/*
* Copyright 2006 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.afp.modca;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;

/**
* An Image Segment is represented by a set of self-defining fields, fields
* that describe their own contents. It starts with a Begin Segment, and
* ends with an End Segment.
*
* Between the Begin Segment and End Segment is the image information to
* be processed, called the Image Content.
*
* Only one Image Content can exist within a single IOCA Image Segment.
*/
public class ImageSegment extends AbstractAFPObject {

/**
* Default name for the object environment group
*/
private static final String DEFAULT_NAME = "IS01";

/**
* The name of the image segment
*/
private String _name;

/**
* The name of the image segment as EBCIDIC bytes
*/
private byte[] _nameBytes;

/**
* The ImageContent for the image segment
*/
private ImageContent _imageContent = null;

/**
* Default constructor for the ImageSegment.
*/
public ImageSegment() {

this(DEFAULT_NAME);

}

/**
* Constructor for the image segment with the specified name,
* the name must be a fixed length of eight characters.
* @param name The name of the image.
*/
public ImageSegment(String name) {

if (name.length() != 4) {
String msg = "Image segment name must be 4 characters long " + name;
log.error("Constructor:: " + msg);
throw new IllegalArgumentException(msg);
}

_name = name;

try {

_nameBytes = name.getBytes(AFPConstants.EBCIDIC_ENCODING);

} catch (UnsupportedEncodingException usee) {

_nameBytes = name.getBytes();
log.warn(
"Constructor:: UnsupportedEncodingException translating the name "
+ name);

}

}

/**
* Sets the image size parameters
* resolution, hsize and vsize.
* @param hresol The horizontal resolution of the image.
* @param vresol The vertical resolution of the image.
* @param hsize The horizontal size of the image.
* @param vsize The vertival size of the image.
*/
public void setImageSize(int hresol, int vresol, int hsize, int vsize) {
if (_imageContent == null) {
_imageContent = new ImageContent();
}
_imageContent.setImageSize(hresol, vresol, hsize, vsize);
}

/**
* Sets the image encoding.
* @param encoding The image encoding.
*/
public void setImageEncoding(byte encoding) {
if (_imageContent == null) {
_imageContent = new ImageContent();
}
_imageContent.setImageEncoding(encoding);
}

/**
* Sets the image compression.
* @param compression The image compression.
*/
public void setImageCompression(byte compression) {
if (_imageContent == null) {
_imageContent = new ImageContent();
}
_imageContent.setImageCompression(compression);
}

/**
* Sets the image IDE size.
* @param size The IDE size.
*/
public void setImageIDESize(byte size) {
if (_imageContent == null) {
_imageContent = new ImageContent();
}
_imageContent.setImageIDESize(size);
}

/**
* Sets the image IDE color model.
* @param size The IDE color model.
*/
public void setImageIDEColorModel(byte colorModel) {
if (_imageContent == null) {
_imageContent = new ImageContent();
}
_imageContent.setImageIDEColorModel(colorModel);
}

/**
* Set the data of the image.
* @param data the image data
*/
public void setImageData(byte data[]) {
if (_imageContent == null) {
_imageContent = new ImageContent();
}
_imageContent.setImageData(data);
}

/**
* Accessor method to write the AFP datastream for the Image Segment
* @param os The stream to write to
* @throws java.io.IOException
*/
public void writeDataStream(OutputStream os)
throws IOException {

writeStart(os);

if (_imageContent != null) {
_imageContent.writeDataStream(os);
}

writeEnd(os);

}

/**
* Helper method to write the start of the Image Segment.
* @param os The stream to write to
*/
private void writeStart(OutputStream os)
throws IOException {

byte[] data = new byte[] {
0x70, // ID
0x04, // Length
0x00, // Name byte 1
0x00, // Name byte 2
0x00, // Name byte 3
0x00, // Name byte 4
};

for (int i = 0; i < _nameBytes.length; i++) {

data[2 + i] = _nameBytes[i];

}

os.write(data);

}

/**
* Helper method to write the end of the Image Segment.
* @param os The stream to write to
*/
private void writeEnd(OutputStream os)
throws IOException {

byte[] data = new byte[] {
0x71, // ID
0x00, // Length
};

os.write(data);

}

}

+ 94
- 0
src/sandbox/org/apache/fop/render/afp/modca/ImageSizeParameter.java 查看文件

@@ -0,0 +1,94 @@
/*
* Copyright 2006 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.afp.modca;

import java.io.IOException;
import java.io.OutputStream;
import org.apache.fop.render.afp.tools.BinaryUtils;

/**
* Describes the measurement characteristics of the image when it is created.
*/
public class ImageSizeParameter extends AbstractAFPObject {

private int _hresol = 0;
private int _vresol = 0;
private int _hsize = 0;
private int _vsize = 0;

/**
* Constructor for a ImageSizeParameter for the specified
* resolution, hsize and vsize.
* @param hresol The horizontal resolution of the image.
* @param vresol The vertical resolution of the image.
* @param hsize The hsize of the image.
* @param vsize The vsize of the vsize.
*/
public ImageSizeParameter(int hresol, int vresol, int hsize, int vsize) {

_hresol = hresol;
_vresol = vresol;
_hsize = hsize;
_vsize = vsize;

}

/**
* Accessor method to write the AFP datastream for the Image Size Parameter
* @param os The stream to write to
* @throws java.io.IOException
*/
public void writeDataStream(OutputStream os)
throws IOException {

byte[] data = new byte[] {
(byte)0x94, // ID = Image Size Parameter
0x09, // Length
0x00, // Unit base - 10 Inches
0x00, // HRESOL
0x00, //
0x00, // VRESOL
0x00, //
0x00, // HSIZE
0x00, //
0x00, // VSIZE
0x00, //
};

byte[] x = BinaryUtils.convert(_hresol, 2);
data[3] = x[0];
data[4] = x[1];

byte[] y = BinaryUtils.convert(_vresol, 2);
data[5] = y[0];
data[6] = y[1];

byte[] w = BinaryUtils.convert(_hsize, 2);
data[7] = w[0];
data[8] = w[1];

byte[] h = BinaryUtils.convert(_vsize, 2);
data[9] = h[0];
data[10] = h[1];

os.write(data);

}

}

+ 171
- 0
src/sandbox/org/apache/fop/render/afp/modca/IncludeObject.java 查看文件

@@ -0,0 +1,171 @@
/*
* Copyright 2006 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.afp.modca;

import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;

import org.apache.fop.render.afp.tools.BinaryUtils;

/**
* An Include Object structured field references an object on a page or overlay.
* It optionally contains parameters that identify the object and that specify
* presentation parameters such as object position, size, orientation, mapping,
* and default color.
* <p>
* Where the presentation parameters conflict with parameters specified in the
* object's environment group (OEG), the parameters in the Include Object
* structured field override. If the referenced object is a page segment, the
* IOB parameters override the corresponding environment group parameters on all
* data objects in the page segment.
* </p>
*/
public class IncludeObject extends AbstractNamedAFPObject {

/**
* The object type
*/
private byte _objectType = (byte) 0x92;

/**
* The orientation on the include object
*/
private int _orientation = 0;

/**
* Constructor for the include object with the specified name, the name must
* be a fixed length of eight characters and is the name of the referenced
* object.
*
* @param name
* the name of the image
*/
public IncludeObject(String name) {

super(name);
_objectType = (byte) 0xFB;

}

/**
* Sets the orienation to use for the Include Object.
*
* @param orientation
* The orientation (0,90, 180, 270)
*/
public void setOrientation(int orientation) {

if (orientation == 0 || orientation == 90 || orientation == 180
|| orientation == 270) {
_orientation = orientation;
} else {
throw new IllegalArgumentException(
"The orientation must be one of the values 0, 90, 180, 270");
}

}

/**
* Accessor method to write the AFP datastream for the Include Object
* @param os The stream to write to
* @throws java.io.IOException
*/
public void writeDataStream(OutputStream os)
throws IOException {

byte[] data = new byte[37];

data[0] = 0x5A;

// Set the total record length
byte[] rl1 = BinaryUtils.convert(36, 2); //Ignore first byte
data[1] = rl1[0];
data[2] = rl1[1];

// Structured field ID for a IOB
data[3] = (byte) 0xD3;
data[4] = (byte) 0xAF;
data[5] = (byte) 0xC3;

data[6] = 0x00; // Reserved
data[7] = 0x00; // Reserved
data[8] = 0x00; // Reserved

for (int i = 0; i < _nameBytes.length; i++) {
data[9 + i] = _nameBytes[i];
}

data[17] = 0x00;
data[18] = _objectType;

// XoaOset
data[20] = (byte) 0xFF;
data[21] = (byte) 0xFF;
data[22] = (byte) 0xFF;

// YoaOset
data[23] = (byte) 0xFF;
data[24] = (byte) 0xFF;
data[25] = (byte) 0xFF;

switch (_orientation) {
case 90:
data[26] = 0x2D;
data[27] = 0x00;
data[28] = 0x5A;
data[29] = 0x00;
break;
case 180:
data[26] = 0x5A;
data[27] = 0x00;
data[28] = (byte) 0x87;
data[29] = 0x00;
break;
case 270:
data[26] = (byte) 0x87;
data[27] = 0x00;
data[28] = 0x00;
data[29] = 0x00;
break;
default:
data[26] = 0x00;
data[27] = 0x00;
data[28] = 0x2D;
data[29] = 0x00;
break;
}

// XocaOset
data[30] = (byte) 0xFF;
data[31] = (byte) 0xFF;
data[32] = (byte) 0xFF;

// YocaOset
data[33] = (byte) 0xFF;
data[34] = (byte) 0xFF;
data[35] = (byte) 0xFF;

data[36] = 0x01;

os.write(data);

}

}

+ 156
- 0
src/sandbox/org/apache/fop/render/afp/modca/IncludePageOverlay.java 查看文件

@@ -0,0 +1,156 @@
/*
* Copyright 2006 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.afp.modca;

import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;

import org.apache.fop.render.afp.tools.BinaryUtils;

/**
*
* The Include Page Overlay structured field references an overlay resource
* definition that is to be positioned on the page. A page overlay can be
* referenced at any time during the page state, but not during an object state.
* The overlay contains its own active environment group definition.
*
* Note: There is no need for the triplets, so I have ignored them.
*
* A real example of where this will be used is for static overlays, such as an
* address on the page.
*
*/
public class IncludePageOverlay extends AbstractNamedAFPObject {

/**
* The x coordinate
*/
private int _xCoor = 0;

/**
* The y coordinate
*/
private int _yCoor = 0;

/**
* The orientation
*/
private int _orientation = 0;

/**
* Constructor for the Include Page Overlay
* @param overlayName Name of the page segment
* @param x The x position
* @param y The y position
* @param orientation The orientation
*/
public IncludePageOverlay(String overlayName, int x, int y, int orientation) {

super(overlayName);

_xCoor = x;
_yCoor = y;
setOrientation(orientation);
}

/**
* Sets the orienation to use for the overlay.
*
* @param orientation
* The orientation (0,90, 180, 270)
*/
public void setOrientation(int orientation) {

if (orientation == 0 || orientation == 90 || orientation == 180
|| orientation == 270) {
_orientation = orientation;
} else {
throw new IllegalArgumentException(
"The orientation must be one of the values 0, 90, 180, 270");
}

}

/**
* Accessor method to write the AFP datastream for the Include Page Overlay
* @param os The stream to write to
* @throws java.io.IOException
*/
public void writeDataStream(OutputStream os)
throws IOException {

byte[] data = new byte[25]; //(9 +16)

data[0] = 0x5A;

// Set the total record length
byte[] rl1 = BinaryUtils.convert(24, 2); //Ignore first byte
data[1] = rl1[0];
data[2] = rl1[1];

// Structured field ID for a IPO
data[3] = (byte) 0xD3;
data[4] = (byte) 0xAF;
data[5] = (byte) 0xD8;

data[6] = 0x00; // Reserved
data[7] = 0x00; // Reserved
data[8] = 0x00; // Reserved

for (int i = 0; i < _nameBytes.length; i++) {

data[9 + i] = _nameBytes[i];

}

byte[] r2 = BinaryUtils.convert(_xCoor, 3);
data[17] = r2[0]; // x coordinate
data[18] = r2[1];
data[19] = r2[2];

byte[] r3 = BinaryUtils.convert(_yCoor, 3);
data[20] = r3[0]; // y coordinate
data[21] = r3[1];
data[22] = r3[2];

switch (_orientation) {
case 90:
data[23] = 0x2D;
data[24] = 0x00;
break;
case 180:
data[23] = 0x5A;
data[24] = 0x00;
break;
case 270:
data[23] = (byte) 0x87;
data[24] = 0x00;
break;
default:
data[23] = 0x00;
data[24] = 0x00;
break;
}

os.write(data);

}

}

+ 114
- 0
src/sandbox/org/apache/fop/render/afp/modca/IncludePageSegment.java 查看文件

@@ -0,0 +1,114 @@
/*
* Copyright 2006 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.afp.modca;

import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;

import org.apache.fop.render.afp.tools.BinaryUtils;

/**
* The Include Page Segment structured field references a page segment resource
* object that is to be presented on the page or overlay presentation space. The IPS
* specifies a reference point on the including page or overlay coordinate system that
* may be used to position objects contained in the page segment. A page segment
* can be referenced at any time during page or overlay state, but not during an
* object state. The page segment inherits the active environment group definition of
* the including page or overlay.
*
* Note : No use for Triplets.
*
* A 'real' example for where this will be used is for
* the dynamic placing of overlay objects, such as signatures
* that may have to be placed at different positions on a document.
*
*/
public class IncludePageSegment extends AbstractNamedAFPObject{

/**
* The x position where we need to put this object on the page
*/
private byte [] _xCoor;

/**
* The y position where we need to put this object on the page
*/
private byte [] _yCoor;

/**
* Constructor for the Include Page Segment
* @param name Name of the page segment
* @param xVal The x position
* @param yVal The y position
*/
public IncludePageSegment(String name, int xVal, int yVal){

super(name);
_xCoor = BinaryUtils.convert(xVal, 3);
_yCoor = BinaryUtils.convert(yVal, 3);

}

/**
* Accessor method to write the AFP datastream for the Include Page Segment
* @param os The stream to write to
* @throws java.io.IOException
*/
public void writeDataStream(OutputStream os)
throws IOException {

byte[] data = new byte[23]; //(9 +14)

data[0] = 0x5A;

// Set the total record length
byte[] rl1 = BinaryUtils.convert(22, 2); //Ignore first byte
data[1] = rl1[0];
data[2] = rl1[1];

// Structured field ID for a IPS
data[3] = (byte) 0xD3;
data[4] = (byte) 0xAF;
data[5] = (byte) 0x5F;

data[6] = 0x00; // Reserved
data[7] = 0x00; // Reserved
data[8] = 0x00; // Reserved

for (int i = 0; i < _nameBytes.length; i++) {

data[9 + i] = _nameBytes[i];

}

data[17] = _xCoor[0]; // x coordinate
data[18] = _xCoor[1];
data[19] = _xCoor[2];

data[20] = _yCoor[0]; // y coordinate
data[21] = _yCoor[1];
data[22] = _yCoor[2];

os.write(data);

}


}

+ 81
- 0
src/sandbox/org/apache/fop/render/afp/modca/InvokeMediumMap.java 查看文件

@@ -0,0 +1,81 @@
/*
* Copyright 2006 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.afp.modca;

import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;

import org.apache.fop.render.afp.tools.BinaryUtils;

/**
* The Invoke Medium Map structured field identifies the Medium Map that is to
* become active for the document. An Invoke Medium Map structured field affects
* the document's current environment. The Medium Map's effect on current environment
* parameter values lasts until a new Medium Map is invoked.
*/
public class InvokeMediumMap extends AbstractNamedAFPObject {

/**
* Constructor for the Invoke Medium Map
* @param mediumMapName Name of the medium map
*/
public InvokeMediumMap(String mediumMapName) {

super(mediumMapName);

}

/**
* Accessor method to write the AFP datastream for the Invoke Medium Map
* @param os The stream to write to
* @throws java.io.IOException
*/
public void writeDataStream(OutputStream os)
throws IOException {

byte[] data = new byte[17];

data[0] = 0x5A;

// Set the total record length
byte[] rl1 = BinaryUtils.convert(16, 2); //Ignore first byte
data[1] = rl1[0];
data[2] = rl1[1];

// Structured field ID for a IPO
data[3] = (byte) 0xD3;
data[4] = (byte) 0xAB;
data[5] = (byte) 0xCC;

data[6] = 0x00; // Reserved
data[7] = 0x00; // Reserved
data[8] = 0x00; // Reserved

for (int i = 0; i < _nameBytes.length; i++) {

data[9 + i] = _nameBytes[i];

}

os.write(data);

}

}

+ 298
- 0
src/sandbox/org/apache/fop/render/afp/modca/MapCodedFont.java 查看文件

@@ -0,0 +1,298 @@
/*
* Copyright 2006 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.afp.modca;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;

import org.apache.fop.render.afp.exceptions.FontRuntimeException;
import org.apache.fop.render.afp.fonts.AFPFont;
import org.apache.fop.render.afp.fonts.CharacterSet;
import org.apache.fop.render.afp.fonts.OutlineFont;
import org.apache.fop.render.afp.fonts.RasterFont;
import org.apache.fop.render.afp.tools.BinaryUtils;

/**
* The Map Coded Font structured field maps a unique coded font resource local
* ID, which may be embedded one or more times within an object's data and
* descriptor, to the identifier of a coded font resource object. Additionally,
* the Map Coded Font structured field specifies a set of resource attributes
* for the coded font.
*
* @author <a href="mailto:pete@townsend.uk.com">Pete Townsend </a>
*/
public class MapCodedFont extends AbstractAFPObject {

/**
* The collection of map coded fonts (maximum of 254)
*/
private ArrayList _fontlist = null;

/**
* Constructor for the MapCodedFont
*/
public MapCodedFont() {

_fontlist = new ArrayList();

}

/**
* Accessor method to write the AFP datastream for the Map Coded Font
* @param os The stream to write to
* @throws java.io.IOException
*/
public void writeDataStream(OutputStream os)
throws IOException {


ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.write(0x5A);
baos.write(new byte[] { 0x00, 0x00 });

// Field identifier for a MapCodedFont
baos.write(new byte[] { (byte) 0xD3, (byte) 0xAB, (byte) 0x8A });

// Reserved
baos.write(new byte[] { 0x00, 0x00, 0x00 });

for (int i = 0; i < _fontlist.size(); i++) {

FontDefinition fd = (FontDefinition) _fontlist.get(i);

// Start of repeating groups (occurs 1 to 254)
baos.write(0x00);

if (fd._scale == 0) {
// Raster Font
baos.write(0x22); // Length of 34
} else {
// Outline Font
baos.write(0x3A); // Length of 58
}

// Font Character Set Name Reference
baos.write(0x0C);
baos.write(0x02);
baos.write((byte) 0x86);
baos.write(0x00);
baos.write(fd._characterset);

// Font Code Page Name Reference
baos.write(0x0C);
baos.write(0x02);
baos.write((byte) 0x85);
baos.write(0x00);
baos.write(fd._codepage);

// Character Rotation
baos.write(0x04);
baos.write(0x26);
baos.write(fd._orientation);
baos.write(0x00);

// Resource Local Identifier
baos.write(0x04);
baos.write(0x24);
baos.write(0x05);
baos.write(fd._fontReferenceKey);

if (fd._scale != 0) {
// Outline Font (triplet '1F')
baos.write(0x14);
baos.write(0x1F);
baos.write(0x00);
baos.write(0x00);

baos.write(BinaryUtils.convert(fd._scale, 2)); // Height
baos.write(new byte[] { 0x00, 0x00 }); // Width

baos.write(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00 });

baos.write(0x60);

// Outline Font (triplet '5D')
baos.write(0x04);
baos.write(0x5D);
baos.write(BinaryUtils.convert(fd._scale, 2));
}

}

byte[] data = baos.toByteArray();

// Set the total record length
byte[] rl1 = BinaryUtils.convert(data.length - 1, 2);
data[1] = rl1[0];
data[2] = rl1[1];

os.write(data);

}

/**
* Add a font definition on the the map coded font object.
*
* @param fontReference
* the font number used as the resource identifier
* @param font
* the font
* @param size
* the size of the font
* @param orientation
* the orientation of the font
*/
public void addFont(byte fontReference, AFPFont font, int size, int orientation)
throws MaximumSizeExceededException {

FontDefinition fd = new FontDefinition();

fd._fontReferenceKey = fontReference;

switch (orientation) {
case 90:
fd._orientation = 0x2D;
break;
case 180:
fd._orientation = 0x5A;
break;
case 270:
fd._orientation = (byte) 0x87;
break;
default:
fd._orientation = 0x00;
break;
}

try {

if (font instanceof RasterFont) {

RasterFont raster = (RasterFont) font;
CharacterSet cs = raster.getCharacterSet(size);
if (cs == null) {
String msg = "Character set not found for font "
+ font.getFontName() + " with point size " + size;
log.error(msg);
throw new FontRuntimeException(msg);
}

fd._characterset = cs.getNameBytes();

if (fd._characterset.length != 8) {
throw new IllegalArgumentException("The character set "
+ new String(fd._characterset,
AFPConstants.EBCIDIC_ENCODING)
+ " must have a fixed length of 8 characters.");
}

fd._codepage = cs.getCodePage().getBytes(
AFPConstants.EBCIDIC_ENCODING);

if (fd._codepage.length != 8) {
throw new IllegalArgumentException("The code page "
+ new String(fd._codepage,
AFPConstants.EBCIDIC_ENCODING)
+ " must have a fixed length of 8 characters.");
}

} else if (font instanceof OutlineFont) {

OutlineFont outline = (OutlineFont) font;
CharacterSet cs = outline.getCharacterSet();
fd._characterset = cs.getNameBytes();

// There are approximately 72 points to 1 inch or 20 1440ths per point.

fd._scale = ((size / 1000) * 20);

fd._codepage = cs.getCodePage().getBytes(
AFPConstants.EBCIDIC_ENCODING);

if (fd._codepage.length != 8) {
throw new IllegalArgumentException("The code page "
+ new String(fd._codepage,
AFPConstants.EBCIDIC_ENCODING)
+ " must have a fixed length of 8 characters.");
}

} else {
String msg = "Font of type " + font.getClass().getName()
+ " not recognized.";
log.error(msg);
throw new FontRuntimeException(msg);
}

if (_fontlist.size() > 253) {

// Throw an exception if the size is exceeded
throw new MaximumSizeExceededException();

} else {

_fontlist.add(fd);

}

} catch (UnsupportedEncodingException ex) {

throw new FontRuntimeException("Failed to create font "
+ " due to a UnsupportedEncodingException", ex);

}

}

/**
* Private utility class used as a container for font attributes
*/
private class FontDefinition {

/**
* The code page of the font
*/
private byte[] _codepage;

/**
* The character set of the font
*/
private byte[] _characterset;

/**
* The font reference key
*/
private byte _fontReferenceKey;

/**
* The orientation of the font
*/
private byte _orientation;

/**
* The scale (only specified for outline fonts)
*/
private int _scale = 0;

}

}

+ 157
- 0
src/sandbox/org/apache/fop/render/afp/modca/MapPageOverlay.java 查看文件

@@ -0,0 +1,157 @@
/*
* Copyright 2006 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.afp.modca;

import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;

import org.apache.fop.render.afp.tools.BinaryUtils;

/**
* The Map Page Overlay structured field maps a Resource Local ID to the name of
* a Begin Overlay structured field. A Map Page Overlay structured field may
* contain from one to 254 repeating groups.
*
*/
public class MapPageOverlay extends AbstractAFPObject {

/**
* The collection of overlays (maximum of 254 stored as byte[])
*/
private ArrayList _overLays = new ArrayList();

/**
* Constructor for the Map Page Overlay
*/
public MapPageOverlay() {

}

/**
* Add an overlay to to the map page overlay object.
*
* @param name
* The name of the overlay.
*/
public void addOverlay(String name) throws MaximumSizeExceededException {

if (_overLays.size() > 253) {
throw new MaximumSizeExceededException();
}

if (name.length() != 8) {
throw new IllegalArgumentException("The name of overlay " + name
+ " must be 8 characters");
}

if (log.isDebugEnabled()) {
log.debug("addOverlay():: adding overlay " + name);
}

byte[] data;

try {

data = name.getBytes(AFPConstants.EBCIDIC_ENCODING);
_overLays.add(data);

} catch (UnsupportedEncodingException usee) {

log
.error("addOverlay():: UnsupportedEncodingException translating the name "
+ name);

}

}

/**
* Accessor method to write the AFP datastream for the Map Page Overlay
* @param os The stream to write to
* @throws java.io.IOException
*/
public void writeDataStream(OutputStream os)
throws IOException {


int oLayCount = _overLays.size();
int recordlength = oLayCount * 18;

byte[] data = new byte[recordlength + 9];

data[0] = 0x5A;

// Set the total record length
byte[] rl1 = BinaryUtils.convert(recordlength + 8, 2); //Ignore the
// first byte in
// the length
data[1] = rl1[0];
data[2] = rl1[1];

// Structured field ID for a MPO
data[3] = (byte) 0xD3;
data[4] = (byte) 0xAB;
data[5] = (byte) 0xD8;

data[6] = 0x00; // Reserved
data[7] = 0x00; // Reserved
data[8] = 0x00; // Reserved

int pos = 8;

//For each overlay
byte olayref = 0x00;

for (int i = 0; i < oLayCount; i++) {

olayref = (byte) (olayref + 1);

data[++pos] = 0x00;
data[++pos] = 0x12; //the length of repeating group

data[++pos] = 0x0C; //Fully Qualified Name
data[++pos] = 0x02;
data[++pos] = (byte) 0x84;
data[++pos] = 0x00;

//now add the name
byte[] name = (byte[]) _overLays.get(i);

for (int j = 0; j < name.length; j++) {

data[++pos] = name[j];

}

data[++pos] = 0x04; //Resource Local Identifier (RLI)
data[++pos] = 0x24;
data[++pos] = 0x02;

//now add the unique id to the RLI
data[++pos] = olayref;

}

os.write(data);

}

}

+ 31
- 0
src/sandbox/org/apache/fop/render/afp/modca/MaximumSizeExceededException.java 查看文件

@@ -0,0 +1,31 @@
/*
* Copyright 2006 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.afp.modca;

/**
* An exception to handle maximum sizes being exceeded.
*
*/
public class MaximumSizeExceededException extends Exception {

public MaximumSizeExceededException() {
super();
}

}

+ 106
- 0
src/sandbox/org/apache/fop/render/afp/modca/ObjectAreaDescriptor.java 查看文件

@@ -0,0 +1,106 @@
/*
* Copyright 2006 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.afp.modca;

import java.io.IOException;
import java.io.OutputStream;
import org.apache.fop.render.afp.tools.BinaryUtils;

/**
* The Object Area Descriptor structured field specifies the size and attributes
* of an object area presentation space.
*
*/
public class ObjectAreaDescriptor extends AbstractAFPObject {

private int _width = 0;
private int _height = 0;

/**
* Construct an object area descriptor for the specified object width
* and object height.
* @param width The page width.
* @param height The page height.
*/
public ObjectAreaDescriptor(int width, int height) {

_width = width;
_height = height;

}

/**
* Accessor method to write the AFP datastream for the Object Area Descriptor
* @param os The stream to write to
* @throws java.io.IOException
*/
public void writeDataStream(OutputStream os)
throws IOException {

byte[] data = new byte[] {
0x5A,
0x00, // Length
0x1C, // Length
(byte) 0xD3,
(byte) 0xA6,
(byte) 0x6B,
0x00, // Flags
0x00, // Reserved
0x00, // Reserved
0x03, // Triplet length
0x43, // tid = Descriptor Position Triplet
0x01, // DesPosId = 1
0x08, // Triplet length
0x4B, // tid = Measurement Units Triplet
0x00, // XaoBase = 10 inches
0x00, // YaoBase = 10 inches
0x09, // XaoUnits = 2400
0x60, // XaoUnits =
0x09, // YaoUnits = 2400
0x60, // YaoUnits =
0x09, // Triplet length
0x4C, // tid = Object Area Size
0x02, // Size Type
0x00, // XoaSize
0x00,
0x00,
0x00, // YoaSize
0x00,
0x00,
};

byte[] l = BinaryUtils.convert(data.length - 1, 2);
data[1] = l[0];
data[2] = l[1];

byte[] x = BinaryUtils.convert(_width, 3);
data[23] = x[0];
data[24] = x[1];
data[25] = x[2];

byte[] y = BinaryUtils.convert(_height, 3);
data[26] = y[0];
data[27] = y[1];
data[28] = y[2];

os.write(data);

}

}

+ 111
- 0
src/sandbox/org/apache/fop/render/afp/modca/ObjectAreaPosition.java 查看文件

@@ -0,0 +1,111 @@
/*
* Copyright 2006 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.afp.modca;

import java.io.IOException;
import java.io.OutputStream;
import org.apache.fop.render.afp.tools.BinaryUtils;

/**
* The Object Area Position structured field specifies the origin and
* orientation of the object area, and the origin and orientation of the
* object content within the object area.
*/
public class ObjectAreaPosition extends AbstractAFPObject {

private int _x = 0;
private int _y = 0;
private int _rot = 0;

/**
* Construct an object area position for the specified object y, y position.
* @param x The x coordinate.
* @param y The y coordinate.
* @param rotation The coordinate system rotation (must be 0, 90, 180, 270).
*/
public ObjectAreaPosition(int x, int y, int rotation) {

_x = x;
_y = y;
_rot = rotation;
}

/**
* Accessor method to write the AFP datastream for the Object Area Position
* @param os The stream to write to
* @throws java.io.IOException
*/
public void writeDataStream(OutputStream os)
throws IOException {

byte[] data = new byte[] {
0x5A,
0x00, // Length
0x20, // Length
(byte) 0xD3,
(byte) 0xAC,
(byte) 0x6B,
0x00, // Flags
0x00, // Reserved
0x00, // Reserved
0x01, // OAPosID = 1
0x17, // RGLength = 23
0x00, // XoaOSet
0x00,
0x00,
0x00, // YoaOSet
0x00,
0x00,
(byte)(_rot / 2), // XoaOrent
0x00,
(byte)(_rot / 2 + 45), // YoaOrent
0x00,
0x00, // Reserved
0x00, // XocaOSet
0x00,
0x00,
0x00, // YocaOSet
0x00,
0x00,
0x00, // XocaOrent
0x00,
0x2D, // YocaOrent
0x00,
0x01, // RefCSys
};

byte[] l = BinaryUtils.convert(data.length - 1, 2);
data[1] = l[0];
data[2] = l[1];

byte[] x = BinaryUtils.convert(_x, 3);
data[11] = x[0];
data[12] = x[1];
data[13] = x[2];

byte[] y = BinaryUtils.convert(_y, 3);
data[14] = y[0];
data[15] = y[1];
data[16] = y[2];

os.write(data);

}

}

+ 194
- 0
src/sandbox/org/apache/fop/render/afp/modca/ObjectEnvironmentGroup.java 查看文件

@@ -0,0 +1,194 @@
/*
* Copyright 2006 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.afp.modca;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;


/**
* An Object Environment Group (OEG) may be associated with an object and is contained
* within the object's begin-end envelope.
* The object environment group defines the object's origin and orientation on the page,
* and can contain font and color attribute table information. The scope of an object
* environment group is the scope of its containing object.
*
* An application that creates a data-stream document may omit some of the parameters
* normally contained in the object environment group, or it may specify that one or
* more default values are to be used.
*/
public final class ObjectEnvironmentGroup extends AbstractNamedAFPObject {

/**
* Default name for the object environment group
*/
private static final String DEFAULT_NAME = "OEG00001";

/**
* The ObjectAreaDescriptor for the object environment group
*/
private ObjectAreaDescriptor _objectAreaDescriptor = null;

/**
* The ObjectAreaPosition for the object environment group
*/
private ObjectAreaPosition _objectAreaPosition = null;

/**
* The ImageDataDescriptor for the object environment group
*/
private ImageDataDescriptor _imageDataDescriptor = null;

/**
* Default constructor for the ObjectEnvironmentGroup.
*/
public ObjectEnvironmentGroup() {

this(DEFAULT_NAME);

}

/**
* Constructor for the ObjectEnvironmentGroup, this takes a
* name parameter which must be 8 characters long.
* @param name the object environment group name
*/
public ObjectEnvironmentGroup(String name) {

super(name);

}

/**
* Sets the object area parameters.
* @param x the x position of the object
* @param y the y position of the object
* @param width the object width
* @param height the object height
* @param rotation the object orientation
*/
public void setObjectArea(int x, int y, int width, int height, int rotation) {

_objectAreaDescriptor = new ObjectAreaDescriptor(width, height);
_objectAreaPosition = new ObjectAreaPosition(x, y, rotation);

}

/**
* Set the dimensions of the image.
* @param xresol the x resolution of the image
* @param yresol the y resolution of the image
* @param width the image width
* @param height the image height
*/
public void setImageData(int xresol, int yresol, int width, int height) {
_imageDataDescriptor = new ImageDataDescriptor(xresol, yresol, width, height);
}

/**
* Accessor method to obtain write the AFP datastream for
* the object environment group.
* @param os The stream to write to
* @throws java.io.IOException
*/
public void writeDataStream(OutputStream os)
throws IOException {


writeStart(os);

_objectAreaDescriptor.writeDataStream(os);

_objectAreaPosition.writeDataStream(os);

if (_imageDataDescriptor != null) {
_imageDataDescriptor.writeDataStream(os);
}

writeEnd(os);

}

/**
* Helper method to write the start of the object environment group.
* @param os The stream to write to
*/
private void writeStart(OutputStream os)
throws IOException {

byte[] data = new byte[] {
0x5A, // Structured field identifier
0x00, // Length byte 1
0x10, // Length byte 2
(byte) 0xD3, // Structured field id byte 1
(byte) 0xA8, // Structured field id byte 2
(byte) 0xC7, // Structured field id byte 3
0x00, // Flags
0x00, // Reserved
0x00, // Reserved
0x00, // Name
0x00, //
0x00, //
0x00, //
0x00, //
0x00, //
0x00, //
0x00, //
};

for (int i = 0; i < _nameBytes.length; i++) {

data[9 + i] = _nameBytes[i];

}

os.write(data);

}

/**
* Helper method to write the end of the object environment group.
* @param os The stream to write to
*/
private void writeEnd(OutputStream os)
throws IOException {

byte[] data = new byte[17];

data[0] = 0x5A; // Structured field identifier
data[1] = 0x00; // Length byte 1
data[2] = 0x10; // Length byte 2
data[3] = (byte) 0xD3; // Structured field id byte 1
data[4] = (byte) 0xA9; // Structured field id byte 2
data[5] = (byte) 0xC7; // Structured field id byte 3
data[6] = 0x00; // Flags
data[7] = 0x00; // Reserved
data[8] = 0x00; // Reserved

for (int i = 0; i < _nameBytes.length; i++) {

data[9 + i] = _nameBytes[i];

}

os.write(data);

}

}

+ 130
- 0
src/sandbox/org/apache/fop/render/afp/modca/Overlay.java 查看文件

@@ -0,0 +1,130 @@
/*
* Copyright 2006 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.afp.modca;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;

/**
*/
public class Overlay extends AbstractPageObject{

/**
* Construct a new overlay object for the specified name argument, the overlay
* name should be an 8 character identifier.
*
* @param name
* the name of the page.
* @param width
* the width of the page.
* @param height
* the height of the page.
* @param rotation
* the rotation of the page.
*/
public Overlay(String name, int width, int height, int rotation) {

super(name, width, height, rotation);

}

/**
* Accessor method to write the AFP datastream for the overlay.
*
* @param os The stream to write to
* @throws java.io.IOException
*/
public void writeDataStream(OutputStream os)
throws IOException {

writeStart(os);

_activeEnvironmentGroup.writeDataStream(os);

writeObjectList(_segments, os);

writeObjectList(_tagLogicalElements, os);

writeObjectList(_objects, os);

writeEnd(os);

}

/**
* Helper method to write the start of the overlay.
* @param os The stream to write to
*/
private void writeStart(OutputStream os)
throws IOException {

byte[] data = new byte[17];

data[0] = 0x5A; // Structured field identifier
data[1] = 0x00; // Length byte 1
data[2] = 0x10; // Length byte 2
data[3] = (byte) 0xD3; // Structured field id byte 1
data[4] = (byte) 0xA8; // Structured field id byte 2
data[5] = (byte) 0xDF; // Structured field id byte 3
data[6] = 0x00; // Flags
data[7] = 0x00; // Reserved
data[8] = 0x00; // Reserved

for (int i = 0; i < _nameBytes.length; i++) {

data[9 + i] = _nameBytes[i];

}

os.write(data);

}

/**
* Helper method to write the end of the overlay.
* @param os The stream to write to
*/
private void writeEnd(OutputStream os)
throws IOException {

byte[] data = new byte[17];

data[0] = 0x5A; // Structured field identifier
data[1] = 0x00; // Length byte 1
data[2] = 0x10; // Length byte 2
data[3] = (byte) 0xD3; // Structured field id byte 1
data[4] = (byte) 0xA9; // Structured field id byte 2
data[5] = (byte) 0xDF; // Structured field id byte 3
data[6] = 0x00; // Flags
data[7] = 0x00; // Reserved
data[8] = 0x00; // Reserved

for (int i = 0; i < _nameBytes.length; i++) {

data[9 + i] = _nameBytes[i];

}

os.write(data);

}

}

+ 97
- 0
src/sandbox/org/apache/fop/render/afp/modca/PageDescriptor.java 查看文件

@@ -0,0 +1,97 @@
/*
* Copyright 2006 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.afp.modca;

import java.io.IOException;
import java.io.OutputStream;
import org.apache.fop.render.afp.tools.BinaryUtils;

/**
* The Page Descriptor structured field specifies the size and attributes of
* a page or overlay presentation space.
*
*/
public class PageDescriptor extends AbstractAFPObject {

private int _width = 0;
private int _height = 0;

/**
* Construct a page descriptor for the specified page width
* and page height.
* @param width The page width.
* @param height The page height.
*/
public PageDescriptor(int width, int height) {

_width = width;
_height = height;

}

/**
* Accessor method to write the AFP datastream for the Page Descriptor
* @param os The stream to write to
* @throws java.io.IOException
*/
public void writeDataStream(OutputStream os)
throws IOException {

byte[] data = new byte[] {
0x5A,
0x00,
0x17,
(byte) 0xD3,
(byte) 0xA6,
(byte) 0xAF,
0x00,
0x00,
0x00,
0x00,
0x00,
0x09,
0x60,
0x09,
0x60,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
};

byte[] x = BinaryUtils.convert(_width, 3);
data[15] = x[0];
data[16] = x[1];
data[17] = x[2];

byte[] y = BinaryUtils.convert(_height, 3);
data[18] = y[0];
data[19] = y[1];
data[20] = y[2];

os.write(data);

}

}

+ 207
- 0
src/sandbox/org/apache/fop/render/afp/modca/PageGroup.java 查看文件

@@ -0,0 +1,207 @@
/*
* Copyright 2006 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.afp.modca;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

/**
* A page group is used in the data stream to define a named, logical grouping
* of sequential pages. Page groups are delimited by begin-end structured fields
* that carry the name of the page group. Page groups are defined so that the
* pages that comprise the group can be referenced or processed as a single
* entity. Page groups are often processed in stand-alone fashion; that is, they
* are indexed, retrieved, and presented outside the context of the containing
* document.
*
* @author <a href="mailto:pete@townsend.uk.com">Pete Townsend </a>
*/
public class PageGroup extends AbstractNamedAFPObject {

/**
* The pages contained within this group
*/
private List _objects = new ArrayList();

/**
* The tag logical elements contained within this group
*/
private List _tagLogicalElements = new ArrayList();

/**
* The page state
*/
private boolean _complete = false;

/**
* Constructor for the PageGroup.
*
* @param name
* the name of the page group
*/
public PageGroup(String name) {

super(name);

}

/**
* Adds a page object to the group.
*
* @param page
* the page object to add
*/
public void addPage(PageObject page) {

if (!_objects.contains(page)) {
_objects.add(page);
}

}

/**
* @return the name of the page group
*/
public String getName() {
return _name;
}

/**
* Creates a TagLogicalElement on the page.
*
* @param name
* the name of the tag
* @param value
* the value of the tag
*/
public void createTagLogicalElement(String name, String value) {

TagLogicalElement tle = new TagLogicalElement(name, value);
_tagLogicalElements.add(tle);

}

/**
* Creates an InvokeMediaMap on the page.
*
* @param name
* the name of the media map
*/
public void createInvokeMediumMap(String name) {

InvokeMediumMap imm = new InvokeMediumMap(name);
_objects.add(imm);

}

/**
* Method to mark the end of the page group.
*/
public void endPageGroup() {

_complete = true;

}

/**
* Returns an indication if the page group is complete
*/
public boolean isComplete() {
return _complete;
}

/**
* Accessor method to write the AFP datastream for the page group.
* @param os The stream to write to
* @throws java.io.IOException
*/
public void writeDataStream(OutputStream os)
throws IOException {

writeStart(os);

writeObjectList(_tagLogicalElements, os);

writeObjectList(_objects, os);

writeEnd(os);

}

/**
* Helper method to write the start of the page group.
* @param os The stream to write to
*/
private void writeStart(OutputStream os)
throws IOException {

byte[] data = new byte[17];

data[0] = 0x5A; // Structured field identifier
data[1] = 0x00; // Length byte 1
data[2] = 0x10; // Length byte 2
data[3] = (byte) 0xD3; // Structured field id byte 1
data[4] = (byte) 0xA8; // Structured field id byte 2
data[5] = (byte) 0xAD; // Structured field id byte 3
data[6] = 0x00; // Flags
data[7] = 0x00; // Reserved
data[8] = 0x00; // Reserved

for (int i = 0; i < _nameBytes.length; i++) {

data[9 + i] = _nameBytes[i];

}

os.write(data);

}

/**
* Helper method to write the end of the page group.
* @param os The stream to write to
*/
private void writeEnd(OutputStream os)
throws IOException {

byte[] data = new byte[17];

data[0] = 0x5A; // Structured field identifier
data[1] = 0x00; // Length byte 1
data[2] = 0x10; // Length byte 2
data[3] = (byte) 0xD3; // Structured field id byte 1
data[4] = (byte) 0xA9; // Structured field id byte 2
data[5] = (byte) 0xAD; // Structured field id byte 3
data[6] = 0x00; // Flags
data[7] = 0x00; // Reserved
data[8] = 0x00; // Reserved

for (int i = 0; i < _nameBytes.length; i++) {

data[9 + i] = _nameBytes[i];

}

os.write(data);

}

}

+ 185
- 0
src/sandbox/org/apache/fop/render/afp/modca/PageObject.java 查看文件

@@ -0,0 +1,185 @@
/*
* Copyright 2006 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.afp.modca;
import java.io.IOException;
import java.io.OutputStream;



/**
* Pages contain the data objects that comprise a presentation document. Each
* page has a set of data objects associated with it. Each page within a
* document is independent from any other page, and each must establish its own
* environment parameters.
*
* The page is the level in the document component hierarchy that is used for
* printing or displaying a document's content. The data objects contained in
* the page envelope in the data stream are presented when the page is
* presented. Each data object has layout information associated with it that
* directs the placement and orientation of the data on the page. In addition,
* each page contains layout information that specifies the measurement units,
* page width, and page depth.
*
* A page is initiated by a begin page structured field and terminated by an end
* page structured field. Structured fields that define objects and active
* environment groups or that specify attributes of the page may be encountered
* in page state.
*
*/
public class PageObject extends AbstractPageObject {

/**
* The resource group object
*/
private ResourceGroup _resourceGroup = null;

/**
* Construct a new page object for the specified name argument, the page
* name should be an 8 character identifier.
*
* @param name
* the name of the page.
* @param width
* the width of the page.
* @param height
* the height of the page.
* @param rotation
* the rotation of the page.
*/
public PageObject(String name, int width, int height, int rotation) {

super(name, width, height, rotation);

}

/**
* Adds an overlay to the page resources
* @param the overlay to add
*/
public void addOverlay(Overlay overlay) {
if (_resourceGroup == null) {
_resourceGroup = new ResourceGroup();
}
_resourceGroup.addOverlay(overlay);
}

/**
* Creates an IncludePageOverlay on the page.
*
* @param name
* the name of the overlay
* @param x
* the x position of the overlay
* @param y
* the y position of the overlay
* @param orientation
* the orientation required for the overlay
*/
public void createIncludePageOverlay(String name, int x, int y, int orientation) {

IncludePageOverlay ipo = new IncludePageOverlay(name, x, y, orientation);
_objects.add(ipo);

}

/**
* Accessor method to write the AFP datastream for the page.
* @param os The stream to write to
* @throws java.io.IOException
*/
public void writeDataStream(OutputStream os)
throws IOException {

writeStart(os);

if (_resourceGroup != null) {
_resourceGroup.writeDataStream(os);
}

_activeEnvironmentGroup.writeDataStream(os);

writeObjectList(_segments, os);

writeObjectList(_tagLogicalElements, os);

writeObjectList(_objects, os);

writeEnd(os);

}

/**
* Helper method to write the start of the page.
* @param os The stream to write to
*/
private void writeStart(OutputStream os)
throws IOException {

byte[] data = new byte[17];

data[0] = 0x5A; // Structured field identifier
data[1] = 0x00; // Length byte 1
data[2] = 0x10; // Length byte 2
data[3] = (byte) 0xD3; // Structured field id byte 1
data[4] = (byte) 0xA8; // Structured field id byte 2
data[5] = (byte) 0xAF; // Structured field id byte 3
data[6] = 0x00; // Flags
data[7] = 0x00; // Reserved
data[8] = 0x00; // Reserved

for (int i = 0; i < _nameBytes.length; i++) {

data[9 + i] = _nameBytes[i];

}

os.write(data);

}

/**
* Helper method to write the end of the page.
* @param os The stream to write to
*/
private void writeEnd(OutputStream os)
throws IOException {

byte[] data = new byte[17];

data[0] = 0x5A; // Structured field identifier
data[1] = 0x00; // Length byte 1
data[2] = 0x10; // Length byte 2
data[3] = (byte) 0xD3; // Structured field id byte 1
data[4] = (byte) 0xA9; // Structured field id byte 2
data[5] = (byte) 0xAF; // Structured field id byte 3
data[6] = 0x00; // Flags
data[7] = 0x00; // Reserved
data[8] = 0x00; // Reserved

for (int i = 0; i < _nameBytes.length; i++) {

data[9 + i] = _nameBytes[i];

}

os.write(data);

}

}

+ 598
- 0
src/sandbox/org/apache/fop/render/afp/modca/PresentationTextData.java 查看文件

@@ -0,0 +1,598 @@
/*
* Copyright 2006 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.afp.modca;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import org.apache.fop.render.afp.AFPFontColor;

import org.apache.fop.render.afp.tools.BinaryUtils;

/**
* Presentation text data contains the graphic characters and the control
* sequences necessary to position the characters within the object space. The
* data consists of: - graphic characters to be presented - control sequences
* that position them - modal control sequences that adjust the positions by
* small amounts - other functions causing text to be presented with differences
* in appearance.
*
* The graphic characters are expected to conform to a coded font representation
* so that they can be translated from the code point in the object data to the
* character in the coded font. The units of measure for linear displacements
* are derived from the PresentationTextDescriptor or from the hierarchical
* defaults.
*
* In addition to graphic character code points, Presentation Text data can
* contain embedded control sequences. These are strings of two or more bytes
* which signal an alternate mode of processing for the content of the current
* Presentation Text data.
*
*/
public class PresentationTextData extends AbstractAFPObject {

/**
* The maximum size of the presentation text data.
*/
private static final int MAX_SIZE = 8192;

/**
* The afp data relating to this presentaion text data.
*/
private ByteArrayOutputStream _baos = new ByteArrayOutputStream(1024);

/**
* The current x coordinate.
*/
private int _currentXCoordinate = -1;

/**
* The current y cooridnate
*/
private int _currentYCoordinate = -1;

/**
* The current font
*/
private String _currentFont = "";

/**
* The current orientation
*/
private int _currentOrientation = 0;

/**
* The current color
*/
private AFPFontColor _currentColor = new AFPFontColor(0, 0, 0);

/**
* The current variable space increment
*/
private int _currentVariableSpaceCharacterIncrement = 0;

/**
* The current inter character adjustment
*/
private int _currentInterCharacterAdjustment = 0;

/**
* Default constructor for the PresentationTextData.
*/
public PresentationTextData() {

this(false);

}

/**
* Constructor for the PresentationTextData, the boolean flag indicate
* whether the control sequence prefix should be set to indicate the start
* of a new control sequence.
*
* @param controlInd
* The control sequence indicator.
*/
public PresentationTextData(boolean controlInd) {

_baos.write(new byte[] { 0x5A, // Structured field identifier
0x00, // Record length byte 1
0x00, // Record length byte 2
(byte) 0xD3, // PresentationTextData identifier byte 1
(byte) 0xEE, // PresentationTextData identifier byte 2
(byte) 0x9B, // PresentationTextData identifier byte 3
0x00, // Flag
0x00, // Reserved
0x00, // Reserved
}, 0, 9);

if (controlInd) {
_baos.write(new byte[] { 0x2B, (byte) 0xD3 }, 0, 2);
}

}

/**
* The Set Coded Font Local control sequence activates a coded font and
* specifies the character attributes to be used. This is a modal control
* sequence.
*
* @param font
* The font local identifier.
* @param afpdata
* The output stream to which data should be written.
*/
private void setCodedFont(byte font, ByteArrayOutputStream afpdata) {

// Avoid unnecessary specification of the font
if (String.valueOf(font).equals(_currentFont)) {
return;
} else {
_currentFont = String.valueOf(font);
}

afpdata.write(new byte[] { 0x03, (byte) 0xF1, font, }, 0, 3);

}

/**
* Establishes the current presentation position on the baseline at a new
* I-axis coordinate, which is a specified number of measurement units from
* the B-axis. There is no change to the current B-axis coordinate.
*
* @param coordinate
* The coordinate for the inline move.
* @param afpdata
* The output stream to which data should be written.
*/
private void absoluteMoveInline(int coordinate,
ByteArrayOutputStream afpdata) {

byte[] b = BinaryUtils.convert(coordinate, 2);

afpdata.write(new byte[] { 0x04, (byte) 0xC7, b[0], b[1], }, 0, 4);

_currentXCoordinate = coordinate;

}

/**
* Establishes the baseline and the current presentation position at a new
* B-axis coordinate, which is a specified number of measurement units from
* the I-axis. There is no change to the current I-axis coordinate.
*
* @param coordinate
* The coordinate for the baseline move.
* @param afpdata
* The output stream to which data should be written.
*/
private void absoluteMoveBaseline(int coordinate,
ByteArrayOutputStream afpdata) {

byte[] b = BinaryUtils.convert(coordinate, 2);

afpdata.write(new byte[] { 0x04, (byte) 0xD3, b[0], b[1], }, 0, 4);

_currentYCoordinate = coordinate;

}

/**
* The Transparent Data control sequence contains a sequence of code points
* that are presented without a scan for embedded control sequences.
*
* @param data
* The text data to add.
* @param afpdata
* The output stream to which data should be written.
*/
private void addTransparentData(byte[] data, ByteArrayOutputStream afpdata) {

// Calculate the length
int l = data.length + 2;

if (l > 255) {
// Check that we are not exceeding the maximum length
throw new IllegalArgumentException(
"Transparent data is longer than 253 bytes: " + data);
}

afpdata.write(new byte[] { BinaryUtils.convert(l)[0], (byte) 0xDB, },
0, 2);

afpdata.write(data, 0, data.length);

}

/**
* Draws a line of specified length and specified width in the B-direction
* from the current presentation position. The location of the current
* presentation position is unchanged.
*
* @param length
* The length of the rule.
* @param width
* The width of the rule.
* @param afpdata
* The output stream to which data should be written.
*/
private void drawBaxisRule(int length, int width,
ByteArrayOutputStream afpdata) {

afpdata.write(new byte[] { 0x07, // Length
(byte) 0xE7, // Type
}, 0, 2);

// Rule length
byte[] data1 = BinaryUtils.shortToByteArray((short) length);
afpdata.write(data1, 0, data1.length);
// Rule width
byte[] data2 = BinaryUtils.shortToByteArray((short) width);
afpdata.write(data2, 0, data2.length);
// Rule width fraction
afpdata.write(0x00);

}

/**
* Draws a line of specified length and specified width in the I-direction
* from the current presentation position. The location of the current
* presentation position is unchanged.
*
* @param length
* The length of the rule.
* @param width
* The width of the rule.
* @param afpdata
* The output stream to which data should be written.
*/
private void drawIaxisRule(int length, int width,
ByteArrayOutputStream afpdata) {

afpdata.write(new byte[] { 0x07, // Length
(byte) 0xE5, // Type
}, 0, 2);

// Rule length
byte[] data1 = BinaryUtils.shortToByteArray((short) length);
afpdata.write(data1, 0, data1.length);
// Rule width
byte[] data2 = BinaryUtils.shortToByteArray((short) width);
afpdata.write(data2, 0, data2.length);
// Rule width fraction
afpdata.write(0x00);

}

/**
* Create the presentation text data for the byte array of data.
*
* @param fontNumber
* The font resource identifier.
* @param x
* The x coordinate for the text data.
* @param y
* The y coordinate for the text data.
* @param orientation
* The orientation of the text data.
* @param col
* The text color.
* @param vsci
* The variable space character increment.
* @param ica
* The inter character adjustment.
* @param data
* The text data to be created.
* @throws MaximumSizeExceededException
*/
public void createTextData(int fontNumber, int x, int y, int orientation,
AFPFontColor col, int vsci, int ica, byte[] data)
throws MaximumSizeExceededException {

ByteArrayOutputStream afpdata = new ByteArrayOutputStream();

if (_currentOrientation != orientation) {
setTextOrientation(orientation, afpdata);
_currentOrientation = orientation;
_currentXCoordinate = -1;
_currentYCoordinate = -1;
}

// Avoid unnecessary specification of the Y co-ordinate
if (y != _currentYCoordinate) {
absoluteMoveBaseline(y, afpdata);
_currentXCoordinate = -1;
}

// Avoid unnecessary specification of the X co-ordinate
if (x != _currentXCoordinate) {
absoluteMoveInline(x, afpdata);
}

// Avoid unnecessary specification of the variable space increment
if (vsci != _currentVariableSpaceCharacterIncrement) {
setVariableSpaceCharacterIncrement(vsci, afpdata);
_currentVariableSpaceCharacterIncrement = vsci;
}

// Avoid unnecessary specification of the inter character adjustment
if (ica != _currentInterCharacterAdjustment) {
setInterCharacterAdjustment(ica, afpdata);
_currentInterCharacterAdjustment = ica;
}

// Avoid unnecessary specification of the text color
if (!col.equals(_currentColor)) {
setExtendedTextColor(col, afpdata);
_currentColor.setTo(col);
}

setCodedFont(BinaryUtils.convert(fontNumber)[0], afpdata);
addTransparentData(data, afpdata);
_currentXCoordinate = -1;

int s = afpdata.size();

if (_baos.size() + s > MAX_SIZE) {
_currentXCoordinate = -1;
_currentYCoordinate = -1;
throw new MaximumSizeExceededException();
}

byte[] outputdata = afpdata.toByteArray();
_baos.write(outputdata, 0, outputdata.length);

}

/**
* Drawing of lines using the starting and ending coordinates, thickness and
* colour arguments.
*
* @param x1
* The starting X coordinate.
* @param y1
* The starting Y coordinate.
* @param x2
* The ending X coordinate.
* @param y2
* The ending Y coordinate.
* @param thickness
* The line thickness.
* @param orientation
* The orientation of the text data.
* @param col
* The text color.
*/
public void createLineData(int x1, int y1, int x2, int y2, int thickness,
int orientation, AFPFontColor col) throws MaximumSizeExceededException {

ByteArrayOutputStream afpdata = new ByteArrayOutputStream();

if (_currentOrientation != orientation) {
setTextOrientation(orientation, afpdata);
_currentOrientation = orientation;
}

// Avoid unnecessary specification of the Y coordinate
if (y1 != _currentYCoordinate) {
absoluteMoveBaseline(y1, afpdata);
}

// Avoid unnecessary specification of the X coordinate
if (x1 != _currentXCoordinate) {
absoluteMoveInline(x1, afpdata);
}

if (!col.equals(_currentColor)) {
setExtendedTextColor(col, afpdata);
_currentColor.setTo(col);
}

if (y1 == y2) {
drawIaxisRule(x2 - x1, thickness, afpdata);
} else if (x1 == x2) {
drawBaxisRule(y2 - y1, thickness, afpdata);
} else {
return;
}

int s = afpdata.size();

if (_baos.size() + s > MAX_SIZE) {
_currentXCoordinate = -1;
_currentYCoordinate = -1;
throw new MaximumSizeExceededException();
}

byte[] outputdata = afpdata.toByteArray();
_baos.write(outputdata, 0, outputdata.length);

}

/**
* The Set Text Orientation control sequence establishes the I-direction and
* B-direction for the subsequent text. This is a modal control sequence.
*
* Semantics: This control sequence specifies the I-axis and B-axis
* orientations with respect to the Xp-axis for the current Presentation
* Text object. The orientations are rotational values expressed in degrees
* and minutes.
*
* @param orientation
* The text orientation (0,90, 180, 270).
* @param afpdata
* The output stream to which data should be written.
*/
private void setTextOrientation(int orientation,
ByteArrayOutputStream afpdata) {

afpdata.write(new byte[] { 0x06, (byte) 0xF7, }, 0, 2);

switch (orientation) {
case 90:
afpdata.write(0x2D);
afpdata.write(0x00);
afpdata.write(0x5A);
afpdata.write(0x00);
break;
case 180:
afpdata.write(0x5A);
afpdata.write(0x00);
afpdata.write(0x87);
afpdata.write(0x00);
break;
case 270:
afpdata.write(0x87);
afpdata.write(0x00);
afpdata.write(0x00);
afpdata.write(0x00);
break;
default:
afpdata.write(0x00);
afpdata.write(0x00);
afpdata.write(0x2D);
afpdata.write(0x00);
break;
}

}

/**
* The Set Extended Text Color control sequence specifies a color value and
* defines the color space and encoding for that value. The specified color
* value is applied to foreground areas of the text presentation space.
* This is a modal control sequence.
*
* @param col
* The color to be set.
* @param afpdata
* The output stream to which data should be written.
*/
private void setExtendedTextColor(AFPFontColor col,
ByteArrayOutputStream afpdata) {

afpdata.write(new byte[] {
15 // Control sequence length
, (byte)0x81 // Control sequence function type
, 0x00 // Reserved; must be zero
, 0x01 // Color space - 0x01 = RGB
, 0x00 // Reserved; must be zero
, 0x00 // Reserved; must be zero
, 0x00 // Reserved; must be zero
, 0x00 // Reserved; must be zero
, 8 // Number of bits in component 1
, 8 // Number of bits in component 2
, 8 // Number of bits in component 3
, 0 // Number of bits in component 4
, (byte)(col.getRed()) // Red intensity
, (byte)(col.getGreen()) // Green intensity
, (byte)(col.getBlue()) // Blue intensity
}, 0, 15);

}

/**
* //TODO
* This is a modal control sequence.
*
* @param incr
* The increment to be set.
* @param afpdata
* The output stream to which data should be written.
*/
private void setVariableSpaceCharacterIncrement(int incr,
ByteArrayOutputStream afpdata) {

byte[] b = BinaryUtils.convert(incr, 2);

afpdata.write(new byte[] {
4 // Control sequence length
, (byte)0xC5 // Control sequence function type
, b[0]
, b[1]
}, 0, 4);

}

/**
* //TODO
* This is a modal control sequence.
*
* @param incr
* The increment to be set.
* @param afpdata
* The output stream to which data should be written.
*/
private void setInterCharacterAdjustment(int incr,
ByteArrayOutputStream afpdata) {

byte[] b = BinaryUtils.convert(Math.abs(incr), 2);

afpdata.write(new byte[] {
5 // Control sequence length
, (byte)0xC3 // Control sequence function type
, b[0]
, b[1]
, (byte)(incr >= 0 ? 0 : 1) // Direction
}, 0, 5);

}

/**
* Accessor method to write the AFP datastream for
* the text data.
* @param os The stream to write to
* @throws java.io.IOException
*/
public void writeDataStream(OutputStream os)
throws IOException {

byte[] data = _baos.toByteArray();
byte[] size = BinaryUtils.convert(data.length - 1, 2);
data[1] = size[0];
data[2] = size[1];

os.write(data);

}

/**
* A control sequence is a sequence of bytes that specifies a control
* function. A control sequence consists of a control sequence introducer
* and zero or more parameters. The control sequence can extend multiple
* presentation text data objects, but must eventually be terminated. This
* method terminates the control sequence.
*
* @throws MaximumSizeExceededException
*/
public void endControlSequence() throws MaximumSizeExceededException {

byte[] data = new byte[2];
data[0] = 0x02;
data[1] = (byte) 0xF8;

if (data.length + _baos.size() > MAX_SIZE) {
throw new MaximumSizeExceededException();
}

_baos.write(data, 0, data.length);

}

}

+ 113
- 0
src/sandbox/org/apache/fop/render/afp/modca/PresentationTextDescriptor.java 查看文件

@@ -0,0 +1,113 @@
/*
* Copyright 2006 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.afp.modca;

import java.io.IOException;
import java.io.OutputStream;
import org.apache.fop.render.afp.tools.BinaryUtils;

/**
* The Presentation Text Descriptor specifies the units of measure for the
* Presentation Text object space, the size of the Presentation Text object
* space, and the initial values for modal parameters, called initial text
* conditions. Initial values not provided are defaulted by the controlling
* environment or the receiving device.
*
* The Presentation Text Descriptor provides the following initial values:
* - Unit base
* - Xp-units per unit base
* - Yp-units per unit base
* - Xp-extent of the presentation space
* - Yp-extent of the presentation space
* - Initial text conditions.
*
* The initial text conditions are values provided by the Presentation Text
* Descriptor to initialize the modal parameters of the control sequences.
* Modal control sequences typically are characterized by the word set in
* the name of the control sequence. Modal parameters are identified as such
* in their semantic descriptions.
*
*/
public class PresentationTextDescriptor extends AbstractAFPObject {

private int _width = 0;
private int _height = 0;

/**
* Constructor a PresentationTextDescriptor for the specified
* width and height.
* @param width The width of the page.
* @param height The height of the page.
*/
public PresentationTextDescriptor(int width, int height) {

_width = width;
_height = height;

}

/**
* Accessor method to write the AFP datastream for the Presentation Text Descriptor
* @param os The stream to write to
* @throws java.io.IOException
*/
public void writeDataStream(OutputStream os)
throws IOException {

byte[] data = new byte[] {
0x5A,
0x00,
0x16,
(byte) 0xD3,
(byte) 0xB1,
(byte) 0x9B,
0x00,
0x00,
0x00,
0x00,
0x00,
0x09,
0x60,
0x09,
0x60,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
};

byte[] x = BinaryUtils.convert(_width, 3);
data[15] = x[0];
data[16] = x[1];
data[17] = x[2];

byte[] y = BinaryUtils.convert(_height, 3);
data[18] = y[0];
data[19] = y[1];
data[20] = y[2];

os.write(data);

}

}

+ 330
- 0
src/sandbox/org/apache/fop/render/afp/modca/PresentationTextObject.java 查看文件

@@ -0,0 +1,330 @@
/*
* Copyright 2006 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.afp.modca;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import org.apache.fop.render.afp.AFPFontColor;

/**
* The Presentation Text object is the data object used in document processing
* environments for representing text which has been prepared for presentation.
* Text, as used here, means an ordered string of characters, such as graphic
* symbols, numbers, and letters, that are suitable for the specific purpose of
* representing coherent information. Text which has been prepared for
* presentation has been reduced to a primitive form through explicit
* specification of the characters and their placement in the presentation
* space. Control sequences which designate specific control functions may be
* embedded within the text. These functions extend the primitive form by
* applying specific characteristics to the text when it is presented. The
* collection of the graphic characters and control codes is called Presentation
* Text, and the object that contains the Presentation Text is called the
* PresentationText object.
*
*/
public class PresentationTextObject extends AbstractNamedAFPObject {

/**
* Default name for the presentation text object
*/
private static final String DEFAULT_NAME = "PTO00001";

private PresentationTextData currentPresentationTextData = null;

private ArrayList presentationTextData = new ArrayList();

/**
* Default constructor for the PresentationTextObject
*/
public PresentationTextObject() {

this(DEFAULT_NAME);

}

/**
* Construct a new PresentationTextObject for the specified name argument,
* the name should be an 8 character identifier.
*/
public PresentationTextObject(String name) {

super(name);

}

/**
* Create the presentation text data for the byte array of data.
*
* @param fontNumber
* The font resource identifier.
* @param x
* The x coordinate for the text data.
* @param y
* The y coordinate for the text data.
* @param col
* The text color.
* @param vsci
* The variable space character increment.
* @param ica
* The inter character increment.
* @param data
* The text data to be created.
*/
public void createTextData(int fontNumber, int x, int y, AFPFontColor col, int vsci, int ica, byte[] data) {

// Use a default orientation of zero
createTextData(fontNumber, x, y, 0, col, vsci, ica, data);

}

/**
* Create the presentation text data for the byte array of data.
*
* @param fontNumber
* The font resource identifier.
* @param x
* The x coordinate for the text data.
* @param y
* The y coordinate for the text data.
* @param orientation
* The orientation of the text data.
* @param col
* The text color.
* @param vsci
* The variable space character increment.
* @param ica
* The inter character adjustment.
* @param data
* The text data to be created.
*/
public void createTextData(int fontNumber, int x, int y, int orientation,
AFPFontColor col, int vsci, int ica, byte[] data) {

if (currentPresentationTextData == null) {
startPresentationTextData();
}

try {

currentPresentationTextData.createTextData(fontNumber, x, y,
orientation, col, vsci, ica, data);

} catch (MaximumSizeExceededException msee) {

endPresentationTextData();
createTextData(fontNumber, x, y, orientation, col, vsci, ica, data);

}

}

/**
* Drawing of lines using the starting and ending coordinates, thickness.
*
* @param x1
* The first x coordinate of the line.
* @param y1
* The first y coordinate of the line.
* @param x2
* The second x coordinate of the line.
* @param y2
* The second y coordinate of the line.
* @param thickness
* The thickness of the line.
* @param col
* The text color.
*/
public void createLineData(int x1, int y1, int x2, int y2, int thickness, AFPFontColor col) {
// Default orientation
createLineData(x1, y1, x2, y2, thickness, 0, col);
}

/**
* Drawing of lines using the starting and ending coordinates, thickness and
* orientation arguments.
*
* @param x1
* The first x coordinate of the line.
* @param y1
* The first y coordinate of the line.
* @param x2
* The second x coordinate of the line.
* @param y2
* The second y coordinate of the line.
* @param thickness
* The thickness of the line.
* @param orientation
* The orientation of the line.
* @param col
* The text color.
*/
public void createLineData(int x1, int y1, int x2, int y2, int thickness,
int orientation, AFPFontColor col) {

if (currentPresentationTextData == null) {
startPresentationTextData();
}

try {

currentPresentationTextData.createLineData(x1, y1, x2, y2,
thickness, orientation, col);

} catch (MaximumSizeExceededException msee) {

endPresentationTextData();
createLineData(x1, y1, x2, y2, thickness, orientation, col);

}

}

/**
* Helper method to mark the start of the presentation text data
*/
private void startPresentationTextData() {

if (presentationTextData.size() == 0) {
currentPresentationTextData = new PresentationTextData(true);
} else {
currentPresentationTextData = new PresentationTextData();
}

presentationTextData.add(currentPresentationTextData);

}

/**
* Helper method to mark the end of the presentation text data
*/
private void endPresentationTextData() {

currentPresentationTextData = null;

}

/**
* Accessor method to write the AFP datastream for the PresentationTextObject.
* @param os The stream to write to
* @throws java.io.IOException
*/
public void writeDataStream(OutputStream os)
throws IOException {

writeStart(os);

writeObjectList(presentationTextData, os);

writeEnd(os);

}

public String getName() {

return _name;

}

/**
* Helper method to write the start of the presenation text object.
* @param os The stream to write to
*/
private void writeStart(OutputStream os)
throws IOException {

byte[] data = new byte[17];

data[0] = 0x5A; // Structured field identifier
data[1] = 0x00; // Length byte 1
data[2] = 0x10; // Length byte 2
data[3] = (byte) 0xD3; // Structured field id byte 1
data[4] = (byte) 0xA8; // Structured field id byte 2
data[5] = (byte) 0x9B; // Structured field id byte 3
data[6] = 0x00; // Flags
data[7] = 0x00; // Reserved
data[8] = 0x00; // Reserved

for (int i = 0; i < _nameBytes.length; i++) {

data[9 + i] = _nameBytes[i];

}

os.write(data);

}

/**
* Helper method to write the end of the presenation text object.
* @param os The stream to write to
*/
private void writeEnd(OutputStream os)
throws IOException {


byte[] data = new byte[17];

data[0] = 0x5A; // Structured field identifier
data[1] = 0x00; // Length byte 1
data[2] = 0x10; // Length byte 2
data[3] = (byte) 0xD3; // Structured field id byte 1
data[4] = (byte) 0xA9; // Structured field id byte 2
data[5] = (byte) 0x9B; // Structured field id byte 3
data[6] = 0x00; // Flags
data[7] = 0x00; // Reserved
data[8] = 0x00; // Reserved

for (int i = 0; i < _nameBytes.length; i++) {

data[9 + i] = _nameBytes[i];

}

os.write(data);

}

/**
* A control sequence is a sequence of bytes that specifies a control
* function. A control sequence consists of a control sequence introducer
* and zero or more parameters. The control sequence can extend multiple
* presentation text data objects, but must eventually be terminated. This
* method terminates the control sequence.
*/
public void endControlSequence() {

if (currentPresentationTextData == null) {
startPresentationTextData();
}

try {

currentPresentationTextData.endControlSequence();

} catch (MaximumSizeExceededException msee) {

endPresentationTextData();
endControlSequence();

}

}

}

+ 151
- 0
src/sandbox/org/apache/fop/render/afp/modca/ResourceGroup.java 查看文件

@@ -0,0 +1,151 @@
/*
* Copyright 2006 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.afp.modca;

import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

/**
* A Resource Group contains a set of overlays.
*/
public final class ResourceGroup extends AbstractNamedAFPObject {

/**
* Default name for the resource group
*/
private static final String DEFAULT_NAME = "RG000001";


/**
* The overlays contained in this resource group
*/
private List _overlays = new ArrayList();

public ResourceGroup() {

this(DEFAULT_NAME);

}

/**
* Constructor for the ResourceGroup, this takes a
* name parameter which must be 8 characters long.
* @param name the resource group name
*/
public ResourceGroup(String name) {

super(name);

}

/**
* Adds an overlay to the resource group
* @param overlay the overlay to add
*/
public void addOverlay(Overlay overlay) {
_overlays.add(overlay);
}

/**
* Returns the list of overlays
* @return the list of overlays
*/
public List getOverlays() {
return _overlays;
}

/**
* Accessor method to obtain write the AFP datastream for
* the resource group.
* @param os The stream to write to
* @throws java.io.IOException
*/
public void writeDataStream(OutputStream os)
throws IOException {

writeStart(os);

writeObjectList(_overlays, os);

writeEnd(os);

}

/**
* Helper method to write the start of the resource group.
* @param os The stream to write to
*/
private void writeStart(OutputStream os)
throws IOException {

byte[] data = new byte[17];

data[0] = 0x5A; // Structured field identifier
data[1] = 0x00; // Length byte 1
data[2] = 0x10; // Length byte 2
data[3] = (byte) 0xD3; // Structured field id byte 1
data[4] = (byte) 0xA8; // Structured field id byte 2
data[5] = (byte) 0xC6; // Structured field id byte 3
data[6] = 0x00; // Flags
data[7] = 0x00; // Reserved
data[8] = 0x00; // Reserved

for (int i = 0; i < _nameBytes.length; i++) {

data[9 + i] = _nameBytes[i];

}

os.write(data);

}

/**
* Helper method to write the end of the resource group.
* @param os The stream to write to
*/
private void writeEnd(OutputStream os)
throws IOException {

byte[] data = new byte[17];

data[0] = 0x5A; // Structured field identifier
data[1] = 0x00; // Length byte 1
data[2] = 0x10; // Length byte 2
data[3] = (byte) 0xD3; // Structured field id byte 1
data[4] = (byte) 0xA9; // Structured field id byte 2
data[5] = (byte) 0xC6; // Structured field id byte 3
data[6] = 0x00; // Flags
data[7] = 0x00; // Reserved
data[8] = 0x00; // Reserved

for (int i = 0; i < _nameBytes.length; i++) {

data[9 + i] = _nameBytes[i];

}

os.write(data);

}

}

+ 148
- 0
src/sandbox/org/apache/fop/render/afp/modca/TagLogicalElement.java 查看文件

@@ -0,0 +1,148 @@
/*
* Copyright 2006 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.afp.modca;

import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;

import org.apache.fop.render.afp.tools.BinaryUtils;

/**
* A Tag Logical Element structured field assigns an attribute name and an
* attribute value to a page or page group. The Tag Logical Element structured
* field may be embedded directly in the page or page group, or it may reference
* the page or page group from a document index. When a Tag Logical Element
* structured field references a page or is embedded in a page following the
* active environment group, it is associated with the page. When a Tag Logical
* Element structured field references a page group or is embedded in a page
* group following the Begin Named Page Group structured field, it is associated
* with the page group. When a Tag Logical Element structured field is associated
* with a page group, the parameters of the Tag Logical Element structured field
* are inherited by all pages in the page group and by all other page groups
* that are nested in the page group. The scope of a Tag Logical Element is
* determined by its position with respect to other TLEs that reference, or are
* embedded in, the same page or page group. The Tag Logical Element structured
* field does not provide any presentation specifications and therefore has no
* effect on the appearance of a document when it is presented.
* <p/>
*/
public class TagLogicalElement extends AbstractAFPObject {

/**
* Name of the key, used within the TLE
*/
private String _tleName = null;

/**
* Value returned by the key
*/
private String _tleValue = null;

/**
* Byte representaion of the name
*/
private byte[] _tleByteName = null;

/**
* Byte representaion of the value
*/
private byte[] _tleByteValue = null;

/**
* Construct a tag logical element with the name and value specified.
* @param name the name of the tag logical element
* @param value the value of the tag logical element
*/
public TagLogicalElement(String name, String value) {

_tleName = name;
_tleValue = value;

try {

_tleByteName = name.getBytes(AFPConstants.EBCIDIC_ENCODING);
_tleByteValue = value.getBytes(AFPConstants.EBCIDIC_ENCODING);

} catch (UnsupportedEncodingException usee) {

_tleByteName = name.getBytes();
_tleByteValue = value.getBytes();
log.warn(
"Constructor:: UnsupportedEncodingException translating the name "
+ name);

}

}

/**
* Accessor method to obtain the byte array AFP datastream for the
* TagLogicalElement.
* @param os The outputsteam stream
* @throws java.io.IOException
*/
public void writeDataStream(OutputStream os) throws IOException {

byte[] data = new byte[17 + _tleName.length() + _tleValue.length()];

data[0] = 0x5A;
// Set the total record length
byte[] rl1 =
BinaryUtils.convert(16 + _tleName.length() + _tleValue.length(), 2);
//Ignore first byte
data[1] = rl1[0];
data[2] = rl1[1];

// Structured field ID for a TLE
data[3] = (byte) 0xD3;
data[4] = (byte) 0xA0;
data[5] = (byte) 0x90;

data[6] = 0x00; // Reserved
data[7] = 0x00; // Reserved
data[8] = 0x00; // Reserved

//Use 2 triplets, attrubute name and value (the key for indexing)

byte[] rl2 = BinaryUtils.convert(_tleName.length() + 4, 1);
data[9] = rl2[0]; // length of the triplet, including this field
data[10] = 0x02; //Identifies it as a FQN triplet
data[11] = 0x0B; // GID format
data[12] = 0x00;

int pos = 13;
for (int i = 0; i < _tleByteName.length; i++) {
data[pos++] = _tleByteName[i];
}

byte[] rl3 = BinaryUtils.convert(_tleByteValue.length + 4, 1);
data[pos++] = rl3[0]; // length of the triplet, including this field
data[pos++] = 0x36; //Identifies the triplet, attribute value
data[pos++] = 0x00; // Reserved
data[pos++] = 0x00; // Reserved

for (int i = 0; i < _tleByteValue.length; i++) {
data[pos++] = _tleByteValue[i];
}
os.write(data);

}

}

+ 60
- 0
src/sandbox/org/apache/fop/render/afp/modca/TagLogicalElementBean.java 查看文件

@@ -0,0 +1,60 @@
/*
* Copyright 2006 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.afp.modca;

/**
* The TagLogicalElementBean provides a bean for holding the attributes of
* a tag logical element as key value pairs.
* <p/>
*/
public class TagLogicalElementBean {

/** The key attribute */
private String _key;

/** The value attribute */
private String _value;

/**
* Constructor for the TagLogicalElementBean.
* @param key the key attribute
* @param value the value attribute
*/
public TagLogicalElementBean(String key, String value) {
_key = key;
_value = value;
}

/**
* Getter for the key attribute.
* @return the key
*/
public String getKey() {
return _key;
}

/**
* Getter for the value attribute.
* @return the value
*/
public String getValue() {
return _value;
}

}

+ 131
- 0
src/sandbox/org/apache/fop/render/afp/tools/BinaryUtils.java 查看文件

@@ -0,0 +1,131 @@
/*
* Copyright 2006 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.afp.tools;

import java.io.ByteArrayOutputStream;

/**
* Library of utility useful conversion methods.
*
*/
public final class BinaryUtils {

/**
* Convert an int into the corresponding byte array by encoding each
* two hexadecimal digits as a char. This will return a byte array
* to the length specified by bufsize.
* @param integer The int representation.
* @param bufsize The required byte array size.
*/
public static byte[] convert(int integer, int bufsize) {

StringBuffer buf = new StringBuffer(Integer.toHexString(integer));
if (buf.length() % 2 == 0) {
// Ignore even number of digits
} else {
// Convert to an even number of digits
buf.insert(0, "0");
}
int size = buf.length() / 2;
while (size < bufsize) {
buf.insert(0, "00");
size++;
};
return convert(buf.toString());

}

/**
* Convert an int into the corresponding byte array by encoding each
* two hexadecimal digits as a char.
* @param integer The int representation
*/
public static byte[] convert(int integer) {

return convert(Integer.toHexString(integer));

}

/**
* Convert a String of hexadecimal digits into the corresponding
* byte array by encoding each two hexadecimal digits as a byte.
* @param digits The hexadecimal digits representation.
*/
public static byte[] convert(String digits) {

if (digits.length() % 2 == 0) {
// Even number of digits, so ignore
} else {
// Convert to an even number of digits
digits = "0" + digits;
}

ByteArrayOutputStream baos = new ByteArrayOutputStream();
for (int i = 0; i < digits.length(); i += 2) {
char c1 = digits.charAt(i);
char c2 = digits.charAt(i + 1);
byte b = 0;
if ((c1 >= '0') && (c1 <= '9'))
b += ((c1 - '0') * 16);
else if ((c1 >= 'a') && (c1 <= 'f'))
b += ((c1 - 'a' + 10) * 16);
else if ((c1 >= 'A') && (c1 <= 'F'))
b += ((c1 - 'A' + 10) * 16);
else
throw new IllegalArgumentException("Bad hexadecimal digit");
if ((c2 >= '0') && (c2 <= '9'))
b += (c2 - '0');
else if ((c2 >= 'a') && (c2 <= 'f'))
b += (c2 - 'a' + 10);
else if ((c2 >= 'A') && (c2 <= 'F'))
b += (c2 - 'A' + 10);
else
throw new IllegalArgumentException("Bad hexadecimal digit");
baos.write(b);
}
return (baos.toByteArray());

}

/**
* Convert the specified short into a byte array.
* @param value The value to be converted.
* @param array The array to receive the data.
* @param offset The offset into the byte array for the start of the value.
*/
public static void shortToByteArray(
short value,
byte[] array,
int offset) {
array[offset] = (byte) (value >>> 8);
array[offset + 1] = (byte) value;
}

/**
* Convert the specified short into a byte array.
* @param value The value to be converted.
* @return The byte array
*/
public static byte[] shortToByteArray(short value) {
byte[] serverValue = new byte[2];
shortToByteArray(value, serverValue, 0);
return serverValue;
}

}

+ 112
- 0
src/sandbox/org/apache/fop/render/afp/tools/DTDEntityResolver.java 查看文件

@@ -0,0 +1,112 @@
/*
* Copyright 2006 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.afp.tools;

import java.io.IOException;
import java.net.URL;

import org.apache.fop.render.afp.exceptions.FontRuntimeException;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;

/**
* An entity resolver for both DOM and SAX models of the SAX document.
* <p>
* The entity resolver only handles queries for the DTD. It will find any URI
* with a recognised public id and return an {@link org.xml.sax.InputSource}.
* <p>
* @author <a href="mailto:joe@exubero.com">Joe Schmetzer</a>
*/
public class DTDEntityResolver implements EntityResolver {

/** Public ID for the AFP fonts 1.0 DTD. */
public static final String AFP_DTD_1_0_ID = "-//APACHE/DTD AFP Installed Font Definition DTD 1.0//EN";

/** Resource location for the AFP fonts 1.0 DTD. */
public static final String AFP_DTD_1_0_RESOURCE = "afp-fonts-1.0.dtd";

/** Public ID for the AFP fonts 1.1 DTD. */
public static final String AFP_DTD_1_1_ID = "-//APACHE/DTD AFP Installed Font Definition DTD 1.1//EN";

/** Resource location for the AFP fonts 1.1 DTD. */
public static final String AFP_DTD_1_1_RESOURCE = "afp-fonts-1.1.dtd";

/** Public ID for the AFP fonts 1.2 DTD. */
public static final String AFP_DTD_1_2_ID = "-//APACHE/DTD AFP Installed Font Definition DTD 1.2//EN";

/** Resource location for the AFP fonts 1.2 DTD. */
public static final String AFP_DTD_1_2_RESOURCE = "afp-fonts-1.2.dtd";

/**
* Resolve the combination of system and public identifiers.
* If this resolver recognises the publicId, it will handle the resolution
* from the classpath, otherwise it will return null and allow the default
* resolution to occur.
*
* @param publicId the public identifier to use
* @param systemId the system identifier to resolve
* @return An input source to the entity or null if not handled
* @throws IOException an error reading the stream
*/
public InputSource resolveEntity(String publicId, String systemId)
throws IOException {

URL resource = null;
if( AFP_DTD_1_2_ID.equals(publicId) ) {
resource = getResource( AFP_DTD_1_2_RESOURCE );
} else if( AFP_DTD_1_1_ID.equals(publicId) ) {
resource = getResource( AFP_DTD_1_1_RESOURCE );
} else if( AFP_DTD_1_0_ID.equals(publicId) ) {
throw new FontRuntimeException(
"The AFP Installed Font Definition 1.0 DTD is not longer supported" );
} else if( systemId != null && systemId.indexOf("afp-fonts.dtd") >= 0 ) {
throw new FontRuntimeException(
"The AFP Installed Font Definition DTD must be specified using the public id" );
} else {
return null;
}

InputSource inputSource = new InputSource( resource.openStream() );
inputSource.setPublicId( publicId );
inputSource.setSystemId( systemId );

return inputSource;
}

/**
* Returns the URL of a resource on the classpath
* @param resourceName the path to the resource relative to the root of the
* classpath.
* @return the URL of the required resource
* @throws FontRuntimeException if the resource could not be found.
*/
private URL getResource( String resourcePath ) {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
if (cl == null) {
cl = ClassLoader.getSystemClassLoader();
}

URL resource = cl.getResource( resourcePath );
if( resource == null ) {
throw new FontRuntimeException( "Resource " + resourcePath +
" could not be found on the classpath" );
}

return resource;
}
}

+ 80
- 0
src/sandbox/org/apache/fop/render/afp/tools/StringUtils.java 查看文件

@@ -0,0 +1,80 @@
/*
* Copyright 2006 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.afp.tools;

/**
* Library of utility methods useful in dealing with strings.
*
*/
public class StringUtils {

/**
* Padds the string to the left with the given character for
* the specified length.
* @param input The input string.
* @param padding The char used for padding.
* @param length The length of the new string.
* @return The padded string.
*/
public static String lpad(String input, char padding, int length) {

if (input == null) {
input = new String();
}

if (input.length() >= length) {
return input;
} else {
StringBuffer result = new StringBuffer();
int numChars = length - input.length();
for (int i = 0; i < numChars; i++) {
result.append(padding);
}
result.append(input);
return result.toString();
}
}

/**
* Padds the string to the right with the given character for
* the specified length.
* @param input The input string.
* @param padding The char used for padding.
* @param length The length of the new string.
* @return The padded string.
*/
public static String rpad(String input, char padding, int length) {

if (input == null) {
input = new String();
}

if (input.length() >= length) {
return input;
} else {
StringBuffer result = new StringBuffer(input);
int numChars = length - input.length();
for (int i = 0; i < numChars; i++) {
result.append(padding);
}
return result.toString();
}
}

}

+ 134
- 0
src/sandbox/org/apache/fop/render/afp/tools/StructuredFieldReader.java 查看文件

@@ -0,0 +1,134 @@
/*
* Copyright 2006 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.afp.tools;

import java.io.IOException;
import java.io.InputStream;

/**
* A helper class to read structured fields from a MO:DCA document. Each
* component of a mixed object document is explicitly defined and delimited
* in the data. This is accomplished through the use of MO:DCA data structures,
* called structured fields. Structured fields are used to envelop document
* components and to provide commands and information to applications using
* the data. Structured fields may contain one or more parameters. Each
* parameter provides one value from a set of values defined by the architecture.
* <p/>
* MO:DCA structured fields consist of two parts: an introducer that identifies
* the length and type of the structured field, and data that provides the
* structured field's effect. The data is contained in a set of parameters,
* which can consist of other data structures and data elements. The maximum
* length of a structured field is 32767 bytes.
* <p/>
*/
public class StructuredFieldReader {

/**
* The input stream to read
*/
private InputStream _inputStream = null;

/**
* The constructor for the StructuredFieldReader
* @param inputStream the input stream to process
*/
public StructuredFieldReader(InputStream inputStream) {

_inputStream = inputStream;

}

/**
* Get the next structured field as identified by the identifer
* parameter (this must be a valid MO:DCA structured field.
* @param identifier the three byte identifier
*/
public byte[] getNext(byte[] identifier) throws IOException {

int bufferPointer = 0;
byte[] bufferData = new byte[identifier.length + 2];
for (int x = 0; x < identifier.length; x++) {
bufferData[x] = (byte) 0;
}

int c;
while ((c = _inputStream.read()) > -1) {

bufferData[bufferPointer] = (byte) c;

// Check the last characters in the buffer
int index = 0;
boolean found = true;

for (int i = identifier.length - 1; i > -1; i--) {

int p = bufferPointer - index;
if (p < 0) {
p = bufferData.length + p;
}

index++;

if (identifier[i] != bufferData[p]) {
found = false;
break;
}

}

if (found) {

byte[] length = new byte[2];

int a = bufferPointer - identifier.length;
if (a < 0) {
a = bufferData.length + a;
}

int b = bufferPointer - identifier.length - 1;
if (b < 0) {
b = bufferData.length + b;
}

length[0] = bufferData[b];
length[1] = bufferData[a];

int reclength = ((length[0] & 0xFF) << 8) + (length[1] & 0xFF) - identifier.length -2;

byte[] retval = new byte[reclength];

_inputStream.read(retval, 0, reclength);

return retval;

}

bufferPointer++;
if (bufferPointer >= bufferData.length) {
bufferPointer = 0;
}

}

return new byte[] {
};

}

}

正在加载...
取消
保存