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