From 8430f0839958e9c59877fb05ae4ffb487ffc0296 Mon Sep 17 00:00:00 2001
From: Mehdi Houshmand
Date: Fri, 24 Aug 2012 14:50:54 +0000
Subject: [PATCH] Bugzilla#48954: Support for character encoding of TLEs in AFP
output. Submitted by PH.
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1376950 13f79535-47bb-0310-9956-ffa450edef68
---
.../content/xdocs/trunk/output.xml | 5 +-
src/java/org/apache/fop/afp/DataStream.java | 31 ++++---
src/java/org/apache/fop/afp/Factory.java | 8 +-
.../fop/afp/modca/AbstractPageObject.java | 13 ++-
.../org/apache/fop/afp/modca/PageGroup.java | 10 +--
.../fop/afp/modca/TagLogicalElement.java | 86 ++++++++++++++-----
.../fop/afp/modca/TagLogicalElementBean.java | 64 --------------
.../afp/modca/triplets/EncodingTriplet.java | 63 ++++++++++++++
src/java/org/apache/fop/fo/FONode.java | 17 ++++
.../fop/render/afp/AFPDocumentHandler.java | 3 +-
.../afp/extensions/AFPExtensionHandler.java | 6 ++
.../render/afp/extensions/AFPPageSetup.java | 23 +++++
.../afp/extensions/AFPPageSetupElement.java | 11 +++
status.xml | 3 +
14 files changed, 224 insertions(+), 119 deletions(-)
delete mode 100644 src/java/org/apache/fop/afp/modca/TagLogicalElementBean.java
create mode 100644 src/java/org/apache/fop/afp/modca/triplets/EncodingTriplet.java
diff --git a/src/documentation/content/xdocs/trunk/output.xml b/src/documentation/content/xdocs/trunk/output.xml
index 7c4ace72e..4f792971b 100644
--- a/src/documentation/content/xdocs/trunk/output.xml
+++ b/src/documentation/content/xdocs/trunk/output.xml
@@ -971,7 +971,8 @@ Note that the value of the encoding attribute in the example is the double-byte
xmlns:afp="http://xmlgraphics.apache.org/fop/extensions/afp">
-
+
@@ -985,7 +986,7 @@ Note that the value of the encoding attribute in the example is the double-byte
The tag-logical-element extension element can appear within a simple-page-master
(page level) or it can appear as child of page-sequence (page group level).
Multiple tag-logical-element extension elements within a simple-page-master or
- page-sequence are allowed. The name and value attributes are mandatory.
+ page-sequence are allowed. The name and value attributes are mandatory. The encoding attribute specifying a CCSID encoding is optional.
diff --git a/src/java/org/apache/fop/afp/DataStream.java b/src/java/org/apache/fop/afp/DataStream.java
index 2794ae932..9225df796 100644
--- a/src/java/org/apache/fop/afp/DataStream.java
+++ b/src/java/org/apache/fop/afp/DataStream.java
@@ -40,7 +40,7 @@ import org.apache.fop.afp.modca.Overlay;
import org.apache.fop.afp.modca.PageGroup;
import org.apache.fop.afp.modca.PageObject;
import org.apache.fop.afp.modca.ResourceGroup;
-import org.apache.fop.afp.modca.TagLogicalElementBean;
+import org.apache.fop.afp.modca.TagLogicalElement;
import org.apache.fop.afp.modca.triplets.FullyQualifiedNameTriplet;
import org.apache.fop.afp.ptoca.PtocaBuilder;
import org.apache.fop.afp.ptoca.PtocaProducer;
@@ -90,7 +90,7 @@ public class DataStream {
/** The MO:DCA interchange set in use (default to MO:DCA-P IS/2 set) */
private InterchangeSet interchangeSet
- = InterchangeSet.valueOf(InterchangeSet.MODCA_PRESENTATION_INTERCHANGE_SET_2);
+ = InterchangeSet.valueOf(InterchangeSet.MODCA_PRESENTATION_INTERCHANGE_SET_2);
private final Factory factory;
@@ -544,17 +544,19 @@ public class DataStream {
currentPage.createIncludePageSegment(name, xOrigin, yOrigin, createHardPageSegments);
}
+
+
/**
* Creates a TagLogicalElement on the current page.
*
* @param attributes
* the array of key value pairs.
*/
- public void createPageTagLogicalElement(TagLogicalElementBean[] attributes) {
+
+ public void createPageTagLogicalElement(TagLogicalElement.State[] attributes) {
for (int i = 0; i < attributes.length; i++) {
- String name = attributes[i].getKey();
- String value = attributes[i].getValue();
- currentPage.createTagLogicalElement(name, value, tleSequence++);
+
+ currentPage.createTagLogicalElement(attributes[i], tleSequence++);
}
}
@@ -564,11 +566,9 @@ public class DataStream {
* @param attributes
* the array of key value pairs.
*/
- public void createPageGroupTagLogicalElement(TagLogicalElementBean[] attributes) {
+ public void createPageGroupTagLogicalElement(TagLogicalElement.State[] attributes) {
for (int i = 0; i < attributes.length; i++) {
- String name = attributes[i].getKey();
- String value = attributes[i].getValue();
- currentPageGroup.createTagLogicalElement(name, value);
+ currentPageGroup.createTagLogicalElement(attributes[i]);
}
}
@@ -579,12 +579,17 @@ public class DataStream {
* The tag name
* @param value
* The tag value
+ * @param encoding The CCSID character set encoding
*/
- public void createTagLogicalElement(String name, String value) {
+ public void createTagLogicalElement(String name, String value, int encoding) {
+
+ TagLogicalElement.State tleState = new TagLogicalElement.State(name, value, encoding);
if (currentPage != null) {
- currentPage.createTagLogicalElement(name, value, tleSequence++);
+
+ currentPage.createTagLogicalElement(tleState, tleSequence++);
+
} else {
- currentPageGroup.createTagLogicalElement(name, value);
+ currentPageGroup.createTagLogicalElement(tleState);
}
}
diff --git a/src/java/org/apache/fop/afp/Factory.java b/src/java/org/apache/fop/afp/Factory.java
index ef68a22fb..a1cfbc66e 100644
--- a/src/java/org/apache/fop/afp/Factory.java
+++ b/src/java/org/apache/fop/afp/Factory.java
@@ -374,13 +374,13 @@ public class Factory {
/**
* Creates a MO:DCA {@link TagLogicalElement}
*
- * @param name name of the element
- * @param value value of the element
+ * @param state the attribute state for the TLE
* @param tleSequence current start tle sequence number within stream*
* @return a new {@link TagLogicalElement}
*/
- public TagLogicalElement createTagLogicalElement(String name, String value, int tleSequence) {
- TagLogicalElement tle = new TagLogicalElement(name, value, tleSequence);
+ public TagLogicalElement createTagLogicalElement(TagLogicalElement.State state,
+ int tleSequence) {
+ TagLogicalElement tle = new TagLogicalElement(state, tleSequence);
return tle;
}
diff --git a/src/java/org/apache/fop/afp/modca/AbstractPageObject.java b/src/java/org/apache/fop/afp/modca/AbstractPageObject.java
index e8b8bc1df..11b5f98b5 100644
--- a/src/java/org/apache/fop/afp/modca/AbstractPageObject.java
+++ b/src/java/org/apache/fop/afp/modca/AbstractPageObject.java
@@ -223,19 +223,16 @@ public abstract class AbstractPageObject extends AbstractNamedAFPObject implemen
/**
* Creates a TagLogicalElement on the page.
*
- * @param name
- * the name of the tag
- * @param value
- * the value of the tag
- * @param tleID
- * unique ID within AFP stream
+ * @param state the state of the TLE
+ * @param tleID the id of the TLE
*/
- public void createTagLogicalElement(String name, String value, int tleID) {
- TagLogicalElement tle = new TagLogicalElement(name, value, tleID);
+ public void createTagLogicalElement(TagLogicalElement.State state, int tleID) {
+ TagLogicalElement tle = new TagLogicalElement(state, tleID);
List list = getTagLogicalElements();
list.add(tle);
}
+
/**
* Creates a NoOperation on the page.
*
diff --git a/src/java/org/apache/fop/afp/modca/PageGroup.java b/src/java/org/apache/fop/afp/modca/PageGroup.java
index e7c18d72b..50f7ecde6 100644
--- a/src/java/org/apache/fop/afp/modca/PageGroup.java
+++ b/src/java/org/apache/fop/afp/modca/PageGroup.java
@@ -55,13 +55,11 @@ public class PageGroup extends AbstractResourceEnvironmentGroupContainer {
/**
* Creates a TagLogicalElement on the page.
*
- * @param name
- * the name of the tag
- * @param value
- * the value of the tag
+ * @param state
+ * the state of the TLE
*/
- public void createTagLogicalElement(String name, String value) {
- TagLogicalElement tle = factory.createTagLogicalElement(name, value, tleSequence);
+ public void createTagLogicalElement(TagLogicalElement.State state) {
+ TagLogicalElement tle = factory.createTagLogicalElement(state, tleSequence);
if (!getTagLogicalElements().contains(tle)) {
getTagLogicalElements().add(tle);
tleSequence++;
diff --git a/src/java/org/apache/fop/afp/modca/TagLogicalElement.java b/src/java/org/apache/fop/afp/modca/TagLogicalElement.java
index 706ceae3b..c5efa13e6 100644
--- a/src/java/org/apache/fop/afp/modca/TagLogicalElement.java
+++ b/src/java/org/apache/fop/afp/modca/TagLogicalElement.java
@@ -24,6 +24,7 @@ import java.io.OutputStream;
import org.apache.fop.afp.modca.triplets.AttributeQualifierTriplet;
import org.apache.fop.afp.modca.triplets.AttributeValueTriplet;
+import org.apache.fop.afp.modca.triplets.EncodingTriplet;
import org.apache.fop.afp.modca.triplets.FullyQualifiedNameTriplet;
import org.apache.fop.afp.util.BinaryUtils;
@@ -49,15 +50,9 @@ import org.apache.fop.afp.util.BinaryUtils;
public class TagLogicalElement extends AbstractTripletStructuredObject {
/**
- * Name of the key, used within the TLE
+ * the params of the TLE
*/
- private String name = null;
-
- /**
- * Value returned by the key
- */
- private String value = null;
-
+ private State state;
/**
* Sequence of TLE within document
*/
@@ -66,25 +61,26 @@ public class TagLogicalElement extends AbstractTripletStructuredObject {
/**
* 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
+ * @param state the state of the tag logical element
* @param tleID unique identifier for TLE within AFP stream
*/
- public TagLogicalElement(String name, String value, int tleID) {
- this.name = name;
- this.value = value;
+
+ public TagLogicalElement(State state, int tleID) {
+ this.state = state;
+
this.tleID = tleID;
}
- /**
- * Sets the attribute value of this structured field
- *
- * @param value the attribute value
- */
- public void setAttributeValue(String value) {
+ private void setAttributeValue(String value) {
addTriplet(new AttributeValueTriplet(value));
}
+ private void setEncoding(int encoding) {
+ if (encoding != State.ENCODING_NONE) {
+ addTriplet(new EncodingTriplet(encoding));
+ }
+ }
+
/**
* Sets the attribute qualifier of this structured field
*
@@ -100,8 +96,9 @@ public class TagLogicalElement extends AbstractTripletStructuredObject {
setFullyQualifiedName(
FullyQualifiedNameTriplet.TYPE_ATTRIBUTE_GID,
FullyQualifiedNameTriplet.FORMAT_CHARSTR,
- name);
- setAttributeValue(value);
+ state.key);
+ setAttributeValue(state.value);
+ setEncoding(state.encoding);
setAttributeQualifier(tleID, 1);
byte[] data = new byte[SF_HEADER_LENGTH];
@@ -115,4 +112,51 @@ public class TagLogicalElement extends AbstractTripletStructuredObject {
writeTriplets(os);
}
+
+ /**
+ *
+ * Holds the attribute state of a TLE
+ *
+ */
+ public static class State {
+
+ /**
+ * value interpreted as no encoding
+ */
+ public static final int ENCODING_NONE = -1;
+ /** The key attribute */
+ private String key;
+
+ /** The value attribute */
+ private String value;
+
+ /** The CCSID character et encoding attribute */
+ private int encoding = ENCODING_NONE;
+
+
+ /**
+ * Constructor
+ *
+ * @param key the key attribute
+ * @param value the value attribute
+ */
+ public State(String key, String value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ /**
+ *
+ * @param key the key attribute
+ * @param value the value attribute
+ * @param encoding the CCSID character set encoding attribute
+ */
+ public State(String key, String value, int encoding) {
+ this.key = key;
+ this.value = value;
+ this.encoding = encoding;
+ }
+
+
+ }
}
diff --git a/src/java/org/apache/fop/afp/modca/TagLogicalElementBean.java b/src/java/org/apache/fop/afp/modca/TagLogicalElementBean.java
deleted file mode 100644
index 923a5d590..000000000
--- a/src/java/org/apache/fop/afp/modca/TagLogicalElementBean.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* $Id$ */
-
-package org.apache.fop.afp.modca;
-
-/**
- * The TagLogicalElementBean provides a bean for holding the attributes of
- * a tag logical element as key value pairs.
- *
- */
-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) {
- this.key = key;
- this.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;
- }
-
-}
diff --git a/src/java/org/apache/fop/afp/modca/triplets/EncodingTriplet.java b/src/java/org/apache/fop/afp/modca/triplets/EncodingTriplet.java
new file mode 100644
index 000000000..05e56e5ae
--- /dev/null
+++ b/src/java/org/apache/fop/afp/modca/triplets/EncodingTriplet.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.afp.modca.triplets;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.afp.util.BinaryUtils;
+/**
+ *
+ * Represents a CCSID encoding triplet.
+ *
+ */
+public class EncodingTriplet extends AbstractTriplet {
+
+
+ private int encoding;
+ /**
+ * @param encoding the CCSID character set encoding
+ */
+ public EncodingTriplet( int encoding) {
+ super(CODED_GRAPHIC_CHARACTER_SET_GLOBAL_IDENTIFIER);
+ this.encoding = encoding;
+ }
+ /** {@inheritDoc} */
+ public void writeToStream(OutputStream os) throws IOException {
+
+ // [len,id,0,0,0,0]
+ byte[] data = getData();
+
+ byte[] encodingBytes = BinaryUtils.convert(encoding, 2);
+
+ // [len,id,0,0,0,0] -> [len.id,0,0,encodingBytes[0],encodingBytes[1]]
+ System.arraycopy(encodingBytes, 0, data, 4, encodingBytes.length);
+
+ os.write(data);
+
+ }
+
+ /** {@inheritDoc} */
+ public int getDataLength() {
+ //len(1b) + id(1b) + 0x0000 (2b) + encoding (2b) = 6b
+ return 6;
+ }
+
+}
diff --git a/src/java/org/apache/fop/fo/FONode.java b/src/java/org/apache/fop/fo/FONode.java
index c66259f11..8b55e6d30 100644
--- a/src/java/org/apache/fop/fo/FONode.java
+++ b/src/java/org/apache/fop/fo/FONode.java
@@ -38,6 +38,7 @@ import org.apache.fop.accessibility.StructureTreeElement;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.complexscripts.bidi.DelimitedTextRange;
+import org.apache.fop.fo.expr.PropertyException;
import org.apache.fop.fo.extensions.ExtensionAttachment;
import org.apache.fop.fo.extensions.ExtensionElementMapping;
import org.apache.fop.fo.extensions.InternalElementMapping;
@@ -601,6 +602,22 @@ public abstract class FONode implements Cloneable {
getFOValidationEventProducer().missingProperty(this, getName(), propertyName, locator);
}
+
+
+ /**
+ * Helper function to throw an error caused by an invalid property
+ *
+ * @param propertyName the name of the property.
+ * @param propertyValue the value of the property.
+ * * @param e optional property parsing exception.
+ * @throws ValidationException the validation error provoked by the method call
+ */
+ protected void invalidPropertyValueError(String propertyName, String propertyValue, Exception e)
+ throws ValidationException {
+ getFOValidationEventProducer().invalidPropertyValue(this, getName(), propertyName,
+ propertyValue, new PropertyException(e), locator);
+ }
+
/**
* Helper function to return "Error(line#/column#)" string for
* above exception messages
diff --git a/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java b/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java
index a0b1e99db..35db42ac4 100644
--- a/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java
+++ b/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java
@@ -318,7 +318,8 @@ public class AFPDocumentHandler extends AbstractBinaryWritingIFDocumentHandler
case IN_PAGE_HEADER:
String name = aps.getName();
String value = aps.getValue();
- dataStream.createTagLogicalElement(name, value);
+ int encoding = aps.getEncoding();
+ dataStream.createTagLogicalElement(name, value, encoding);
break;
default:
throw new IFException(
diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java b/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java
index 14a34a0b3..abf6e359e 100644
--- a/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java
+++ b/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java
@@ -144,6 +144,12 @@ public class AFPExtensionHandler extends DefaultHandler
if (placement != null && placement.length() > 0) {
pageSetupExtn.setPlacement(ExtensionPlacement.fromXMLValue(placement));
}
+
+ String encoding = lastAttributes.getValue("encoding");
+ if (encoding != null && pageSetupExtn != null) {
+ pageSetupExtn.setEncoding(Integer.parseInt(encoding));
+ }
+
if (content.length() > 0 && pageSetupExtn != null) {
pageSetupExtn.setContent(content.toString());
content.setLength(0); //Reset text buffer (see characters())
diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPPageSetup.java b/src/java/org/apache/fop/render/afp/extensions/AFPPageSetup.java
index 2d30f3ae8..27db41d39 100644
--- a/src/java/org/apache/fop/render/afp/extensions/AFPPageSetup.java
+++ b/src/java/org/apache/fop/render/afp/extensions/AFPPageSetup.java
@@ -23,6 +23,8 @@ import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
+import org.apache.fop.afp.modca.TagLogicalElement;
+
/**
* This is the pass-through value object for the AFP extension.
*/
@@ -47,6 +49,27 @@ public class AFPPageSetup extends AFPExtensionAttachment {
/** defines where to place the extension in the generated file */
protected ExtensionPlacement placement = ExtensionPlacement.DEFAULT;
+ /**
+ * the CCSID character set encoding
+ */
+ protected int encoding = TagLogicalElement.State.ENCODING_NONE;
+
+ /**
+ *
+ * @return CCSID character set encoding
+ */
+ public int getEncoding() {
+ return encoding;
+ }
+
+ /**
+ *
+ * @param encoding CCSID character set encoding
+ */
+ public void setEncoding(int encoding) {
+ this.encoding = encoding;
+ }
+
/**
* Default constructor.
*
diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java b/src/java/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java
index 42be9bfe0..9b325c5cd 100644
--- a/src/java/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java
+++ b/src/java/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java
@@ -35,6 +35,7 @@ import org.apache.fop.fo.extensions.ExtensionAttachment;
*/
public class AFPPageSetupElement extends AbstractAFPExtensionObject {
+ private static final String ATT_ENCODING = "encoding";
private static final String ATT_SRC = "src";
/**
@@ -105,6 +106,16 @@ public class AFPPageSetupElement extends AbstractAFPExtensionObject {
} else {
missingPropertyError(AFPPageSetup.ATT_VALUE);
}
+ attr = attlist.getValue(ATT_ENCODING);
+ if (attr != null) {
+ try {
+ pageSetup.setEncoding(Integer.parseInt(attr));
+ } catch (NumberFormatException nfe) {
+ invalidPropertyValueError(ATT_ENCODING, attr, nfe);
+ }
+
+ }
+
}
String placement = attlist.getValue(AFPPageSetup.ATT_PLACEMENT);
if (placement != null && placement.length() > 0) {
diff --git a/status.xml b/status.xml
index 270496f59..aa9b0d5c1 100644
--- a/status.xml
+++ b/status.xml
@@ -62,6 +62,9 @@
documents. Example: the fix of marks layering will be such a case when it's done.
-->
+
+ Support for character encoding of TLEs in AFP output
+
When PDF accessibility is enabled, the contents for the different regions must appear in the
proper order in the structure tree.
--
2.39.5