aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPeter Hancock <phancock@apache.org>2012-10-04 14:46:01 +0000
committerPeter Hancock <phancock@apache.org>2012-10-04 14:46:01 +0000
commitaf57408966c6e9a525475f52bdc96add31cb0e51 (patch)
tree7aec6fd97d2d6c501be6b2473aa399b236e37a51 /src
parent118f9d4f0f6aeed4971ea9cc61fd4d63198c9a84 (diff)
parentd261730a4f7be752ae12a5ec52e6bad8ee4fa5c1 (diff)
downloadxmlgraphics-fop-af57408966c6e9a525475f52bdc96add31cb0e51.tar.gz
xmlgraphics-fop-af57408966c6e9a525475f52bdc96add31cb0e51.zip
Merged trunk@1391502
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_RoundedCorners@1394098 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src')
-rw-r--r--src/documentation/content/xdocs/dev/index.xml2
-rw-r--r--src/documentation/content/xdocs/maillist.xml6
-rw-r--r--src/documentation/content/xdocs/trunk/output.xml10
-rw-r--r--src/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverter.java41
-rw-r--r--src/java/org/apache/fop/accessibility/fo/FOEventRecorder.java508
-rw-r--r--src/java/org/apache/fop/accessibility/fo/StructureTreeEventTrigger.java70
-rw-r--r--src/java/org/apache/fop/afp/AFPStreamer.java3
-rw-r--r--src/java/org/apache/fop/afp/DataStream.java37
-rw-r--r--src/java/org/apache/fop/afp/Factory.java13
-rw-r--r--src/java/org/apache/fop/afp/modca/AbstractPageObject.java12
-rw-r--r--src/java/org/apache/fop/afp/modca/PageGroup.java25
-rw-r--r--src/java/org/apache/fop/afp/modca/TagLogicalElement.java92
-rw-r--r--src/java/org/apache/fop/afp/modca/TagLogicalElementBean.java64
-rw-r--r--src/java/org/apache/fop/afp/modca/triplets/EncodingTriplet.java63
-rw-r--r--src/java/org/apache/fop/afp/util/AFPResourceAccessor.java2
-rw-r--r--src/java/org/apache/fop/apps/EnvironmentProfile.java7
-rw-r--r--src/java/org/apache/fop/apps/EnvironmentalProfileFactory.java21
-rw-r--r--src/java/org/apache/fop/apps/FOUserAgent.java32
-rw-r--r--src/java/org/apache/fop/apps/FopConfParser.java2
-rw-r--r--src/java/org/apache/fop/apps/FopFactory.java6
-rw-r--r--src/java/org/apache/fop/apps/FopFactoryBuilder.java7
-rw-r--r--src/java/org/apache/fop/apps/FopFactoryConfig.java10
-rw-r--r--src/java/org/apache/fop/apps/io/InternalResourceResolver.java4
-rw-r--r--src/java/org/apache/fop/apps/io/ResourceResolver.java51
-rw-r--r--src/java/org/apache/fop/apps/io/ResourceResolverFactory.java118
-rw-r--r--src/java/org/apache/fop/apps/io/TempResourceResolver.java48
-rw-r--r--src/java/org/apache/fop/apps/io/TempResourceURIGenerator.java57
-rw-r--r--src/java/org/apache/fop/area/CachedRenderPagesModel.java3
-rw-r--r--src/java/org/apache/fop/area/PageViewport.java177
-rw-r--r--src/java/org/apache/fop/cli/CommandLineOptions.java2
-rw-r--r--src/java/org/apache/fop/events/CompositeEventListener.java16
-rw-r--r--src/java/org/apache/fop/fo/Constants.java9
-rw-r--r--src/java/org/apache/fop/fo/DelegatingFOEventHandler.java20
-rw-r--r--src/java/org/apache/fop/fo/FOEventHandler.java30
-rw-r--r--src/java/org/apache/fop/fo/FONode.java30
-rw-r--r--src/java/org/apache/fop/fo/FOPropertyMapping.java14
-rw-r--r--src/java/org/apache/fop/fo/FOValidationEventProducer.java12
-rw-r--r--src/java/org/apache/fop/fo/FOValidationEventProducer.xml1
-rw-r--r--src/java/org/apache/fop/fo/FObj.java13
-rw-r--r--src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java1
-rw-r--r--src/java/org/apache/fop/fo/extensions/InternalElementMapping.java3
-rw-r--r--src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java44
-rw-r--r--src/java/org/apache/fop/fo/flow/Markers.java212
-rw-r--r--src/java/org/apache/fop/fo/flow/RetrieveMarker.java17
-rw-r--r--src/java/org/apache/fop/fo/flow/RetrieveTableMarker.java25
-rw-r--r--src/java/org/apache/fop/fo/flow/table/TableCell.java9
-rw-r--r--src/java/org/apache/fop/fo/flow/table/TableColumn.java12
-rw-r--r--src/java/org/apache/fop/fo/flow/table/TablePart.java2
-rw-r--r--src/java/org/apache/fop/fo/pagination/Flow.java5
-rw-r--r--src/java/org/apache/fop/fo/pagination/LayoutMasterSet.java19
-rw-r--r--src/java/org/apache/fop/fo/pagination/StaticContent.java2
-rw-r--r--src/java/org/apache/fop/fonts/CIDFont.java4
-rw-r--r--src/java/org/apache/fop/fonts/CIDFull.java113
-rw-r--r--src/java/org/apache/fop/fonts/CIDSet.java90
-rw-r--r--src/java/org/apache/fop/fonts/CIDSubset.java129
-rw-r--r--src/java/org/apache/fop/fonts/FontCacheManager.java18
-rw-r--r--src/java/org/apache/fop/fonts/FontCacheManagerFactory.java37
-rw-r--r--src/java/org/apache/fop/fonts/FontManager.java32
-rw-r--r--src/java/org/apache/fop/fonts/FontManagerConfigurator.java34
-rw-r--r--src/java/org/apache/fop/fonts/FontReader.java2
-rw-r--r--src/java/org/apache/fop/fonts/LazyFont.java3
-rw-r--r--src/java/org/apache/fop/fonts/MultiByteFont.java69
-rw-r--r--src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java2
-rw-r--r--src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java5
-rw-r--r--src/java/org/apache/fop/image/loader/batik/PreloaderWMF.java5
-rw-r--r--src/java/org/apache/fop/layoutmgr/AbstractBaseLayoutManager.java7
-rw-r--r--src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java61
-rw-r--r--src/java/org/apache/fop/layoutmgr/AbstractPageSequenceLayoutManager.java11
-rw-r--r--src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java5
-rw-r--r--src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java4
-rw-r--r--src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java4
-rw-r--r--src/java/org/apache/fop/layoutmgr/BreakElement.java21
-rw-r--r--src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java21
-rw-r--r--src/java/org/apache/fop/layoutmgr/LocalBreaker.java137
-rw-r--r--src/java/org/apache/fop/layoutmgr/RetrieveTableMarkerLayoutManager.java75
-rw-r--r--src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java113
-rw-r--r--src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java4
-rw-r--r--src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java4
-rw-r--r--src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java4
-rw-r--r--src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java4
-rw-r--r--src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java4
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/RowPainter.java7
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java187
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java26
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java124
-rw-r--r--src/java/org/apache/fop/pdf/PDFDocument.java28
-rw-r--r--src/java/org/apache/fop/pdf/PDFEncoding.java99
-rw-r--r--src/java/org/apache/fop/pdf/PDFFactory.java112
-rw-r--r--src/java/org/apache/fop/pdf/PDFFont.java2
-rw-r--r--src/java/org/apache/fop/pdf/PDFStructElem.java6
-rw-r--r--src/java/org/apache/fop/pdf/PDFStructTreeRoot.java3
-rw-r--r--src/java/org/apache/fop/pdf/StandardStructureTypes.java5
-rw-r--r--src/java/org/apache/fop/pdf/StructureHierarchyMember.java (renamed from src/java/org/apache/fop/apps/io/Resource.java)38
-rw-r--r--src/java/org/apache/fop/render/afp/AFPDocumentHandler.java3
-rw-r--r--src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java6
-rw-r--r--src/java/org/apache/fop/render/afp/extensions/AFPPageSetup.java23
-rw-r--r--src/java/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java11
-rw-r--r--src/java/org/apache/fop/render/bitmap/AbstractBitmapDocumentHandler.java2
-rw-r--r--src/java/org/apache/fop/render/bitmap/BitmapRenderingSettings.java23
-rw-r--r--src/java/org/apache/fop/render/bitmap/TIFFCompressionValue.java98
-rw-r--r--src/java/org/apache/fop/render/bitmap/TIFFCompressionValues.java61
-rw-r--r--src/java/org/apache/fop/render/bitmap/TIFFDocumentHandler.java3
-rw-r--r--src/java/org/apache/fop/render/bitmap/TIFFRenderer.java40
-rw-r--r--src/java/org/apache/fop/render/bitmap/TIFFRendererConfig.java28
-rw-r--r--src/java/org/apache/fop/render/bitmap/TIFFRendererConfigurator.java41
-rw-r--r--src/java/org/apache/fop/render/pdf/FOToPDFRoleMap.java162
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFEventProducer.java3
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFStructureTreeBuilder.java326
-rw-r--r--src/java/org/apache/fop/render/pdf/PageSequenceStructElem.java79
-rw-r--r--src/java/org/apache/fop/render/pdf/TableStructElem.java48
-rw-r--r--src/java/org/apache/fop/render/ps/PSDocumentHandler.java2
-rw-r--r--src/java/org/apache/fop/render/ps/PSFontUtils.java30
-rw-r--r--src/java/org/apache/fop/servlet/FopServlet.java5
113 files changed, 2651 insertions, 1991 deletions
diff --git a/src/documentation/content/xdocs/dev/index.xml b/src/documentation/content/xdocs/dev/index.xml
index 357402026..27f1b2cd9 100644
--- a/src/documentation/content/xdocs/dev/index.xml
+++ b/src/documentation/content/xdocs/dev/index.xml
@@ -97,7 +97,7 @@ To review the archives, you have several options:
<li>The <link href="http://marc.theaimsgroup.com/?l=fop-dev&amp;r=1&amp;w=2">Mailing list ARChives</link> (MARC) at the AIMS group (search).</li>
<li><link href="http://www.mail-archive.com/fop-dev%40xmlgraphics.apache.org/">The Mail Archive</link>.</li>
<li>The <link href="http://dir.gmane.org/gmane.text.xml.fop.devel">GMANE</link> archive.</li>
- <li>The <link href="http://www.nabble.com/FOP---Dev-f352.html">Nabble</link> archive.</li>
+ <li>The <link href="http://apache-fop.1065347.n5.nabble.com/">Nabble</link> archive.</li>
<li>The <link href="http://fop-dev.markmail.org">MarkMail</link> archive.</li>
</ul>
</li>
diff --git a/src/documentation/content/xdocs/maillist.xml b/src/documentation/content/xdocs/maillist.xml
index b24166462..406ccf3c0 100644
--- a/src/documentation/content/xdocs/maillist.xml
+++ b/src/documentation/content/xdocs/maillist.xml
@@ -43,17 +43,17 @@ If you are using Microsoft Outlook, this setting can be found at the "Mail Forma
<title>Archives</title>
<p>To review the archives, you have several options:</p>
<ul>
-
+
<li>The <link href="http://mail-archives.apache.org/mod_mbox/xmlgraphics-fop-users/">Apache Mailing List archive</link> (mod_mbox archive, no full-text search, yet).</li>
<li>The <link href="http://xmlgraphics.apache.org/mail/fop-users/">Apache Mailing List archive</link> (gzipped mbox files).</li>
<li>The <jump href="http://marc.theaimsgroup.com/?l=fop-user&amp;r=1&amp;w=2">Mailing list ARChives </jump> (MARC) at the AIMS group.</li>
<li><jump href="http://www.mail-archive.com/fop-users%40xmlgraphics.apache.org/">The Mail Archive</jump>.</li>
<li>The <jump href="http://dir.gmane.org/gmane.text.xml.fop.user">GMANE archive</jump>.</li>
- <li>The <jump href="http://www.nabble.com/FOP---Users-f353.html">Nabble archive</jump> (only posts after May 2005).</li>
+ <li>The <jump href="http://apache-fop.1065347.n5.nabble.com/FOP-Users-f3.html">Nabble archive</jump> (only posts after May 2005).</li>
<li>The <jump href="http://fop-users.markmail.org/">MarkMail archive</jump>.</li>
</ul>
<note>
- If you don't like mailing lists and prefer a forum-like system, have a look at
+ If you don't like mailing lists and prefer a forum-like system, have a look at
<jump href="http://dir.gmane.org/gmane.text.xml.fop.user">GMANE</jump> or
<jump href="http://www.nabble.com/FOP---Users-f353.html">Nabble</jump>. They
allow you to post to the mailing list without having to subscribe.
diff --git a/src/documentation/content/xdocs/trunk/output.xml b/src/documentation/content/xdocs/trunk/output.xml
index 7c4ace72e..5de820c18 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">
<fo:layout-master-set>
<fo:simple-page-master master-name="simple">
- <afp:tag-logical-element name="The TLE Name" value="The TLE Value" />
+ <afp:tag-logical-element name="The TLE Name" value="The TLE Value"
+ encoding="500" />
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
@@ -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.
</p>
</section>
<section id="afp-no-operation">
@@ -1269,6 +1270,7 @@ Note that the value of the encoding attribute in the example is the double-byte
<source><![CDATA[<renderer mime="image/tiff">
<transparent-page-background>true</transparent-page-background>
<compression>CCITT T.6</compression>
+ <single-strip>true</single-strip>
<fonts><!-- described elsewhere --></fonts>
</renderer>]]></source>
<p>
@@ -1302,6 +1304,10 @@ Note that the value of the encoding attribute in the example is the double-byte
added separately. The internal TIFF codec from XML Graphics Commons only supports PackBits,
Deflate and JPEG compression for writing.
</note>
+ <p>
+ The default value for the <code>"single-strip"</code> is <code>"false"</code> resulting in the RowsPerStrip Tiff Tag equal to the number of rows.
+ If set to <code>true</code> RowsPerStrip is set to 1.
+ </p>
</section>
<section id="bitmap-rendering-options">
<title>Runtime Rendering Options</title>
diff --git a/src/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverter.java b/src/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverter.java
index 27469d6e0..aaf112cb5 100644
--- a/src/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverter.java
+++ b/src/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverter.java
@@ -72,8 +72,6 @@ public class FO2StructureTreeConverter extends DelegatingFOEventHandler {
private final Stack<FOEventHandler> converters = new Stack<FOEventHandler>();
- private final Stack<FOEventRecorder> tableFooterRecorders = new Stack<FOEventRecorder>();
-
private final FOEventHandler structureTreeEventTrigger;
/** The descendants of some elements like fo:leader must be ignored. */
@@ -166,6 +164,20 @@ public class FO2StructureTreeConverter extends DelegatingFOEventHandler {
}
@Override
+ public void startStatic(StaticContent staticContent) {
+ handleStartArtifact(staticContent);
+ converter.startStatic(staticContent);
+ super.startStatic(staticContent);
+ }
+
+ @Override
+ public void endStatic(StaticContent staticContent) {
+ converter.endStatic(staticContent);
+ handleEndArtifact(staticContent);
+ super.endStatic(staticContent);
+ }
+
+ @Override
public void startFlow(Flow fl) {
converter.startFlow(fl);
super.startFlow(fl);
@@ -216,16 +228,11 @@ public class FO2StructureTreeConverter extends DelegatingFOEventHandler {
@Override
public void startTable(Table tbl) {
converter.startTable(tbl);
- tableFooterRecorders.push(null);
super.startTable(tbl);
}
@Override
public void endTable(Table tbl) {
- FOEventRecorder tableFooterRecorder = tableFooterRecorders.pop();
- if (tableFooterRecorder != null) {
- tableFooterRecorder.replay(converter);
- }
converter.endTable(tbl);
super.endTable(tbl);
}
@@ -256,8 +263,6 @@ public class FO2StructureTreeConverter extends DelegatingFOEventHandler {
@Override
public void startFooter(TableFooter footer) {
- converters.push(converter);
- converter = new FOEventRecorder();
converter.startFooter(footer);
super.startFooter(footer);
}
@@ -265,10 +270,6 @@ public class FO2StructureTreeConverter extends DelegatingFOEventHandler {
@Override
public void endFooter(TableFooter footer) {
converter.endFooter(footer);
- /* Replace the dummy table footer with the real one. */
- tableFooterRecorders.pop();
- tableFooterRecorders.push((FOEventRecorder) converter);
- converter = converters.pop();
super.endFooter(footer);
}
@@ -357,20 +358,6 @@ public class FO2StructureTreeConverter extends DelegatingFOEventHandler {
}
@Override
- public void startStatic(StaticContent staticContent) {
- handleStartArtifact(staticContent);
- converter.startStatic(staticContent);
- super.startStatic(staticContent);
- }
-
- @Override
- public void endStatic(StaticContent statisContent) {
- converter.endStatic(statisContent);
- handleEndArtifact(statisContent);
- super.endStatic(statisContent);
- }
-
- @Override
public void startMarkup() {
converter.startMarkup();
super.startMarkup();
diff --git a/src/java/org/apache/fop/accessibility/fo/FOEventRecorder.java b/src/java/org/apache/fop/accessibility/fo/FOEventRecorder.java
deleted file mode 100644
index b2b18046d..000000000
--- a/src/java/org/apache/fop/accessibility/fo/FOEventRecorder.java
+++ /dev/null
@@ -1,508 +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.accessibility.fo;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.fop.fo.FOEventHandler;
-import org.apache.fop.fo.FOText;
-import org.apache.fop.fo.flow.BasicLink;
-import org.apache.fop.fo.flow.Block;
-import org.apache.fop.fo.flow.BlockContainer;
-import org.apache.fop.fo.flow.Character;
-import org.apache.fop.fo.flow.ExternalGraphic;
-import org.apache.fop.fo.flow.Footnote;
-import org.apache.fop.fo.flow.FootnoteBody;
-import org.apache.fop.fo.flow.Inline;
-import org.apache.fop.fo.flow.InstreamForeignObject;
-import org.apache.fop.fo.flow.Leader;
-import org.apache.fop.fo.flow.ListBlock;
-import org.apache.fop.fo.flow.ListItem;
-import org.apache.fop.fo.flow.ListItemBody;
-import org.apache.fop.fo.flow.ListItemLabel;
-import org.apache.fop.fo.flow.PageNumber;
-import org.apache.fop.fo.flow.PageNumberCitation;
-import org.apache.fop.fo.flow.PageNumberCitationLast;
-import org.apache.fop.fo.flow.Wrapper;
-import org.apache.fop.fo.flow.table.Table;
-import org.apache.fop.fo.flow.table.TableBody;
-import org.apache.fop.fo.flow.table.TableCell;
-import org.apache.fop.fo.flow.table.TableColumn;
-import org.apache.fop.fo.flow.table.TableFooter;
-import org.apache.fop.fo.flow.table.TableHeader;
-import org.apache.fop.fo.flow.table.TableRow;
-
-final class FOEventRecorder extends FOEventHandler {
-
- private interface Event {
- void replay(FOEventHandler target);
- }
-
- private final List<Event> events = new ArrayList<Event>();
-
- public void replay(FOEventHandler target) {
- for (Event event : events) {
- event.replay(target);
- }
- }
-
- @Override
- public void startPageNumber(final PageNumber pagenum) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.startPageNumber(pagenum);
- }
- });
- }
-
- @Override
- public void endPageNumber(final PageNumber pagenum) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.endPageNumber(pagenum);
- }
- });
- }
-
- @Override
- public void startPageNumberCitation(final PageNumberCitation pageCite) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.startPageNumberCitation(pageCite);
- }
- });
- }
-
- @Override
- public void endPageNumberCitation(final PageNumberCitation pageCite) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.endPageNumberCitation(pageCite);
- }
- });
- }
-
- @Override
- public void startPageNumberCitationLast(final PageNumberCitationLast pageLast) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.startPageNumberCitationLast(pageLast);
- }
- });
- }
-
- @Override
- public void endPageNumberCitationLast(final PageNumberCitationLast pageLast) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.endPageNumberCitationLast(pageLast);
- }
- });
- }
-
- @Override
- public void startBlock(final Block bl) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.startBlock(bl);
- }
- });
- }
-
- @Override
- public void endBlock(final Block bl) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.endBlock(bl);
- }
- });
- }
-
- @Override
- public void startBlockContainer(final BlockContainer blc) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.startBlockContainer(blc);
- }
- });
- }
-
- @Override
- public void endBlockContainer(final BlockContainer blc) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.endBlockContainer(blc);
- }
- });
- }
-
- @Override
- public void startInline(final Inline inl) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.startInline(inl);
- }
- });
- }
-
- @Override
- public void endInline(final Inline inl) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.endInline(inl);
- }
- });
- }
-
- @Override
- public void startTable(final Table tbl) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.startTable(tbl);
- }
- });
- }
-
- @Override
- public void endTable(final Table tbl) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.endTable(tbl);
- }
- });
- }
-
- @Override
- public void startColumn(final TableColumn tc) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.startColumn(tc);
- }
- });
- }
-
- @Override
- public void endColumn(final TableColumn tc) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.endColumn(tc);
- }
- });
- }
-
- @Override
- public void startHeader(final TableHeader header) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.startHeader(header);
- }
- });
- }
-
- @Override
- public void endHeader(final TableHeader header) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.endHeader(header);
- }
- });
- }
-
- @Override
- public void startFooter(final TableFooter footer) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.startFooter(footer);
- }
- });
- }
-
- @Override
- public void endFooter(final TableFooter footer) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.endFooter(footer);
- }
- });
- }
-
- @Override
- public void startBody(final TableBody body) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.startBody(body);
- }
- });
- }
-
- @Override
- public void endBody(final TableBody body) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.endBody(body);
- }
- });
- }
-
- @Override
- public void startRow(final TableRow tr) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.startRow(tr);
- }
- });
- }
-
- @Override
- public void endRow(final TableRow tr) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.endRow(tr);
- }
- });
- }
-
- @Override
- public void startCell(final TableCell tc) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.startCell(tc);
- }
- });
- }
-
- @Override
- public void endCell(final TableCell tc) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.endCell(tc);
- }
- });
- }
-
- @Override
- public void startList(final ListBlock lb) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.startList(lb);
- }
- });
- }
-
- @Override
- public void endList(final ListBlock lb) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.endList(lb);
- }
- });
- }
-
- @Override
- public void startListItem(final ListItem li) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.startListItem(li);
- }
- });
- }
-
- @Override
- public void endListItem(final ListItem li) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.endListItem(li);
- }
- });
- }
-
- @Override
- public void startListLabel(final ListItemLabel listItemLabel) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.startListLabel(listItemLabel);
- }
- });
- }
-
- @Override
- public void endListLabel(final ListItemLabel listItemLabel) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.endListLabel(listItemLabel);
- }
- });
- }
-
- @Override
- public void startListBody(final ListItemBody listItemBody) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.startListBody(listItemBody);
- }
- });
- }
-
- @Override
- public void endListBody(final ListItemBody listItemBody) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.endListBody(listItemBody);
- }
- });
- }
-
- @Override
- public void startLink(final BasicLink basicLink) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.startLink(basicLink);
- }
- });
- }
-
- @Override
- public void endLink(final BasicLink basicLink) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.endLink(basicLink);
- }
- });
- }
-
- @Override
- public void image(final ExternalGraphic eg) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.image(eg);
- }
- });
- }
-
- @Override
- public void startInstreamForeignObject(final InstreamForeignObject ifo) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.startInstreamForeignObject(ifo);
- }
- });
- }
-
- @Override
- public void endInstreamForeignObject(final InstreamForeignObject ifo) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.endInstreamForeignObject(ifo);
- }
- });
- }
-
- @Override
- public void startFootnote(final Footnote footnote) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.startFootnote(footnote);
- }
- });
- }
-
- @Override
- public void endFootnote(final Footnote footnote) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.endFootnote(footnote);
- }
- });
- }
-
- @Override
- public void startFootnoteBody(final FootnoteBody body) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.startFootnoteBody(body);
- }
- });
- }
-
- @Override
- public void endFootnoteBody(final FootnoteBody body) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.endFootnoteBody(body);
- }
- });
- }
-
- @Override
- public void startLeader(final Leader l) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.startLeader(l);
- }
- });
- }
-
- @Override
- public void endLeader(final Leader l) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.endLeader(l);
- }
- });
- }
-
- @Override
- public void startWrapper(final Wrapper wrapper) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.startWrapper(wrapper);
- }
- });
- }
-
- @Override
- public void endWrapper(final Wrapper wrapper) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.endWrapper(wrapper);
- }
- });
- }
-
- @Override
- public void character(final Character c) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.character(c);
- }
- });
- }
-
- @Override
- public void characters(final FOText foText) {
- events.add(new Event() {
- public void replay(FOEventHandler target) {
- target.characters(foText);
- }
- });
- }
-
-}
diff --git a/src/java/org/apache/fop/accessibility/fo/StructureTreeEventTrigger.java b/src/java/org/apache/fop/accessibility/fo/StructureTreeEventTrigger.java
index 7e3ed0591..09a814ef5 100644
--- a/src/java/org/apache/fop/accessibility/fo/StructureTreeEventTrigger.java
+++ b/src/java/org/apache/fop/accessibility/fo/StructureTreeEventTrigger.java
@@ -20,6 +20,7 @@
package org.apache.fop.accessibility.fo;
import java.util.Locale;
+import java.util.Stack;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
@@ -30,6 +31,7 @@ import org.apache.fop.fo.FOEventHandler;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.FOText;
import org.apache.fop.fo.extensions.ExtensionElementMapping;
+import org.apache.fop.fo.extensions.InternalElementMapping;
import org.apache.fop.fo.flow.AbstractGraphics;
import org.apache.fop.fo.flow.BasicLink;
import org.apache.fop.fo.flow.Block;
@@ -55,6 +57,7 @@ import org.apache.fop.fo.flow.table.TableFooter;
import org.apache.fop.fo.flow.table.TableHeader;
import org.apache.fop.fo.flow.table.TableRow;
import org.apache.fop.fo.pagination.Flow;
+import org.apache.fop.fo.pagination.LayoutMasterSet;
import org.apache.fop.fo.pagination.PageSequence;
import org.apache.fop.fo.pagination.StaticContent;
import org.apache.fop.fo.properties.CommonAccessibilityHolder;
@@ -67,6 +70,12 @@ class StructureTreeEventTrigger extends FOEventHandler {
private StructureTreeEventHandler structureTreeEventHandler;
+ private LayoutMasterSet layoutMasterSet;
+
+ private final Stack<Table> tables = new Stack<Table>();
+
+ private final Stack<Boolean> inTableHeader = new Stack<Boolean>();
+
public StructureTreeEventTrigger(StructureTreeEventHandler structureTreeEventHandler) {
this.structureTreeEventHandler = structureTreeEventHandler;
}
@@ -81,6 +90,9 @@ class StructureTreeEventTrigger extends FOEventHandler {
@Override
public void startPageSequence(PageSequence pageSeq) {
+ if (layoutMasterSet == null) {
+ layoutMasterSet = pageSeq.getRoot().getLayoutMasterSet();
+ }
Locale locale = null;
if (pageSeq.getLanguage() != null) {
if (pageSeq.getCountry() != null) {
@@ -129,8 +141,27 @@ class StructureTreeEventTrigger extends FOEventHandler {
}
@Override
+ public void startStatic(StaticContent staticContent) {
+ AttributesImpl flowName = createFlowNameAttribute(staticContent.getFlowName());
+ startElement(staticContent, flowName);
+ }
+
+ private AttributesImpl createFlowNameAttribute(String flowName) {
+ String regionName = layoutMasterSet.getDefaultRegionNameFor(flowName);
+ AttributesImpl attribute = new AttributesImpl();
+ addNoNamespaceAttribute(attribute, Flow.FLOW_NAME, regionName);
+ return attribute;
+ }
+
+ @Override
+ public void endStatic(StaticContent staticContent) {
+ endElement(staticContent);
+ }
+
+ @Override
public void startFlow(Flow fl) {
- startElement(fl);
+ AttributesImpl flowName = createFlowNameAttribute(fl.getFlowName());
+ startElement(fl, flowName);
}
@Override
@@ -170,42 +201,51 @@ class StructureTreeEventTrigger extends FOEventHandler {
@Override
public void startTable(Table tbl) {
+ tables.push(tbl);
startElement(tbl);
}
@Override
public void endTable(Table tbl) {
endElement(tbl);
+ tables.pop();
}
@Override
public void startHeader(TableHeader header) {
+ inTableHeader.push(Boolean.TRUE);
startElement(header);
}
@Override
public void endHeader(TableHeader header) {
endElement(header);
+ inTableHeader.pop();
}
@Override
public void startFooter(TableFooter footer) {
+ // TODO Shouldn't it be true?
+ inTableHeader.push(Boolean.FALSE);
startElement(footer);
}
@Override
public void endFooter(TableFooter footer) {
endElement(footer);
+ inTableHeader.pop();
}
@Override
public void startBody(TableBody body) {
+ inTableHeader.push(Boolean.FALSE);
startElement(body);
}
@Override
public void endBody(TableBody body) {
endElement(body);
+ inTableHeader.pop();
}
@Override
@@ -223,6 +263,24 @@ class StructureTreeEventTrigger extends FOEventHandler {
AttributesImpl attributes = new AttributesImpl();
addSpanAttribute(attributes, "number-columns-spanned", tc.getNumberColumnsSpanned());
addSpanAttribute(attributes, "number-rows-spanned", tc.getNumberRowsSpanned());
+ boolean rowHeader = inTableHeader.peek();
+ boolean columnHeader = tables.peek().getColumn(tc.getColumnNumber() - 1).isHeader();
+ if (rowHeader || columnHeader) {
+ final String th = "TH";
+ String role = tc.getCommonAccessibility().getRole();
+ /* Do not override a custom role */
+ if (role == null) {
+ role = th;
+ addNoNamespaceAttribute(attributes, "role", th);
+ }
+ if (role.equals(th)) {
+ if (columnHeader) {
+ String scope = rowHeader ? "Both" : "Row";
+ addAttribute(attributes, InternalElementMapping.URI, InternalElementMapping.SCOPE,
+ InternalElementMapping.STANDARD_PREFIX, scope);
+ }
+ }
+ }
startElement(tc, attributes);
}
@@ -278,16 +336,6 @@ class StructureTreeEventTrigger extends FOEventHandler {
}
@Override
- public void startStatic(StaticContent staticContent) {
- startElement(staticContent);
- }
-
- @Override
- public void endStatic(StaticContent statisContent) {
- endElement(statisContent);
- }
-
- @Override
public void startLink(BasicLink basicLink) {
startElementWithID(basicLink);
}
diff --git a/src/java/org/apache/fop/afp/AFPStreamer.java b/src/java/org/apache/fop/afp/AFPStreamer.java
index fb2b282f6..5e6b5a79e 100644
--- a/src/java/org/apache/fop/afp/AFPStreamer.java
+++ b/src/java/org/apache/fop/afp/AFPStreamer.java
@@ -32,10 +32,11 @@ import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.xmlgraphics.io.TempResourceURIGenerator;
+
import org.apache.fop.afp.modca.ResourceGroup;
import org.apache.fop.afp.modca.StreamedResourceGroup;
import org.apache.fop.apps.io.InternalResourceResolver;
-import org.apache.fop.apps.io.TempResourceURIGenerator;
/**
* Manages the streaming of the AFP output
diff --git a/src/java/org/apache/fop/afp/DataStream.java b/src/java/org/apache/fop/afp/DataStream.java
index 2794ae932..272c000bd 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;
@@ -85,12 +85,9 @@ public class DataStream {
/** The current page */
private AbstractPageObject currentPage = null;
- /** Sequence number for TLE's.*/
- private int tleSequence = 0;
-
/** 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 +541,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]);
}
}
@@ -564,11 +563,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 +576,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);
+
} else {
- currentPageGroup.createTagLogicalElement(name, value);
+ currentPageGroup.createTagLogicalElement(tleState);
}
}
@@ -632,7 +634,7 @@ public class DataStream {
*/
public void startPageGroup() throws IOException {
endPageGroup();
- this.currentPageGroup = factory.createPageGroup(tleSequence);
+ this.currentPageGroup = factory.createPageGroup();
}
/**
@@ -643,7 +645,6 @@ public class DataStream {
public void endPageGroup() throws IOException {
if (currentPageGroup != null) {
currentPageGroup.endPageGroup();
- tleSequence = currentPageGroup.getTleSequence();
document.addPageGroup(currentPageGroup);
currentPageGroup = null;
}
diff --git a/src/java/org/apache/fop/afp/Factory.java b/src/java/org/apache/fop/afp/Factory.java
index ef68a22fb..f3e75c1af 100644
--- a/src/java/org/apache/fop/afp/Factory.java
+++ b/src/java/org/apache/fop/afp/Factory.java
@@ -214,13 +214,12 @@ public class Factory {
/**
* Creates a new MO:DCA {@link PageGroup}
- * @param tleSequence current start tle sequence number within stream
* @return a new {@link PageGroup}
*/
- public PageGroup createPageGroup(int tleSequence) {
+ public PageGroup createPageGroup() {
String name = PAGE_GROUP_NAME_PREFIX
+ StringUtils.lpad(String.valueOf(++pageGroupCount), '0', 5);
- return new PageGroup(this, name, tleSequence);
+ return new PageGroup(this, name);
}
/**
@@ -374,13 +373,11 @@ public class Factory {
/**
* Creates a MO:DCA {@link TagLogicalElement}
*
- * @param name name of the element
- * @param value value of the element
- * @param tleSequence current start tle sequence number within stream*
+ * @param state the attribute state for the TLE
* @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) {
+ TagLogicalElement tle = new TagLogicalElement(state);
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..f429af28d 100644
--- a/src/java/org/apache/fop/afp/modca/AbstractPageObject.java
+++ b/src/java/org/apache/fop/afp/modca/AbstractPageObject.java
@@ -223,19 +223,15 @@ 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
*/
- public void createTagLogicalElement(String name, String value, int tleID) {
- TagLogicalElement tle = new TagLogicalElement(name, value, tleID);
+ public void createTagLogicalElement(TagLogicalElement.State state) {
+ TagLogicalElement tle = new TagLogicalElement(state);
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..7d472a2cd 100644
--- a/src/java/org/apache/fop/afp/modca/PageGroup.java
+++ b/src/java/org/apache/fop/afp/modca/PageGroup.java
@@ -36,35 +36,25 @@ import org.apache.fop.afp.Factory;
public class PageGroup extends AbstractResourceEnvironmentGroupContainer {
/**
- * Sequence number for TLE's.
- */
- private int tleSequence = 0;
-
- /**
* Constructor for the PageGroup.
*
* @param factory the resource manager
* @param name the name of the page group
- * @param tleSequence current start tle sequence number within stream
*/
- public PageGroup(Factory factory, String name, int tleSequence) {
+ public PageGroup(Factory factory, String name) {
super(factory, name);
- this.tleSequence = tleSequence;
}
/**
* 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);
if (!getTagLogicalElements().contains(tle)) {
getTagLogicalElements().add(tle);
- tleSequence++;
}
}
@@ -93,9 +83,4 @@ public class PageGroup extends AbstractResourceEnvironmentGroupContainer {
public String toString() {
return this.getName();
}
-
- /** @return the TLE sequence number */
- public int getTleSequence() {
- return 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..9ae88b46f 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,42 +50,30 @@ 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;
-
- /**
- * Sequence of TLE within document
- */
- private int tleID;
+ private State state;
/**
* 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 tleID unique identifier for TLE within AFP stream
+ * @param state the state of the tag logical element
*/
- public TagLogicalElement(String name, String value, int tleID) {
- this.name = name;
- this.value = value;
- this.tleID = tleID;
+
+ public TagLogicalElement(State state) {
+ this.state = state;
}
- /**
- * 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,9 +89,9 @@ public class TagLogicalElement extends AbstractTripletStructuredObject {
setFullyQualifiedName(
FullyQualifiedNameTriplet.TYPE_ATTRIBUTE_GID,
FullyQualifiedNameTriplet.FORMAT_CHARSTR,
- name);
- setAttributeValue(value);
- setAttributeQualifier(tleID, 1);
+ state.key);
+ setAttributeValue(state.value);
+ setEncoding(state.encoding);
byte[] data = new byte[SF_HEADER_LENGTH];
copySF(data, Type.ATTRIBUTE, Category.PROCESS_ELEMENT);
@@ -115,4 +104,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.
- * <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) {
- 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/afp/util/AFPResourceAccessor.java b/src/java/org/apache/fop/afp/util/AFPResourceAccessor.java
index 46b09be21..f760e6c7c 100644
--- a/src/java/org/apache/fop/afp/util/AFPResourceAccessor.java
+++ b/src/java/org/apache/fop/afp/util/AFPResourceAccessor.java
@@ -106,7 +106,7 @@ public final class AFPResourceAccessor {
URI resolveURI(String uri);
}
- private final class NullBaseURIResolver implements URIResolver {
+ private static final class NullBaseURIResolver implements URIResolver {
public URI resolveURI(URI uri) {
return uri;
diff --git a/src/java/org/apache/fop/apps/EnvironmentProfile.java b/src/java/org/apache/fop/apps/EnvironmentProfile.java
index c964120e3..1a585353e 100644
--- a/src/java/org/apache/fop/apps/EnvironmentProfile.java
+++ b/src/java/org/apache/fop/apps/EnvironmentProfile.java
@@ -21,7 +21,9 @@ package org.apache.fop.apps;
import java.net.URI;
-import org.apache.fop.apps.io.ResourceResolver;
+import org.apache.xmlgraphics.image.loader.impl.AbstractImageSessionContext.FallbackResolver;
+import org.apache.xmlgraphics.io.ResourceResolver;
+
import org.apache.fop.fonts.FontManager;
/**
@@ -52,4 +54,7 @@ public interface EnvironmentProfile {
* @return the default base URI
*/
URI getDefaultBaseURI();
+
+ /** @see FopFactoryConfig#getFallbackResolver() */
+ FallbackResolver getFallbackResolver();
}
diff --git a/src/java/org/apache/fop/apps/EnvironmentalProfileFactory.java b/src/java/org/apache/fop/apps/EnvironmentalProfileFactory.java
index 9ba7632d2..922ecff4b 100644
--- a/src/java/org/apache/fop/apps/EnvironmentalProfileFactory.java
+++ b/src/java/org/apache/fop/apps/EnvironmentalProfileFactory.java
@@ -21,8 +21,12 @@ package org.apache.fop.apps;
import java.net.URI;
+import org.apache.xmlgraphics.image.loader.impl.AbstractImageSessionContext.FallbackResolver;
+import org.apache.xmlgraphics.image.loader.impl.AbstractImageSessionContext.RestrictedFallbackResolver;
+import org.apache.xmlgraphics.image.loader.impl.AbstractImageSessionContext.UnrestrictedFallbackResolver;
+import org.apache.xmlgraphics.io.ResourceResolver;
+
import org.apache.fop.apps.io.InternalResourceResolver;
-import org.apache.fop.apps.io.ResourceResolver;
import org.apache.fop.apps.io.ResourceResolverFactory;
import org.apache.fop.fonts.FontCacheManager;
import org.apache.fop.fonts.FontCacheManagerFactory;
@@ -51,7 +55,8 @@ public final class EnvironmentalProfileFactory {
return new Profile(defaultBaseUri, resourceResolver,
createFontManager(defaultBaseUri, resourceResolver,
FontDetectorFactory.createDefault(),
- FontCacheManagerFactory.createDefault()));
+ FontCacheManagerFactory.createDefault()),
+ new UnrestrictedFallbackResolver());
}
/**
@@ -67,7 +72,8 @@ public final class EnvironmentalProfileFactory {
return new Profile(defaultBaseUri, resourceResolver,
createFontManager(defaultBaseUri, resourceResolver,
FontDetectorFactory.createDisabled(),
- FontCacheManagerFactory.createDisabled()));
+ FontCacheManagerFactory.createDisabled()),
+ new RestrictedFallbackResolver());
}
private static final class Profile implements EnvironmentProfile {
@@ -78,8 +84,10 @@ public final class EnvironmentalProfileFactory {
private final URI defaultBaseURI;
+ private final FallbackResolver fallbackResolver;
+
private Profile(URI defaultBaseURI, ResourceResolver resourceResolver,
- FontManager fontManager) {
+ FontManager fontManager, FallbackResolver fallbackResolver) {
if (defaultBaseURI == null) {
throw new IllegalArgumentException("Default base URI must not be null");
}
@@ -92,6 +100,7 @@ public final class EnvironmentalProfileFactory {
this.defaultBaseURI = defaultBaseURI;
this.resourceResolver = resourceResolver;
this.fontManager = fontManager;
+ this.fallbackResolver = fallbackResolver;
}
public ResourceResolver getResourceResolver() {
@@ -105,6 +114,10 @@ public final class EnvironmentalProfileFactory {
public URI getDefaultBaseURI() {
return defaultBaseURI;
}
+
+ public FallbackResolver getFallbackResolver() {
+ return fallbackResolver;
+ }
}
private static FontManager createFontManager(URI defaultBaseUri, ResourceResolver resourceResolver,
diff --git a/src/java/org/apache/fop/apps/FOUserAgent.java b/src/java/org/apache/fop/apps/FOUserAgent.java
index 0ed5b7228..68064343e 100644
--- a/src/java/org/apache/fop/apps/FOUserAgent.java
+++ b/src/java/org/apache/fop/apps/FOUserAgent.java
@@ -131,21 +131,7 @@ public class FOUserAgent {
/** Set of keywords applicable to this document. */
protected String keywords = null;
- private ImageSessionContext imageSessionContext = new AbstractImageSessionContext() {
-
- public ImageContext getParentContext() {
- return factory;
- }
-
- public float getTargetResolution() {
- return FOUserAgent.this.getTargetResolution();
- }
-
- public Source resolveURI(String uri) {
- return FOUserAgent.this.resolveURI(uri);
- }
-
- };
+ private final ImageSessionContext imageSessionContext;
/**
* Main constructor. <b>This constructor should not be called directly. Please use the
@@ -154,11 +140,25 @@ public class FOUserAgent {
* @param resourceResolver the resolver used to acquire resources
* @see org.apache.fop.apps.FopFactory
*/
- FOUserAgent(FopFactory factory, InternalResourceResolver resourceResolver) {
+ FOUserAgent(final FopFactory factory, InternalResourceResolver resourceResolver) {
this.factory = factory;
this.resourceResolver = resourceResolver;
setTargetResolution(factory.getTargetResolution());
setAccessibility(factory.isAccessibilityEnabled());
+ imageSessionContext = new AbstractImageSessionContext(factory.getFallbackResolver()) {
+
+ public ImageContext getParentContext() {
+ return factory;
+ }
+
+ public float getTargetResolution() {
+ return FOUserAgent.this.getTargetResolution();
+ }
+
+ public Source resolveURI(String uri) {
+ return FOUserAgent.this.resolveURI(uri);
+ }
+ };
}
/**
diff --git a/src/java/org/apache/fop/apps/FopConfParser.java b/src/java/org/apache/fop/apps/FopConfParser.java
index c6e3dbd19..b4918ef30 100644
--- a/src/java/org/apache/fop/apps/FopConfParser.java
+++ b/src/java/org/apache/fop/apps/FopConfParser.java
@@ -39,9 +39,9 @@ import org.apache.commons.logging.LogFactory;
import org.apache.xmlgraphics.image.loader.spi.ImageImplRegistry;
import org.apache.xmlgraphics.image.loader.util.Penalty;
+import org.apache.xmlgraphics.io.ResourceResolver;
import org.apache.fop.apps.io.InternalResourceResolver;
-import org.apache.fop.apps.io.ResourceResolver;
import org.apache.fop.apps.io.ResourceResolverFactory;
import org.apache.fop.fonts.FontManagerConfigurator;
import org.apache.fop.hyphenation.HyphenationTreeCache;
diff --git a/src/java/org/apache/fop/apps/FopFactory.java b/src/java/org/apache/fop/apps/FopFactory.java
index 80c957f9f..6bc744b7e 100644
--- a/src/java/org/apache/fop/apps/FopFactory.java
+++ b/src/java/org/apache/fop/apps/FopFactory.java
@@ -36,6 +36,7 @@ import org.apache.commons.logging.LogFactory;
import org.apache.xmlgraphics.image.loader.ImageContext;
import org.apache.xmlgraphics.image.loader.ImageManager;
+import org.apache.xmlgraphics.image.loader.impl.AbstractImageSessionContext.FallbackResolver;
import org.apache.xmlgraphics.util.UnitConv;
import org.apache.fop.apps.io.InternalResourceResolver;
@@ -418,6 +419,11 @@ public final class FopFactory implements ImageContext {
return config.getFontManager();
}
+ /** @see FopFactoryConfig#getFallbackResolver() */
+ FallbackResolver getFallbackResolver() {
+ return config.getFallbackResolver();
+ }
+
/**
* Returns the color space cache for this instance.
* <p>
diff --git a/src/java/org/apache/fop/apps/FopFactoryBuilder.java b/src/java/org/apache/fop/apps/FopFactoryBuilder.java
index cfc47496c..b1fd5e979 100644
--- a/src/java/org/apache/fop/apps/FopFactoryBuilder.java
+++ b/src/java/org/apache/fop/apps/FopFactoryBuilder.java
@@ -30,8 +30,9 @@ import org.apache.avalon.framework.configuration.Configuration;
import org.apache.xmlgraphics.image.loader.ImageContext;
import org.apache.xmlgraphics.image.loader.ImageManager;
+import org.apache.xmlgraphics.image.loader.impl.AbstractImageSessionContext.FallbackResolver;
+import org.apache.xmlgraphics.io.ResourceResolver;
-import org.apache.fop.apps.io.ResourceResolver;
import org.apache.fop.apps.io.ResourceResolverFactory;
import org.apache.fop.fonts.FontManager;
import org.apache.fop.layoutmgr.LayoutManagerMaker;
@@ -464,6 +465,10 @@ public final class FopFactoryBuilder {
public Map<String, String> getHyphenationPatternNames() {
return hyphPatNames;
}
+
+ public FallbackResolver getFallbackResolver() {
+ return enviro.getFallbackResolver();
+ }
}
private interface FopFactoryConfigBuilder {
diff --git a/src/java/org/apache/fop/apps/FopFactoryConfig.java b/src/java/org/apache/fop/apps/FopFactoryConfig.java
index 60e8d98e7..d3ea3127f 100644
--- a/src/java/org/apache/fop/apps/FopFactoryConfig.java
+++ b/src/java/org/apache/fop/apps/FopFactoryConfig.java
@@ -26,8 +26,9 @@ import java.util.Set;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.xmlgraphics.image.loader.ImageManager;
+import org.apache.xmlgraphics.image.loader.impl.AbstractImageSessionContext.FallbackResolver;
+import org.apache.xmlgraphics.io.ResourceResolver;
-import org.apache.fop.apps.io.ResourceResolver;
import org.apache.fop.fonts.FontManager;
import org.apache.fop.layoutmgr.LayoutManagerMaker;
@@ -163,4 +164,11 @@ public interface FopFactoryConfig {
/** @return the hyphenation pattern names */
Map<String, String> getHyphenationPatternNames();
+
+ /**
+ * Controls the mechanisms that are used in the event that {@link javax.xml.transform.Source}
+ * used for resources couldn't be read.
+ * @return the fallback resolver
+ */
+ FallbackResolver getFallbackResolver();
}
diff --git a/src/java/org/apache/fop/apps/io/InternalResourceResolver.java b/src/java/org/apache/fop/apps/io/InternalResourceResolver.java
index 4d664c8f5..af0a26478 100644
--- a/src/java/org/apache/fop/apps/io/InternalResourceResolver.java
+++ b/src/java/org/apache/fop/apps/io/InternalResourceResolver.java
@@ -29,12 +29,14 @@ import javax.xml.transform.Source;
import javax.xml.transform.TransformerException;
import javax.xml.transform.stream.StreamSource;
+import org.apache.xmlgraphics.io.Resource;
+import org.apache.xmlgraphics.io.ResourceResolver;
import org.apache.xmlgraphics.util.uri.DataURIResolver;
/**
* This object holds the base URI from which to resolve URIs against as well as the resolver for
* resource acquisition. It also does some URI sanitization of common URI syntactical errors. This
- * class takes in a {@link org.apache.fop.apps.io.ResourceResolver} and delegates all relevant
+ * class takes in a {@link org.apache.xmlgraphics.io.ResourceResolver} and delegates all relevant
* URIs to it.
*/
public class InternalResourceResolver {
diff --git a/src/java/org/apache/fop/apps/io/ResourceResolver.java b/src/java/org/apache/fop/apps/io/ResourceResolver.java
deleted file mode 100644
index a3a9cf0c3..000000000
--- a/src/java/org/apache/fop/apps/io/ResourceResolver.java
+++ /dev/null
@@ -1,51 +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.apps.io;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.net.URI;
-
-/**
- * Implementations of this resource resolver allow FOP users to control the URI resolution
- * mechanism. All resource and output stream acquisition goes through this when its implementation
- * is given to the {@link org.apache.fop.apps.EnvironmentProfile}.
- */
-public interface ResourceResolver {
-
- /**
- * Get a resource given the URI pointing to said resource.
- *
- * @param uri the resource URI
- * @return the resource
- * @throws IOException if an I/O error occured during resource acquisition
- */
- Resource getResource(URI uri) throws IOException;
-
- /**
- * Gets an output stream of a given URI.
- *
- * @param uri the output stream URI
- * @return the output stream
- * @throws IOException if an I/O error occured while creating an output stream
- */
- OutputStream getOutputStream(URI uri) throws IOException;
-
-}
diff --git a/src/java/org/apache/fop/apps/io/ResourceResolverFactory.java b/src/java/org/apache/fop/apps/io/ResourceResolverFactory.java
index 72eac456d..cdc9438b9 100644
--- a/src/java/org/apache/fop/apps/io/ResourceResolverFactory.java
+++ b/src/java/org/apache/fop/apps/io/ResourceResolverFactory.java
@@ -28,6 +28,11 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
+import org.apache.xmlgraphics.io.Resource;
+import org.apache.xmlgraphics.io.ResourceResolver;
+import org.apache.xmlgraphics.io.TempResourceResolver;
+import org.apache.xmlgraphics.io.TempResourceURIGenerator;
+
/**
* A factory class for {@link ResourceResolver}s.
*/
@@ -70,10 +75,10 @@ public final class ResourceResolverFactory {
}
/**
- * Creates a temporary-resource-schema aware resource resolver. Temporary resource URIs are
+ * Creates a temporary-resource-scheme aware resource resolver. Temporary resource URIs are
* created by {@link TempResourceURIGenerator}.
*
- * @param tempResourceResolver the temporary-resource-schema resolver to use
+ * @param tempResourceResolver the temporary-resource-scheme resolver to use
* @param defaultResourceResolver the default resource resolver to use
* @return the ressource resolver
*/
@@ -84,17 +89,17 @@ public final class ResourceResolverFactory {
}
/**
- * This creates the builder class for binding URI schemas to implementations of
- * {@link ResourceResolver}. This allows users to define their own URI schemas such that they
+ * This creates the builder class for binding URI schemes to implementations of
+ * {@link ResourceResolver}. This allows users to define their own URI schemes such that they
* have finer control over the acquisition of resources.
*
* @param defaultResolver the default resource resolver that should be used in the event that
- * none of the other registered resolvers match the schema
- * @return the schema aware {@link ResourceResolver} builder
+ * none of the other registered resolvers match the scheme
+ * @return the scheme aware {@link ResourceResolver} builder
*/
- public static SchemaAwareResourceResolverBuilder createSchemaAwareResourceResolverBuilder(
+ public static SchemeAwareResourceResolverBuilder createSchemeAwareResourceResolverBuilder(
ResourceResolver defaultResolver) {
- return new SchemaAwareResourceResolverBuilderImpl(defaultResolver);
+ return new SchemeAwareResourceResolverBuilderImpl(defaultResolver);
}
private static final class DefaultResourceResolver implements ResourceResolver {
@@ -132,13 +137,13 @@ public final class ResourceResolverFactory {
this.defaultResourceResolver = defaultResourceResolver;
}
- private static boolean isTempUri(URI uri) {
- return TempResourceURIGenerator.isTempUri(uri);
+ private static boolean isTempURI(URI uri) {
+ return TempResourceURIGenerator.isTempURI(uri);
}
/** {@inheritDoc} */
public Resource getResource(URI uri) throws IOException {
- if (isTempUri(uri)) {
+ if (isTempURI(uri)) {
return tempResourceResolver.getResource(uri.getPath());
} else {
return defaultResourceResolver.getResource(uri);
@@ -147,7 +152,7 @@ public final class ResourceResolverFactory {
/** {@inheritDoc} */
public OutputStream getOutputStream(URI uri) throws IOException {
- if (isTempUri(uri)) {
+ if (isTempURI(uri)) {
return tempResourceResolver.getOutputStream(uri.getPath());
} else {
return defaultResourceResolver.getOutputStream(uri);
@@ -188,23 +193,23 @@ public final class ResourceResolverFactory {
}
}
- private static final class SchemaAwareResourceResolver implements ResourceResolver {
+ private static final class SchemeAwareResourceResolver implements ResourceResolver {
- private final Map<String, ResourceResolver> schemaHandlingResourceResolvers;
+ private final Map<String, ResourceResolver> schemeHandlingResourceResolvers;
private final ResourceResolver defaultResolver;
- private SchemaAwareResourceResolver(
- Map<String, ResourceResolver> schemaHandlingResourceResolvers,
+ private SchemeAwareResourceResolver(
+ Map<String, ResourceResolver> schemEHandlingResourceResolvers,
ResourceResolver defaultResolver) {
- this.schemaHandlingResourceResolvers = schemaHandlingResourceResolvers;
+ this.schemeHandlingResourceResolvers = schemEHandlingResourceResolvers;
this.defaultResolver = defaultResolver;
}
- private ResourceResolver getResourceResolverForSchema(URI uri) {
- String schema = uri.getScheme();
- if (schemaHandlingResourceResolvers.containsKey(schema)) {
- return schemaHandlingResourceResolvers.get(schema);
+ private ResourceResolver getResourceResolverForScheme(URI uri) {
+ String scheme = uri.getScheme();
+ if (schemeHandlingResourceResolvers.containsKey(scheme)) {
+ return schemeHandlingResourceResolvers.get(scheme);
} else {
return defaultResolver;
}
@@ -212,58 +217,58 @@ public final class ResourceResolverFactory {
/** {@inheritDoc} */
public Resource getResource(URI uri) throws IOException {
- return getResourceResolverForSchema(uri).getResource(uri);
+ return getResourceResolverForScheme(uri).getResource(uri);
}
/** {@inheritDoc} */
public OutputStream getOutputStream(URI uri) throws IOException {
- return getResourceResolverForSchema(uri).getOutputStream(uri);
+ return getResourceResolverForScheme(uri).getOutputStream(uri);
}
}
/**
* Implementations of this interface will be builders for {@link ResourceResolver}, they bind
- * URI schemas to their respective resolver. This gives users more control over the mechanisms
+ * URI schemes to their respective resolver. This gives users more control over the mechanisms
* by which URIs are resolved.
* <p>
* Here is an example of how this could be used:
* </p>
* <p><code>
- * SchemaAwareResourceResolverBuilder builder
- * = ResourceResolverFactory.createSchemaAwareResourceResolverBuilder(defaultResolver);
- * builder.registerResourceResolverForSchema("test", testResolver);
- * builder.registerResourceResolverForSchema("anotherTest", test2Resolver);
+ * SchemeAwareResourceResolverBuilder builder
+ * = ResourceResolverFactory.createSchemeAwareResourceResolverBuilder(defaultResolver);
+ * builder.registerResourceResolverForScheme("test", testResolver);
+ * builder.registerResourceResolverForScheme("anotherTest", test2Resolver);
* ResourceResolver resolver = builder.build();
* </code></p>
* This will result in all URIs for the form "test:///..." will be resolved using the
* <code>testResolver</code> object; URIs of the form "anotherTest:///..." will be resolved
* using <code>test2Resolver</code>; all other URIs will be resolved from the defaultResolver.
*/
- public interface SchemaAwareResourceResolverBuilder {
+ public interface SchemeAwareResourceResolverBuilder {
/**
- * Register a schema with its respective {@link ResourceResolver}. This resolver will be
- * used as the only resolver for the specified schema.
+ * Register a scheme with its respective {@link ResourceResolver}. This resolver will be
+ * used as the only resolver for the specified scheme.
*
- * @param schema the schema to be used with the given resolver
+ * @param scheme the scheme to be used with the given resolver
* @param resourceResolver the resource resolver
*/
- void registerResourceResolverForSchema(String schema, ResourceResolver resourceResolver);
+ void registerResourceResolverForScheme(String scheme, ResourceResolver resourceResolver);
/**
* Builds a {@link ResourceResolver} that will delegate to the respective resource resolver
- * when a registered URI schema is given
+ * when a registered URI scheme is given
*
- * @return a resolver that delegates to the appropriate schema resolver
+ * @return a resolver that delegates to the appropriate scheme resolver
*/
ResourceResolver build();
}
- private static final class CompletedSchemaAwareResourceResolverBuilder
- implements SchemaAwareResourceResolverBuilder {
+ private static final class CompletedSchemeAwareResourceResolverBuilder
+ implements SchemeAwareResourceResolverBuilder {
- private static final SchemaAwareResourceResolverBuilder INSTANCE
- = new CompletedSchemaAwareResourceResolverBuilder();
+ private static final SchemeAwareResourceResolverBuilder INSTANCE
+ = new CompletedSchemeAwareResourceResolverBuilder();
/** {@inheritDoc} */
public ResourceResolver build() {
@@ -271,59 +276,58 @@ public final class ResourceResolverFactory {
}
/** {@inheritDoc} */
- public void registerResourceResolverForSchema(String schema,
+ public void registerResourceResolverForScheme(String scheme,
ResourceResolver resourceResolver) {
throw new IllegalStateException("Resource resolver already built");
}
}
- private static final class ActiveSchemaAwareResourceResolverBuilder
- implements SchemaAwareResourceResolverBuilder {
+ private static final class ActiveSchemeAwareResourceResolverBuilder
+ implements SchemeAwareResourceResolverBuilder {
- private final Map<String, ResourceResolver> schemaHandlingResourceResolvers
+ private final Map<String, ResourceResolver> schemeHandlingResourceResolvers
= new HashMap<String, ResourceResolver>();
private final ResourceResolver defaultResolver;
- private ActiveSchemaAwareResourceResolverBuilder(ResourceResolver defaultResolver) {
+ private ActiveSchemeAwareResourceResolverBuilder(ResourceResolver defaultResolver) {
this.defaultResolver = defaultResolver;
}
/** {@inheritDoc} */
- public void registerResourceResolverForSchema(String schema,
+ public void registerResourceResolverForScheme(String scheme,
ResourceResolver resourceResolver) {
- schemaHandlingResourceResolvers.put(schema, resourceResolver);
+ schemeHandlingResourceResolvers.put(scheme, resourceResolver);
}
/** {@inheritDoc} */
public ResourceResolver build() {
- return new SchemaAwareResourceResolver(
- Collections.unmodifiableMap(schemaHandlingResourceResolvers), defaultResolver);
+ return new SchemeAwareResourceResolver(
+ Collections.unmodifiableMap(schemeHandlingResourceResolvers), defaultResolver);
}
}
- private static final class SchemaAwareResourceResolverBuilderImpl
- implements SchemaAwareResourceResolverBuilder {
+ private static final class SchemeAwareResourceResolverBuilderImpl
+ implements SchemeAwareResourceResolverBuilder {
- private SchemaAwareResourceResolverBuilder delegate;
+ private SchemeAwareResourceResolverBuilder delegate;
- private SchemaAwareResourceResolverBuilderImpl(ResourceResolver defaultResolver) {
- this.delegate = new ActiveSchemaAwareResourceResolverBuilder(defaultResolver);
+ private SchemeAwareResourceResolverBuilderImpl(ResourceResolver defaultResolver) {
+ this.delegate = new ActiveSchemeAwareResourceResolverBuilder(defaultResolver);
}
/** {@inheritDoc} */
- public void registerResourceResolverForSchema(String schema,
+ public void registerResourceResolverForScheme(String scheme,
ResourceResolver resourceResolver) {
- delegate.registerResourceResolverForSchema(schema, resourceResolver);
+ delegate.registerResourceResolverForScheme(scheme, resourceResolver);
}
/** {@inheritDoc} */
public ResourceResolver build() {
ResourceResolver resourceResolver = delegate.build();
- delegate = CompletedSchemaAwareResourceResolverBuilder.INSTANCE;
+ delegate = CompletedSchemeAwareResourceResolverBuilder.INSTANCE;
return resourceResolver;
}
}
-
}
diff --git a/src/java/org/apache/fop/apps/io/TempResourceResolver.java b/src/java/org/apache/fop/apps/io/TempResourceResolver.java
deleted file mode 100644
index cf307fab6..000000000
--- a/src/java/org/apache/fop/apps/io/TempResourceResolver.java
+++ /dev/null
@@ -1,48 +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.apps.io;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * Implementations of this interface resolve URIs for temporary files used by FOP. The temporary-
- * resource URI scheme comes from {@link TempResourceURIGenerator#TMP_SCHEMA}.
- */
-public interface TempResourceResolver {
-
- /**
- * Get a temporary-resource given the URI pointing to said resource.
- *
- * @param uri the resource URI
- * @return the resource
- * @throws IOException if an I/O error occured during resource acquisition
- */
- Resource getResource(String uri) throws IOException;
-
- /**
- * Gets an temporary-output stream of a given URI.
- *
- * @param uri the output stream URI
- * @return the output stream
- * @throws IOException if an I/O error occured while creating an output stream
- */
- OutputStream getOutputStream(String uri) throws IOException;
-}
diff --git a/src/java/org/apache/fop/apps/io/TempResourceURIGenerator.java b/src/java/org/apache/fop/apps/io/TempResourceURIGenerator.java
deleted file mode 100644
index 8e6c3606c..000000000
--- a/src/java/org/apache/fop/apps/io/TempResourceURIGenerator.java
+++ /dev/null
@@ -1,57 +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.
- */
-
-package org.apache.fop.apps.io;
-
-import java.net.URI;
-import java.util.concurrent.atomic.AtomicLong;
-
-/**
- * Creates a URI for any temporary resource used within FOP.
- */
-public final class TempResourceURIGenerator {
-
- public static final String TMP_SCHEMA = "tmp";
-
- private final String tempURIPrefix;
-
- private final AtomicLong counter;
-
- /**
- * @param uriPrefix a prefix used to name the unique URI
- */
- public TempResourceURIGenerator(String uriPrefix) {
- counter = new AtomicLong();
- tempURIPrefix = URI.create(TMP_SCHEMA + ":///" + uriPrefix).toASCIIString();
- }
-
- /**
- * Generate a unique URI for a temporary resource
- * @return the URI
- */
- public URI generate() {
- return URI.create(tempURIPrefix + getUniqueId());
- }
-
- private String getUniqueId() {
- return Long.toHexString(counter.getAndIncrement());
- }
-
- public static boolean isTempUri(URI uri) {
- return TMP_SCHEMA.equals(uri.getScheme());
- }
-}
diff --git a/src/java/org/apache/fop/area/CachedRenderPagesModel.java b/src/java/org/apache/fop/area/CachedRenderPagesModel.java
index fcc82cdd3..0837e5ae5 100644
--- a/src/java/org/apache/fop/area/CachedRenderPagesModel.java
+++ b/src/java/org/apache/fop/area/CachedRenderPagesModel.java
@@ -35,9 +35,10 @@ import org.xml.sax.SAXException;
import org.apache.commons.io.IOUtils;
+import org.apache.xmlgraphics.io.TempResourceURIGenerator;
+
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
-import org.apache.fop.apps.io.TempResourceURIGenerator;
import org.apache.fop.fonts.FontInfo;
/**
diff --git a/src/java/org/apache/fop/area/PageViewport.java b/src/java/org/apache/fop/area/PageViewport.java
index f38964ebc..d1250238a 100644
--- a/src/java/org/apache/fop/area/PageViewport.java
+++ b/src/java/org/apache/fop/area/PageViewport.java
@@ -34,6 +34,10 @@ import org.apache.commons.logging.LogFactory;
import org.apache.fop.apps.FOPException;
import org.apache.fop.fo.flow.Marker;
+import org.apache.fop.fo.Constants;
+import org.apache.fop.fo.flow.AbstractRetrieveMarker;
+import org.apache.fop.fo.flow.Marker;
+import org.apache.fop.fo.flow.Markers;
import org.apache.fop.fo.pagination.SimplePageMaster;
import org.apache.fop.traits.WritingModeTraitsGetter;
@@ -81,13 +85,7 @@ public class PageViewport extends AreaTreeObject implements Resolvable {
private Map<String, List<PageViewport>> pendingResolved = null;
- // hashmap of markers for this page
- // start and end are added by the fo that contains the markers
- private Map<String, Marker> markerFirstStart = null;
- private Map<String, Marker> markerLastStart = null;
- private Map<String, Marker> markerFirstAny = null;
- private Map<String, Marker> markerLastEnd = null;
- private Map<String, Marker> markerLastAny = null;
+ private Markers pageMarkers;
/**
* logging instance
@@ -352,115 +350,23 @@ public class PageViewport extends AreaTreeObject implements Resolvable {
}
/**
- * Add the markers for this page.
- * Only the required markers are kept.
- * For "first-starting-within-page" it adds the markers
- * that are starting only if the marker class name is not
- * already added.
- * For "first-including-carryover" it adds any starting marker
- * if the marker class name is not already added.
- * For "last-starting-within-page" it adds all marks that
- * are starting, replacing earlier markers.
- * For "last-ending-within-page" it adds all markers that
- * are ending, replacing earlier markers.
- *
- * Should this logic be placed in the Page layout manager.
+ * Register the markers for this page.
*
* @param marks the map of markers to add
* @param starting if the area being added is starting or ending
* @param isfirst if the area being added has is-first trait
* @param islast if the area being added has is-last trait
*/
- public void addMarkers(Map<String, Marker> marks, boolean starting,
- boolean isfirst, boolean islast) {
-
- if (marks == null) {
- return;
- }
- if (log.isDebugEnabled()) {
- log.debug("--" + marks.keySet() + ": "
- + (starting ? "starting" : "ending")
- + (isfirst ? ", first" : "")
- + (islast ? ", last" : ""));
- }
-
- // at the start of the area, register is-first and any areas
- if (starting) {
- if (isfirst) {
- if (markerFirstStart == null) {
- markerFirstStart = new HashMap<String, Marker>();
- }
- if (markerFirstAny == null) {
- markerFirstAny = new HashMap<String, Marker>();
- }
- // first on page: only put in new values, leave current
- for (String key : marks.keySet()) {
- if (!markerFirstStart.containsKey(key)) {
- markerFirstStart.put(key, marks.get(key));
- if (log.isTraceEnabled()) {
- log.trace("page " + pageNumberString + ": "
- + "Adding marker " + key + " to FirstStart");
- }
- }
- if (!markerFirstAny.containsKey(key)) {
- markerFirstAny.put(key, marks.get(key));
- if (log.isTraceEnabled()) {
- log.trace("page " + pageNumberString + ": "
- + "Adding marker " + key + " to FirstAny");
- }
- }
- }
- if (markerLastStart == null) {
- markerLastStart = new HashMap<String, Marker>();
- }
- // last on page: replace all
- markerLastStart.putAll(marks);
- if (log.isTraceEnabled()) {
- log.trace("page " + pageNumberString + ": "
- + "Adding all markers to LastStart");
- }
- } else {
- if (markerFirstAny == null) {
- markerFirstAny = new HashMap<String, Marker>();
- }
- // first on page: only put in new values, leave current
- for (String key : marks.keySet()) {
- if (!markerFirstAny.containsKey(key)) {
- markerFirstAny.put(key, marks.get(key));
- if (log.isTraceEnabled()) {
- log.trace("page " + pageNumberString + ": "
- + "Adding marker " + key + " to FirstAny");
- }
- }
- }
- }
- } else {
- // at the end of the area, register is-last and any areas
- if (islast) {
- if (markerLastEnd == null) {
- markerLastEnd = new HashMap<String, Marker>();
- }
- // last on page: replace all
- markerLastEnd.putAll(marks);
- if (log.isTraceEnabled()) {
- log.trace("page " + pageNumberString + ": "
- + "Adding all markers to LastEnd");
- }
- }
- if (markerLastAny == null) {
- markerLastAny = new HashMap<String, Marker>();
- }
- // last on page: replace all
- markerLastAny.putAll(marks);
- if (log.isTraceEnabled()) {
- log.trace("page " + pageNumberString + ": "
- + "Adding all markers to LastAny");
- }
+ public void registerMarkers(Map<String, Marker> marks, boolean starting, boolean isfirst, boolean islast) {
+ if (pageMarkers == null) {
+ pageMarkers = new Markers();
}
+ pageMarkers.register(marks, starting, isfirst, islast);
}
+
/**
- * Get a marker from this page.
+ * Resolve a marker from this page.
* This will retrieve a marker with the class name
* and position.
*
@@ -468,64 +374,17 @@ public class PageViewport extends AreaTreeObject implements Resolvable {
* @param pos the position to retrieve
* @return Object the marker found or null
*/
- public Marker getMarker(String name, int pos) {
- Marker mark = null;
- String posName = null;
- switch (pos) {
- case EN_FSWP:
- if (markerFirstStart != null) {
- mark = markerFirstStart.get(name);
- posName = "FSWP";
- }
- if (mark == null && markerFirstAny != null) {
- mark = markerFirstAny.get(name);
- posName = "FirstAny after " + posName;
- }
- break;
- case EN_FIC:
- if (markerFirstAny != null) {
- mark = markerFirstAny.get(name);
- posName = "FIC";
- }
- break;
- case EN_LSWP:
- if (markerLastStart != null) {
- mark = markerLastStart.get(name);
- posName = "LSWP";
- }
- if (mark == null && markerLastAny != null) {
- mark = markerLastAny.get(name);
- posName = "LastAny after " + posName;
- }
- break;
- case EN_LEWP:
- if (markerLastEnd != null) {
- mark = markerLastEnd.get(name);
- posName = "LEWP";
- }
- if (mark == null && markerLastAny != null) {
- mark = markerLastAny.get(name);
- posName = "LastAny after " + posName;
- }
- break;
- default:
- assert false;
- }
- if (log.isTraceEnabled()) {
- log.trace("page " + pageNumberString + ": " + "Retrieving marker " + name
- + " at position " + posName);
+ public Marker resolveMarker(AbstractRetrieveMarker rm) {
+ if (pageMarkers == null) {
+ return null;
}
- return mark;
+ return pageMarkers.resolve(rm);
}
/** Dumps the current marker data to the logger. */
public void dumpMarkers() {
- if (log.isTraceEnabled()) {
- log.trace("FirstAny: " + this.markerFirstAny);
- log.trace("FirstStart: " + this.markerFirstStart);
- log.trace("LastAny: " + this.markerLastAny);
- log.trace("LastEnd: " + this.markerLastEnd);
- log.trace("LastStart: " + this.markerLastStart);
+ if (pageMarkers != null) {
+ pageMarkers.dump();
}
}
diff --git a/src/java/org/apache/fop/cli/CommandLineOptions.java b/src/java/org/apache/fop/cli/CommandLineOptions.java
index 886e27527..7a11df71a 100644
--- a/src/java/org/apache/fop/cli/CommandLineOptions.java
+++ b/src/java/org/apache/fop/cli/CommandLineOptions.java
@@ -421,7 +421,7 @@ public class CommandLineOptions {
throw new FOPException("if you use '-cache', you must specify "
+ "the name of the font cache file");
} else {
- factory.getFontManager().setCacheFile(new File(args[i + 1]));
+ factory.getFontManager().setCacheFile(URI.create(args[i + 1]));
return 1;
}
}
diff --git a/src/java/org/apache/fop/events/CompositeEventListener.java b/src/java/org/apache/fop/events/CompositeEventListener.java
index 2b5cbffb2..c2bef322e 100644
--- a/src/java/org/apache/fop/events/CompositeEventListener.java
+++ b/src/java/org/apache/fop/events/CompositeEventListener.java
@@ -19,6 +19,7 @@
package org.apache.fop.events;
+import java.util.ArrayList;
import java.util.List;
/**
@@ -26,7 +27,7 @@ import java.util.List;
*/
public class CompositeEventListener implements EventListener {
- private List listeners = new java.util.ArrayList();
+ private List<EventListener> listeners = new ArrayList<EventListener>();
/**
* Adds an event listener to the broadcaster. It is appended to the list of previously
@@ -46,22 +47,17 @@ public class CompositeEventListener implements EventListener {
this.listeners.remove(listener);
}
- private synchronized int getListenerCount() {
- return this.listeners.size();
- }
-
/**
* Indicates whether any listeners have been registered with the broadcaster.
* @return true if listeners are present, false otherwise
*/
- public boolean hasEventListeners() {
- return (getListenerCount() > 0);
+ public synchronized boolean hasEventListeners() {
+ return !listeners.isEmpty();
}
- /** {@inheritDoc} */
+ /** {@inheritDoc } */
public synchronized void processEvent(Event event) {
- for (int i = 0, c = getListenerCount(); i < c; i++) {
- EventListener listener = (EventListener)this.listeners.get(i);
+ for (EventListener listener : listeners) {
listener.processEvent(event);
}
}
diff --git a/src/java/org/apache/fop/fo/Constants.java b/src/java/org/apache/fop/fo/Constants.java
index 14c4b5890..722a4ca94 100644
--- a/src/java/org/apache/fop/fo/Constants.java
+++ b/src/java/org/apache/fop/fo/Constants.java
@@ -807,8 +807,11 @@ public interface Constants {
*/
int PR_X_NUMBER_CONVERSION_FEATURES = 285;
+ /** Scope for table header */
+ int PR_X_HEADER_COLUMN = 286;
+
/** Number of property constants defined */
- int PROPERTY_COUNT = 285;
+ int PROPERTY_COUNT = 286;
// compound property constants
@@ -1246,6 +1249,8 @@ public interface Constants {
int EN_BT = 204; // bottom to top
/** Enumeration constant */
int EN_TB_LR = 205; // for top-to-bottom, left-to-right writing mode
+ /** Enumeration constant -- for fo:retrieve-table-marker */
+ int EN_FIRST_INCLUDING_CARRYOVER = 206;
/** Number of enumeration constants defined */
- int ENUM_COUNT = 205;
+ int ENUM_COUNT = 206;
}
diff --git a/src/java/org/apache/fop/fo/DelegatingFOEventHandler.java b/src/java/org/apache/fop/fo/DelegatingFOEventHandler.java
index 50026c996..bb0a1ba75 100644
--- a/src/java/org/apache/fop/fo/DelegatingFOEventHandler.java
+++ b/src/java/org/apache/fop/fo/DelegatingFOEventHandler.java
@@ -143,6 +143,16 @@ public abstract class DelegatingFOEventHandler extends FOEventHandler {
}
@Override
+ public void startStatic(StaticContent staticContent) {
+ delegate.startStatic(staticContent);
+ }
+
+ @Override
+ public void endStatic(StaticContent statisContent) {
+ delegate.endStatic(statisContent);
+ }
+
+ @Override
public void startFlow(Flow fl) {
delegate.startFlow(fl);
}
@@ -293,16 +303,6 @@ public abstract class DelegatingFOEventHandler extends FOEventHandler {
}
@Override
- public void startStatic(StaticContent staticContent) {
- delegate.startStatic(staticContent);
- }
-
- @Override
- public void endStatic(StaticContent statisContent) {
- delegate.endStatic(statisContent);
- }
-
- @Override
public void startMarkup() {
delegate.startMarkup();
}
diff --git a/src/java/org/apache/fop/fo/FOEventHandler.java b/src/java/org/apache/fop/fo/FOEventHandler.java
index 11b6d4a2f..ad647e42a 100644
--- a/src/java/org/apache/fop/fo/FOEventHandler.java
+++ b/src/java/org/apache/fop/fo/FOEventHandler.java
@@ -193,6 +193,20 @@ public abstract class FOEventHandler {
}
/**
+ * Process start of a Static.
+ * @param staticContent StaticContent that is starting
+ */
+ public void startStatic(StaticContent staticContent) {
+ }
+
+ /**
+ * Process end of a Static.
+ * @param staticContent StaticContent that is ending
+ */
+ public void endStatic(StaticContent staticContent) {
+ }
+
+ /**
* This method is called to indicate the start of a new fo:flow
* or fo:static-content.
* This method also handles fo:static-content tags, because the
@@ -409,22 +423,6 @@ public abstract class FOEventHandler {
public void endListBody(ListItemBody listItemBody) {
}
- // Static Regions
- /**
- * Process start of a Static.
- * @param staticContent StaticContent that is starting
- */
- public void startStatic(StaticContent staticContent) {
- }
-
- /**
- * Process end of a Static.
- * @param staticContent StaticContent that is ending
- */
- public void endStatic(StaticContent staticContent) {
- }
-
-
/**
* Process start of a Markup.
*/
diff --git a/src/java/org/apache/fop/fo/FONode.java b/src/java/org/apache/fop/fo/FONode.java
index c66259f11..707dae91e 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;
@@ -562,6 +563,19 @@ public abstract class FONode implements Cloneable {
}
/**
+ * Helper function to return "not supported child" exceptions. Note that the child is valid, just not
+ * supported yet by FOP.
+ *
+ * @param loc org.xml.sax.Locator object of the error (*not* parent node)
+ * @param nsURI namespace URI of incoming invalid node
+ * @param lName local name (i.e., no prefix) of incoming node
+ * @throws ValidationException the validation error provoked by the method call
+ */
+ protected void notSupportedChildError(Locator loc, String nsURI, String lName) throws ValidationException {
+ getFOValidationEventProducer().notSupportedChild(this, getName(), new QName(nsURI, lName), loc);
+ }
+
+ /**
* Helper function to throw an error caused by missing mandatory child elements.
* (e.g., <code>fo:layout-master-set</code> not having any <code>fo:page-master</code>
* child element.
@@ -601,6 +615,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/fo/FOPropertyMapping.java b/src/java/org/apache/fop/fo/FOPropertyMapping.java
index eac510fb0..08afbcd52 100644
--- a/src/java/org/apache/fop/fo/FOPropertyMapping.java
+++ b/src/java/org/apache/fop/fo/FOPropertyMapping.java
@@ -26,6 +26,7 @@ import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.datatypes.LengthBase;
import org.apache.fop.fo.expr.PropertyException;
import org.apache.fop.fo.flow.table.TableFObj.ColumnNumberPropertyMaker;
+import org.apache.fop.fo.pagination.Flow;
import org.apache.fop.fo.properties.BackgroundPositionShorthand;
import org.apache.fop.fo.properties.BorderSpacingShorthandParser;
import org.apache.fop.fo.properties.BorderWidthPropertyMaker;
@@ -2187,7 +2188,8 @@ public final class FOPropertyMapping implements Constants {
m = new EnumProperty.Maker(PR_RETRIEVE_POSITION_WITHIN_TABLE);
m.setInherited(false);
m.addEnum("first-starting", getEnumProperty(EN_FIRST_STARTING, "FIRST_STARTING"));
- m.addEnum("first-including-carryover", getEnumProperty(EN_FIC, "FIC"));
+ m.addEnum("first-including-carryover",
+ getEnumProperty(EN_FIRST_INCLUDING_CARRYOVER, "FIRST_INCLUDING_CARRYOVER"));
m.addEnum("last-starting", getEnumProperty(EN_LAST_STARTING, "LAST_STARTING"));
m.addEnum("last-ending", getEnumProperty(EN_LAST_ENDING, "LAST_ENDING"));
m.setDefault("first-starting");
@@ -2198,7 +2200,7 @@ public final class FOPropertyMapping implements Constants {
m.setInherited(false);
m.addEnum("table", getEnumProperty(EN_TABLE, "TABLE"));
m.addEnum("table-fragment", getEnumProperty(EN_TABLE_FRAGMENT, "TABLE_FRAGMENT"));
- m.addEnum("page", getEnumProperty(EN_DOCUMENT, "PAGE"));
+ m.addEnum("page", getEnumProperty(EN_PAGE, "PAGE"));
m.setDefault("table");
addPropertyMaker("retrieve-boundary-within-table", m);
}
@@ -2277,7 +2279,7 @@ public final class FOPropertyMapping implements Constants {
m = new StringProperty.Maker(PR_FLOW_NAME);
m.setInherited(false);
m.setDefault("");
- addPropertyMaker("flow-name", m);
+ addPropertyMaker(Flow.FLOW_NAME, m);
// force-page-count
m = new EnumProperty.Maker(PR_FORCE_PAGE_COUNT);
@@ -2522,6 +2524,12 @@ public final class FOPropertyMapping implements Constants {
m.setInherited(false);
m.setDefault("false");
addPropertyMaker("table-omit-header-at-break", m);
+
+ // fox:scope
+ m = new EnumProperty.Maker(PR_X_HEADER_COLUMN);
+ m.useGeneric(genericBoolean);
+ m.setDefault("false");
+ addPropertyMaker("fox:header", m);
}
private void createWritingModeProperties() {
diff --git a/src/java/org/apache/fop/fo/FOValidationEventProducer.java b/src/java/org/apache/fop/fo/FOValidationEventProducer.java
index ff005b1b4..ee6b078b5 100644
--- a/src/java/org/apache/fop/fo/FOValidationEventProducer.java
+++ b/src/java/org/apache/fop/fo/FOValidationEventProducer.java
@@ -90,6 +90,18 @@ public interface FOValidationEventProducer extends EventProducer {
Locator loc) throws ValidationException;
/**
+ * A valid but not yet supported child was encountered.
+ *
+ * @param source the event source
+ * @param elementName the name of the context node
+ * @param offendingNode the offending node
+ * @param loc the location of the error or null
+ * @throws ValidationException the validation error provoked by the method call
+ */
+ void notSupportedChild(Object source, String elementName, QName offendingNode, Locator loc)
+ throws ValidationException;
+
+ /**
* A required child element is missing.
* @param source the event source
* @param elementName the name of the context node
diff --git a/src/java/org/apache/fop/fo/FOValidationEventProducer.xml b/src/java/org/apache/fop/fo/FOValidationEventProducer.xml
index 509f7c1d3..a8b2fffb1 100644
--- a/src/java/org/apache/fop/fo/FOValidationEventProducer.xml
+++ b/src/java/org/apache/fop/fo/FOValidationEventProducer.xml
@@ -17,6 +17,7 @@
<message key="tooManyNodes">For "{elementName}", only one "{offendingNode}" may be declared.{{locator}}</message>
<message key="nodeOutOfOrder">For "{elementName}", "{tooLateNode}" must be declared before "{tooEarlyNode}"!{{locator}}</message>
<message key="invalidChild">"{offendingNode}" is not a valid child of "{elementName}"![ {ruleViolated,lookup}]{{locator}}</message>
+ <message key="notSupportedChild">"{offendingNode}" as a child of "{elementName}" is not supported yet!{{locator}}</message>
<message key="missingChildElement">"{elementName}" is missing child elements.[ Required content model: {contentModel}]{{locator}}</message>
<message key="missingProperty">Element "{elementName}" is missing required property "{propertyName}"!{{locator}}</message>
<message key="idNotUnique">Property ID "{id}" (found on "{elementName}") previously used; ID values must be unique within a document!{severity,equals,EventSeverity:FATAL,, Any reference to it will be considered a reference to the first occurrence in the document.}{{locator}}</message>
diff --git a/src/java/org/apache/fop/fo/FObj.java b/src/java/org/apache/fop/fo/FObj.java
index 241a442ab..0e7e55aa9 100644
--- a/src/java/org/apache/fop/fo/FObj.java
+++ b/src/java/org/apache/fop/fo/FObj.java
@@ -20,6 +20,7 @@
package org.apache.fop.fo;
import java.util.Collections;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
@@ -35,6 +36,7 @@ import org.apache.xmlgraphics.util.QName;
import org.apache.fop.apps.FOPException;
import org.apache.fop.fo.extensions.ExtensionAttachment;
import org.apache.fop.fo.flow.Marker;
+import org.apache.fop.fo.flow.table.TableCell;
import org.apache.fop.fo.properties.PropertyMaker;
/**
@@ -65,7 +67,7 @@ public abstract class FObj extends FONode implements Constants {
private boolean isOutOfLineFODescendant = false;
/** Markers added to this element. */
- private Map markers = null;
+ private Map<String, Marker> markers;
private int bidiLevel = -1;
@@ -356,7 +358,7 @@ public abstract class FObj extends FONode implements Constants {
}
}
if (markers == null) {
- markers = new java.util.HashMap();
+ markers = new HashMap<String, Marker>();
}
if (!markers.containsKey(mcname)) {
markers.put(mcname, marker);
@@ -376,7 +378,7 @@ public abstract class FObj extends FONode implements Constants {
/**
* @return the collection of Markers attached to this object
*/
- public Map getMarkers() {
+ public Map<String, Marker> getMarkers() {
return markers;
}
@@ -522,6 +524,11 @@ public abstract class FObj extends FONode implements Constants {
int found = 1;
FONode temp = getParent();
while (temp != null) {
+ if (temp instanceof TableCell && (ancestorID == FO_TABLE_HEADER || ancestorID == FO_TABLE_FOOTER)) {
+ // note that if the retrieve-table-marker is not in a table-header/footer an exception is
+ // thrown, so no need to reset this flag in that case
+ ((TableCell) temp).flagAsHavingRetrieveTableMarker();
+ }
if (temp.getNameId() == ancestorID) {
return found;
}
diff --git a/src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java b/src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java
index 008bca8a8..076691cb4 100644
--- a/src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java
+++ b/src/java/org/apache/fop/fo/extensions/ExtensionElementMapping.java
@@ -52,6 +52,7 @@ public class ExtensionElementMapping extends ElementMapping {
PROPERTY_ATTRIBUTES.add("disable-column-balancing");
//These are FOP's extension properties for accessibility
PROPERTY_ATTRIBUTES.add("alt-text");
+ PROPERTY_ATTRIBUTES.add("header");
//fox:border-*-radius-*
PROPERTY_ATTRIBUTES.add("border-before-radius-start");
PROPERTY_ATTRIBUTES.add("border-before-radius-end");
diff --git a/src/java/org/apache/fop/fo/extensions/InternalElementMapping.java b/src/java/org/apache/fop/fo/extensions/InternalElementMapping.java
index 687952d25..f257dd79d 100644
--- a/src/java/org/apache/fop/fo/extensions/InternalElementMapping.java
+++ b/src/java/org/apache/fop/fo/extensions/InternalElementMapping.java
@@ -43,12 +43,15 @@ public class InternalElementMapping extends ElementMapping {
/** The "struct-ref" attribute, to refer to a structure tree element. */
public static final String STRUCT_REF = "struct-ref";
+ public static final String SCOPE = "scope";
+
private static final Set<String> PROPERTY_ATTRIBUTES = new java.util.HashSet<String>();
static {
//These are FOP's extension properties for accessibility
PROPERTY_ATTRIBUTES.add(STRUCT_ID);
PROPERTY_ATTRIBUTES.add(STRUCT_REF);
+ PROPERTY_ATTRIBUTES.add(SCOPE);
}
/**
diff --git a/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java b/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java
index 62c821504..636bc04df 100644
--- a/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java
+++ b/src/java/org/apache/fop/fo/flow/AbstractRetrieveMarker.java
@@ -46,6 +46,11 @@ public abstract class AbstractRetrieveMarker extends FObjMixed {
private String retrieveClassName;
+ private int position;
+ private String positionLabel;
+ private int boundary;
+ private String boundaryLabel;
+
/**
* Create a new AbstractRetrieveMarker instance that
* is a child of the given {@link FONode}
@@ -206,4 +211,43 @@ public abstract class AbstractRetrieveMarker extends FObjMixed {
return this.retrieveClassName;
}
+ protected void setBoundaryLabel(String label) {
+ this.boundaryLabel = label;
+ }
+
+ protected void setPositionLabel(String label) {
+ this.positionLabel = label;
+ }
+
+ public String getBoundaryLabel() {
+ return this.boundaryLabel;
+ }
+
+ public String getPositionLabel() {
+ return this.positionLabel;
+ }
+
+ protected void setPosition(int position) {
+ this.position = position;
+ }
+
+ protected void setBoundary(int boundary) {
+ this.boundary = boundary;
+ }
+
+ public int getPosition() {
+ return this.position;
+ }
+
+ public int getBoundary() {
+ return this.boundary;
+ }
+
+ public abstract String getLocalName();
+
+ public abstract int getNameId();
+
+ public void changePositionTo(int position) {
+ this.position = position;
+ }
}
diff --git a/src/java/org/apache/fop/fo/flow/Markers.java b/src/java/org/apache/fop/fo/flow/Markers.java
new file mode 100644
index 000000000..24da818af
--- /dev/null
+++ b/src/java/org/apache/fop/fo/flow/Markers.java
@@ -0,0 +1,212 @@
+/*
+ * 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.fo.flow;
+
+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.fo.Constants;
+
+/**
+ * A class to register and resolve markers.
+ */
+public final class Markers {
+
+ // IsAny means either IsFirst or IsLast
+ private Map<String, Marker> firstQualifyingIsFirst;
+ private Map<String, Marker> firstQualifyingIsAny;
+ private Map<String, Marker> lastQualifyingIsFirst;
+ private Map<String, Marker> lastQualifyingIsLast;
+ private Map<String, Marker> lastQualifyingIsAny;
+
+ private static Log log = LogFactory.getLog(Markers.class);
+
+ /**
+ * Registers a marker with the position traits set.
+ * Only the required markers are kept.
+ * For "first-starting-within-page" it adds the markers
+ * that are starting only if the marker class name is not
+ * already added.
+ * For "first-including-carryover" it adds any starting marker
+ * if the marker class name is not already added.
+ * For "last-starting-within-page" it adds all marks that
+ * are starting, replacing earlier markers.
+ * For "last-ending-within-page" it adds all markers that
+ * are ending, replacing earlier markers.
+ *
+ * @param marks a map of markers to register
+ * @param starting whether the registration happens at the start (true) or end (false) the the area
+ * @param isfirst whether it is the first area of the parent LM
+ * @param islast whether it is the last area of the parent LM
+ */
+ public void register(Map<String, Marker> marks, boolean starting, boolean isfirst, boolean islast) {
+ // TODO: find way to put the page number in the log tracing
+
+ if (marks == null) {
+ return;
+ }
+ if (log.isDebugEnabled()) {
+ log.debug("--" + marks.keySet() + ": " + (starting ? "starting" : "ending")
+ + (isfirst ? ", first" : "") + (islast ? ", last" : ""));
+ }
+
+ if (starting) {
+ // at the start of the area, register is-first and any areas
+ if (firstQualifyingIsAny == null) {
+ firstQualifyingIsAny = new HashMap<String, Marker>();
+ }
+ if (isfirst) {
+ if (firstQualifyingIsFirst == null) {
+ firstQualifyingIsFirst = new HashMap<String, Marker>();
+ }
+ // first on scope: only put in new values, leave current
+ for (Iterator<String> iter = marks.keySet().iterator(); iter.hasNext();) {
+ String key = iter.next();
+ if (!firstQualifyingIsFirst.containsKey(key)) {
+ firstQualifyingIsFirst.put(key, marks.get(key));
+ if (log.isTraceEnabled()) {
+ log.trace("Adding marker " + key + " to firstQualifyingIsFirst");
+ }
+ }
+ if (!firstQualifyingIsAny.containsKey(key)) {
+ firstQualifyingIsAny.put(key, marks.get(key));
+ if (log.isTraceEnabled()) {
+ log.trace("Adding marker " + key + " to firstQualifyingIsAny");
+ }
+ }
+ }
+ if (lastQualifyingIsFirst == null) {
+ lastQualifyingIsFirst = new HashMap<String, Marker>();
+ }
+ // last on scope: replace all
+ lastQualifyingIsFirst.putAll(marks);
+ if (log.isTraceEnabled()) {
+ log.trace("Adding all markers to LastStart");
+ }
+ } else {
+ // first on scope: only put in new values, leave current
+ for (Iterator<String> iter = marks.keySet().iterator(); iter.hasNext();) {
+ String key = iter.next();
+ if (!firstQualifyingIsAny.containsKey(key)) {
+ firstQualifyingIsAny.put(key, marks.get(key));
+ if (log.isTraceEnabled()) {
+ log.trace("Adding marker " + key + " to firstQualifyingIsAny");
+ }
+ }
+ }
+ }
+ } else {
+ // at the end of the area, register is-last and any areas
+ if (islast) {
+ if (lastQualifyingIsLast == null) {
+ lastQualifyingIsLast = new HashMap<String, Marker>();
+ }
+ // last on page: replace all
+ lastQualifyingIsLast.putAll(marks);
+ if (log.isTraceEnabled()) {
+ log.trace("Adding all markers to lastQualifyingIsLast");
+ }
+ }
+ if (lastQualifyingIsAny == null) {
+ lastQualifyingIsAny = new HashMap<String, Marker>();
+ }
+ // last on page: replace all
+ lastQualifyingIsAny.putAll(marks);
+ if (log.isTraceEnabled()) {
+ log.trace("Adding all markers to lastQualifyingIsAny");
+ }
+ }
+ }
+
+ /**
+ * Retrieves the best candidate marker for the given position.
+ * @param name the key used to register the marker
+ * @param pos the retrieval scope position
+ * @return a Marker instance
+ */
+ public Marker resolve(AbstractRetrieveMarker arm) {
+ Marker mark = null;
+ int pos = arm.getPosition();
+ String name = arm.getRetrieveClassName();
+ String posName = arm.getPositionLabel();
+ String localName = arm.getLocalName();
+ switch (pos) {
+ case Constants.EN_FSWP: // retrieve-marker
+ case Constants.EN_FIRST_STARTING: // retrieve-table-marker
+ if (firstQualifyingIsFirst != null) {
+ mark = firstQualifyingIsFirst.get(name);
+ }
+ if (mark == null && firstQualifyingIsAny != null) {
+ mark = firstQualifyingIsAny.get(name);
+ posName = "FirstAny after " + posName;
+ }
+ break;
+ case Constants.EN_FIC: // retrieve-marker
+ case Constants.EN_FIRST_INCLUDING_CARRYOVER: // retrieve-table-marker
+ if (firstQualifyingIsAny != null) {
+ mark = firstQualifyingIsAny.get(name);
+ }
+ break;
+ case Constants.EN_LSWP: // retrieve-marker
+ case Constants.EN_LAST_STARTING: // retrieve-table-marker
+ if (lastQualifyingIsFirst != null) {
+ mark = lastQualifyingIsFirst.get(name);
+ }
+ if (mark == null && lastQualifyingIsAny != null) {
+ mark = lastQualifyingIsAny.get(name);
+ posName = "LastAny after " + posName;
+ }
+ break;
+ case Constants.EN_LEWP: // retrieve-marker
+ case Constants.EN_LAST_ENDING: // retrieve-table-marker
+ if (lastQualifyingIsLast != null) {
+ mark = lastQualifyingIsLast.get(name);
+ }
+ if (mark == null && lastQualifyingIsAny != null) {
+ mark = lastQualifyingIsAny.get(name);
+ posName = "LastAny after " + posName;
+ }
+ break;
+ default:
+ throw new RuntimeException("Invalid position attribute in " + localName + ".");
+ }
+ if (log.isTraceEnabled()) {
+ // TODO: find way to put the page number here
+ log.trace(localName + ": name[" + name + "]; position [" + posName + "]");
+ }
+ return mark;
+ }
+
+ /** Dumps the current marker data to the logger. */
+ public void dump() {
+ if (log.isTraceEnabled()) {
+ log.trace("FirstAny: " + this.firstQualifyingIsAny);
+ log.trace("FirstStart: " + this.firstQualifyingIsFirst);
+ log.trace("LastAny: " + this.lastQualifyingIsAny);
+ log.trace("LastEnd: " + this.lastQualifyingIsLast);
+ log.trace("LastStart: " + this.lastQualifyingIsFirst);
+ }
+ }
+
+}
diff --git a/src/java/org/apache/fop/fo/flow/RetrieveMarker.java b/src/java/org/apache/fop/fo/flow/RetrieveMarker.java
index 5fc70c7f2..b001a41ee 100644
--- a/src/java/org/apache/fop/fo/flow/RetrieveMarker.java
+++ b/src/java/org/apache/fop/fo/flow/RetrieveMarker.java
@@ -34,11 +34,6 @@ import org.apache.fop.fo.PropertyList;
*/
public class RetrieveMarker extends AbstractRetrieveMarker {
- // The value of properties relevant for fo:retrieve-marker.
- private int retrievePosition;
- private int retrieveBoundary;
- // End of property values
-
/**
* Create a new RetrieveMarker instance that is a
* child of the given {@link FONode}.
@@ -70,8 +65,10 @@ public class RetrieveMarker extends AbstractRetrieveMarker {
/** {@inheritDoc} */
public void bind(PropertyList pList) throws FOPException {
super.bind(pList);
- this.retrievePosition = pList.get(PR_RETRIEVE_POSITION).getEnum();
- this.retrieveBoundary = pList.get(PR_RETRIEVE_BOUNDARY).getEnum();
+ setPosition(pList.get(PR_RETRIEVE_POSITION).getEnum());
+ setPositionLabel((String) pList.get(PR_RETRIEVE_POSITION).getObject());
+ setBoundary(pList.get(PR_RETRIEVE_BOUNDARY).getEnum());
+ setBoundaryLabel((String) pList.get(PR_RETRIEVE_BOUNDARY).getObject());
}
/**
@@ -84,19 +81,19 @@ public class RetrieveMarker extends AbstractRetrieveMarker {
* {@link org.apache.fop.fo.Constants#EN_LEWP}.
*/
public int getRetrievePosition() {
- return this.retrievePosition;
+ return getPosition();
}
/**
* Return the value for the <code>retrieve-boundary</code>
* property
- * @return the value for retrieve-boundary-within-table; one of
+ * @return the value for retrieve-boundary; one of
* {@link org.apache.fop.fo.Constants#EN_PAGE},
* {@link org.apache.fop.fo.Constants#EN_PAGE_SEQUENCE},
* {@link org.apache.fop.fo.Constants#EN_DOCUMENT}.
*/
public int getRetrieveBoundary() {
- return this.retrieveBoundary;
+ return getBoundary();
}
/** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/fo/flow/RetrieveTableMarker.java b/src/java/org/apache/fop/fo/flow/RetrieveTableMarker.java
index 3090cb702..efacba864 100644
--- a/src/java/org/apache/fop/fo/flow/RetrieveTableMarker.java
+++ b/src/java/org/apache/fop/fo/flow/RetrieveTableMarker.java
@@ -32,11 +32,6 @@ import org.apache.fop.fo.PropertyList;
*/
public class RetrieveTableMarker extends AbstractRetrieveMarker {
- // The value of properties relevant for fo:retrieve-table-marker.
- private int retrievePositionWithinTable;
- private int retrieveBoundaryWithinTable;
- // end property values
-
/**
* Create a new RetrieveTableMarker instance that is
* a child of the given {@link FONode}.
@@ -67,10 +62,10 @@ public class RetrieveTableMarker extends AbstractRetrieveMarker {
/** {@inheritDoc} */
public void bind(PropertyList pList) throws FOPException {
super.bind(pList);
- this.retrievePositionWithinTable
- = pList.get(PR_RETRIEVE_POSITION_WITHIN_TABLE).getEnum();
- this.retrieveBoundaryWithinTable
- = pList.get(PR_RETRIEVE_BOUNDARY_WITHIN_TABLE).getEnum();
+ setPosition(pList.get(PR_RETRIEVE_POSITION_WITHIN_TABLE).getEnum());
+ setPositionLabel((String) pList.get(PR_RETRIEVE_POSITION_WITHIN_TABLE).getObject());
+ setBoundary(pList.get(PR_RETRIEVE_BOUNDARY_WITHIN_TABLE).getEnum());
+ setBoundaryLabel((String) pList.get(PR_RETRIEVE_BOUNDARY_WITHIN_TABLE).getObject());
}
/**
@@ -83,7 +78,7 @@ public class RetrieveTableMarker extends AbstractRetrieveMarker {
* {@link org.apache.fop.fo.Constants#EN_LAST_ENDING}.
*/
public int getRetrievePositionWithinTable() {
- return this.retrievePositionWithinTable;
+ return getPosition();
}
/**
@@ -95,7 +90,7 @@ public class RetrieveTableMarker extends AbstractRetrieveMarker {
* {@link org.apache.fop.fo.Constants#EN_PAGE}.
*/
public int getRetrieveBoundaryWithinTable() {
- return this.retrieveBoundaryWithinTable;
+ return getBoundary();
}
/** {@inheritDoc} */
@@ -110,4 +105,12 @@ public class RetrieveTableMarker extends AbstractRetrieveMarker {
public int getNameId() {
return FO_RETRIEVE_TABLE_MARKER;
}
+
+ /** {@inheritDoc} */
+ public void clearChildNodes() {
+ super.clearChildNodes();
+ this.currentTextNode = null;
+ this.lastFOTextProcessed = null;
+ }
+
}
diff --git a/src/java/org/apache/fop/fo/flow/table/TableCell.java b/src/java/org/apache/fop/fo/flow/table/TableCell.java
index c4f9c2aa6..f198f3aad 100644
--- a/src/java/org/apache/fop/fo/flow/table/TableCell.java
+++ b/src/java/org/apache/fop/fo/flow/table/TableCell.java
@@ -62,6 +62,8 @@ public class TableCell extends TableFObj implements CommonAccessibilityHolder {
/** used for FO validation */
private boolean blockItemFound = false;
+ private boolean hasRetrieveTableMarker;
+
/**
* Create a TableCell instance with the given {@link FONode}
* as parent.
@@ -247,4 +249,11 @@ public class TableCell extends TableFObj implements CommonAccessibilityHolder {
return FO_TABLE_CELL;
}
+ public void flagAsHavingRetrieveTableMarker() {
+ hasRetrieveTableMarker = true;
+ }
+
+ public boolean hasRetrieveTableMarker() {
+ return hasRetrieveTableMarker;
+ }
}
diff --git a/src/java/org/apache/fop/fo/flow/table/TableColumn.java b/src/java/org/apache/fop/fo/flow/table/TableColumn.java
index 5047822da..33cbff884 100644
--- a/src/java/org/apache/fop/fo/flow/table/TableColumn.java
+++ b/src/java/org/apache/fop/fo/flow/table/TableColumn.java
@@ -24,6 +24,7 @@ import org.xml.sax.Locator;
import org.apache.fop.apps.FOPException;
import org.apache.fop.datatypes.Length;
+import org.apache.fop.fo.Constants;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.ValidationException;
@@ -44,6 +45,7 @@ public class TableColumn extends TableFObj {
private Length columnWidth;
private int numberColumnsRepeated;
private int numberColumnsSpanned;
+ private boolean isHeader;
// Unused but valid items, commented out for performance:
// private int visibility;
// End of property values
@@ -120,6 +122,7 @@ public class TableColumn extends TableFObj {
if (!this.implicitColumn) {
this.pList = pList;
}
+ isHeader = (pList.get(Constants.PR_X_HEADER_COLUMN).getEnum() == Constants.EN_TRUE);
}
/** {@inheritDoc} */
@@ -263,4 +266,13 @@ public class TableColumn extends TableFObj {
this.pList = null;
}
+ /**
+ * Returns {@code true} if this column is made of header cells.
+ *
+ * @return {@code true} if cells in this column are like TH cells in HTML
+ */
+ public boolean isHeader() {
+ return isHeader;
+ }
+
}
diff --git a/src/java/org/apache/fop/fo/flow/table/TablePart.java b/src/java/org/apache/fop/fo/flow/table/TablePart.java
index 3ab92cc94..032340681 100644
--- a/src/java/org/apache/fop/fo/flow/table/TablePart.java
+++ b/src/java/org/apache/fop/fo/flow/table/TablePart.java
@@ -169,6 +169,8 @@ public abstract class TablePart extends TableCellContainer {
getUserAgent().getEventBroadcaster());
eventProducer.noMixRowsAndCells(this, getName(), getLocator());
}
+ } else if (localName.equals("retrieve-table-marker")) {
+ notSupportedChildError(loc, nsURI, localName);
} else {
invalidChildError(loc, nsURI, localName);
}
diff --git a/src/java/org/apache/fop/fo/pagination/Flow.java b/src/java/org/apache/fop/fo/pagination/Flow.java
index 981485e32..45c8f7804 100644
--- a/src/java/org/apache/fop/fo/pagination/Flow.java
+++ b/src/java/org/apache/fop/fo/pagination/Flow.java
@@ -36,6 +36,9 @@ import org.apache.fop.fo.properties.CommonAccessibilityHolder;
*/
public class Flow extends FObj implements CommonAccessibilityHolder {
+ /** The "flow-name" property name. */
+ public static final String FLOW_NAME = "flow-name";
+
private String flowName;
private CommonAccessibility commonAccessibility;
@@ -61,7 +64,7 @@ public class Flow extends FObj implements CommonAccessibilityHolder {
/** {@inheritDoc} */
protected void startOfNode() throws FOPException {
if (flowName == null || flowName.equals("")) {
- missingPropertyError("flow-name");
+ missingPropertyError(FLOW_NAME);
}
// according to communication from Paul Grosso (XSL-List,
diff --git a/src/java/org/apache/fop/fo/pagination/LayoutMasterSet.java b/src/java/org/apache/fop/fo/pagination/LayoutMasterSet.java
index 533b113d2..8b109dd0e 100644
--- a/src/java/org/apache/fop/fo/pagination/LayoutMasterSet.java
+++ b/src/java/org/apache/fop/fo/pagination/LayoutMasterSet.java
@@ -217,5 +217,24 @@ public class LayoutMasterSet extends FObj {
public int getNameId() {
return FO_LAYOUT_MASTER_SET;
}
+
+ /**
+ * Returns the default name of the region to which the flow or static-content having
+ * the given flow-name is assigned.
+ *
+ * @param flowName the value of the flow-name property
+ * @return the default region name ("xsl-region-body", "xsl-region-before", etc.)
+ */
+ public String getDefaultRegionNameFor(String flowName) {
+ for (SimplePageMaster spm : simplePageMasters.values()) {
+ for (Region region : spm.getRegions().values()) {
+ if (region.getRegionName().equals(flowName)) {
+ return region.getDefaultRegionName();
+ }
+ }
+ }
+ assert flowName.equals("xsl-before-float-separator") || flowName.equals("xsl-footnote-separator");
+ return flowName;
+ }
}
diff --git a/src/java/org/apache/fop/fo/pagination/StaticContent.java b/src/java/org/apache/fop/fo/pagination/StaticContent.java
index e70c80c5d..412cdbcca 100644
--- a/src/java/org/apache/fop/fo/pagination/StaticContent.java
+++ b/src/java/org/apache/fop/fo/pagination/StaticContent.java
@@ -42,7 +42,7 @@ public class StaticContent extends Flow {
/** {@inheritDoc} */
protected void startOfNode() throws FOPException {
if (getFlowName() == null || getFlowName().equals("")) {
- missingPropertyError("flow-name");
+ missingPropertyError(FLOW_NAME);
}
getFOEventHandler().startStatic(this);
}
diff --git a/src/java/org/apache/fop/fonts/CIDFont.java b/src/java/org/apache/fop/fonts/CIDFont.java
index 82213dd65..dc398263e 100644
--- a/src/java/org/apache/fop/fonts/CIDFont.java
+++ b/src/java/org/apache/fop/fonts/CIDFont.java
@@ -29,7 +29,7 @@ import org.apache.fop.apps.io.InternalResourceResolver;
public abstract class CIDFont extends CustomFont {
/** Contains the character widths for all characters in the font */
- protected int[] width = null;
+ protected int[] width;
/**
* @param resourceResolver the URI resolver for controlling file access
@@ -69,7 +69,7 @@ public abstract class CIDFont extends CustomFont {
* Returns the subset information for this font.
* @return the subset information
*/
- public abstract CIDSubset getCIDSubset();
+ public abstract CIDSet getCIDSet();
// ---- Optional ----
/**
diff --git a/src/java/org/apache/fop/fonts/CIDFull.java b/src/java/org/apache/fop/fonts/CIDFull.java
new file mode 100644
index 000000000..ee062a2bb
--- /dev/null
+++ b/src/java/org/apache/fop/fonts/CIDFull.java
@@ -0,0 +1,113 @@
+/*
+ * 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.fonts;
+
+import java.util.BitSet;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.fop.util.CharUtilities;
+
+/**
+ * Provides methods to get font information.
+ * Naming:
+ * glyph index: original index of the glyph in the non-subset font (!= unicode index)
+ * character selector: index into a set of glyphs. For subset CID fonts, this starts at 0. For non-subset
+ * fonts, this is the same as the glyph index.
+ * Unicode index: The Unicode codepoint of a character.
+ * Glyph name: the Adobe glyph name (as found in Glyphs.java)
+ */
+public class CIDFull implements CIDSet {
+
+ private BitSet glyphIndices;
+ private final MultiByteFont font;
+
+ public CIDFull(MultiByteFont mbf) {
+ font = mbf;
+ }
+
+ private void initGlyphIndices() {
+ // this cannot be called in the constructor since the font is not ready...
+ if (glyphIndices == null) {
+ glyphIndices = font.getGlyphIndices();
+ }
+ }
+
+ /** {@inheritDoc} */
+ public int getOriginalGlyphIndex(int index) {
+ return index;
+ }
+
+ /** {@inheritDoc} */
+ public char getUnicode(int index) {
+ initGlyphIndices();
+ if (glyphIndices.get(index)) {
+ return (char) index;
+ } else {
+ return CharUtilities.NOT_A_CHARACTER;
+ }
+ }
+
+ /** {@inheritDoc} */
+ public int mapChar(int glyphIndex, char unicode) {
+ return (char) glyphIndex;
+ }
+
+ /** {@inheritDoc} */
+ public Map<Integer, Integer> getGlyphs() {
+ // this is never really called for full embedded fonts but the equivalent map would be the identity
+ initGlyphIndices();
+ Map<Integer, Integer> glyphs = new HashMap<Integer, Integer>();
+ int nextBitSet = 0;
+ for (int j = 0; j < glyphIndices.cardinality(); j++) {
+ nextBitSet = glyphIndices.nextSetBit(nextBitSet);
+ glyphs.put(Integer.valueOf(nextBitSet), Integer.valueOf(nextBitSet));
+ nextBitSet++;
+ }
+ return Collections.unmodifiableMap(glyphs);
+ }
+
+ /** {@inheritDoc} */
+ public char[] getChars() {
+ return font.getChars();
+ }
+
+ /** {@inheritDoc} */
+ public int getNumberOfGlyphs() {
+ initGlyphIndices();
+ // note: the real number of glyphs is given by the cardinality() method (not the length()) but since
+ // we will pad gaps in the indices with zeros we really want the length() here. this method is only
+ // called when embedding a font in PostScript and this will be the value of the CIDCount entry
+ return glyphIndices.length();
+ }
+
+ /** {@inheritDoc} */
+ public BitSet getGlyphIndices() {
+ initGlyphIndices();
+ return glyphIndices;
+ }
+
+ /** {@inheritDoc} */
+ public int[] getWidths() {
+ return font.getWidths();
+ }
+
+}
diff --git a/src/java/org/apache/fop/fonts/CIDSet.java b/src/java/org/apache/fop/fonts/CIDSet.java
new file mode 100644
index 000000000..7530ea6e7
--- /dev/null
+++ b/src/java/org/apache/fop/fonts/CIDSet.java
@@ -0,0 +1,90 @@
+/*
+ * 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.fonts;
+
+import java.util.BitSet;
+import java.util.Map;
+
+/**
+ * Declares methods to retrieve font information (glyph indices, widths, unicode values) from a CID font.
+ */
+public interface CIDSet {
+
+ /**
+ * Returns the original index of the glyph inside the (non-subset) font's glyph list. This
+ * index can be used to access the character width information, for example.
+ * @param index the subset index (character selector) to access the glyph
+ * @return the original index (or -1 if no glyph index is available for the subset index)
+ */
+ int getOriginalGlyphIndex(int index);
+
+ /**
+ * Returns the Unicode value for a subset index (character selector). If there's no such
+ * Unicode value, the "NOT A CHARACTER" (0xFFFF) is returned.
+ * @param index the subset index (character selector)
+ * @return the Unicode value or "NOT A CHARACTER" (0xFFFF)
+ */
+ char getUnicode(int index);
+
+ /**
+ * Maps a character to a character selector for a font subset. If the character isn't in the
+ * subset, yet, it is added and a new character selector returned. Otherwise, the already
+ * allocated character selector is returned from the existing map/subset.
+ * @param glyphIndex the glyph index of the character
+ * @param unicode the Unicode index of the character
+ * @return the subset index
+ */
+ int mapChar(int glyphIndex, char unicode);
+
+ /**
+ * Returns an unmodifiable Map of the font subset. It maps from glyph index to
+ * character selector (i.e. the subset index in this case).
+ * @return Map Map&lt;Integer, Integer&gt; of the font subset
+ */
+ Map<Integer, Integer> getGlyphs();
+
+ /**
+ * Returns a char array containing all Unicode characters that are in the subset.
+ * @return a char array with all used Unicode characters
+ */
+ char[] getChars();
+
+ /**
+ * Returns the number of glyphs in the subset.
+ * @return the number of glyphs in the subset
+ */
+ int getNumberOfGlyphs();
+
+ /**
+ * Returns a BitSet with bits set for each available glyph index in the subset.
+ * @return a BitSet indicating available glyph indices
+ */
+ BitSet getGlyphIndices();
+
+ /**
+ * Return the array of widths.
+ * <p>
+ * This is used to get an array for inserting in an output format.
+ * It should not be used for lookup.
+ * @return an array of widths
+ */
+ int[] getWidths();
+
+}
diff --git a/src/java/org/apache/fop/fonts/CIDSubset.java b/src/java/org/apache/fop/fonts/CIDSubset.java
index 372a638d1..f442c13ed 100644
--- a/src/java/org/apache/fop/fonts/CIDSubset.java
+++ b/src/java/org/apache/fop/fonts/CIDSubset.java
@@ -26,18 +26,16 @@ import java.util.Map;
import org.apache.fop.util.CharUtilities;
-//Naming:
-//glyph index: original index of the glyph in the non-subset font (!= unicode index)
-//character selector: index into a set of glyphs. For subset CID fonts, this starts at 0. For
-// non-subset fonts, this is the same as the glyph index.
-//Unicode index: The Unicode codepoint of a character.
-//Glyph name: the Adobe glyph name (as found in Glyphs.java)
-
/**
- * Keeps track of the glyphs used in a document. This information is later used to build
- * a subset of a font.
+ * Provides methods to get font information.
+ * Naming:
+ * glyph index: original index of the glyph in the non-subset font (!= unicode index)
+ * character selector: index into a set of glyphs. For subset CID fonts, this starts at 0. For non-subset
+ * fonts, this is the same as the glyph index.
+ * Unicode index: The Unicode codepoint of a character.
+ * Glyph name: the Adobe glyph name (as found in Glyphs.java)
*/
-public class CIDSubset {
+public class CIDSubset implements CIDSet {
/**
* usedGlyphs contains orginal, new glyph index (glyph index -> char selector)
@@ -48,51 +46,36 @@ public class CIDSubset {
* usedGlyphsIndex contains new glyph, original index (char selector -> glyph index)
*/
private Map<Integer, Integer> usedGlyphsIndex = new HashMap<Integer, Integer>();
- private int usedGlyphsCount = 0;
+ private int usedGlyphsCount;
/**
* usedCharsIndex contains new glyph, original char (char selector -> Unicode)
*/
private Map<Integer, Character> usedCharsIndex = new HashMap<Integer, Character>();
- /**
- * Default constructor.
- */
- public CIDSubset() {
- }
+ private final MultiByteFont font;
- /**
- * Adds the first glyph which is reserved for .notdef for all CID subsets.
- */
- public void setupFirstGlyph() {
- usedGlyphs.put(Integer.valueOf(0), Integer.valueOf(0));
- usedGlyphsIndex.put(Integer.valueOf(0), Integer.valueOf(0));
+ public CIDSubset(MultiByteFont mbf) {
+ font = mbf;
+ // The zeroth value is reserved for .notdef
+ usedGlyphs.put(0, 0);
+ usedGlyphsIndex.put(0, 0);
usedGlyphsCount++;
}
- /**
- * Returns the original index of the glyph inside the (non-subset) font's glyph list. This
- * index can be used to access the character width information, for example.
- * @param subsetIndex the subset index (character selector) to access the glyph
- * @return the original index (or -1 if no glyph index is available for the subset index)
- */
- public int getGlyphIndexForSubsetIndex(int subsetIndex) {
- Integer glyphIndex = usedGlyphsIndex.get(Integer.valueOf(subsetIndex));
+ /** {@inheritDoc} */
+ public int getOriginalGlyphIndex(int index) {
+ Integer glyphIndex = usedGlyphsIndex.get(index);
if (glyphIndex != null) {
- return glyphIndex.intValue();
+ return glyphIndex;
} else {
return -1;
}
}
- /**
- * Returns the Unicode value for a subset index (character selector). If there's no such
- * Unicode value, the "NOT A CHARACTER" (0xFFFF) is returned.
- * @param subsetIndex the subset index (character selector)
- * @return the Unicode value or "NOT A CHARACTER" (0xFFFF)
- */
- public char getUnicodeForSubsetIndex(int subsetIndex) {
- Character mapValue = usedCharsIndex.get(Integer.valueOf(subsetIndex));
+ /** {@inheritDoc} */
+ public char getUnicode(int index) {
+ Character mapValue = usedCharsIndex.get(index);
if (mapValue != null) {
return mapValue.charValue();
} else {
@@ -100,72 +83,60 @@ public class CIDSubset {
}
}
- /**
- * Maps a character to a character selector for a font subset. If the character isn't in the
- * subset, yet, it is added and a new character selector returned. Otherwise, the already
- * allocated character selector is returned from the existing map/subset.
- * @param glyphIndex the glyph index of the character
- * @param unicode the Unicode index of the character
- * @return the subset index
- */
- public int mapSubsetChar(int glyphIndex, char unicode) {
+ /** {@inheritDoc} */
+ public int mapChar(int glyphIndex, char unicode) {
// Reencode to a new subset font or get the reencoded value
// IOW, accumulate the accessed characters and build a character map for them
- Integer subsetCharSelector = usedGlyphs.get(Integer.valueOf(glyphIndex));
+ Integer subsetCharSelector = usedGlyphs.get(glyphIndex);
if (subsetCharSelector == null) {
int selector = usedGlyphsCount;
- usedGlyphs.put(Integer.valueOf(glyphIndex),
- Integer.valueOf(selector));
- usedGlyphsIndex.put(Integer.valueOf(selector),
- Integer.valueOf(glyphIndex));
- usedCharsIndex.put(Integer.valueOf(selector),
- Character.valueOf(unicode));
+ usedGlyphs.put(glyphIndex, selector);
+ usedGlyphsIndex.put(selector, glyphIndex);
+ usedCharsIndex.put(selector, unicode);
usedGlyphsCount++;
return selector;
} else {
- return subsetCharSelector.intValue();
+ return subsetCharSelector;
}
}
- /**
- * Returns an unmodifiable Map of the font subset. It maps from glyph index to
- * character selector (i.e. the subset index in this case).
- * @return Map Map&lt;Integer, Integer&gt; of the font subset
- */
- public Map<Integer, Integer> getSubsetGlyphs() {
+ /** {@inheritDoc} */
+ public Map<Integer, Integer> getGlyphs() {
return Collections.unmodifiableMap(this.usedGlyphs);
}
- /**
- * Returns a char array containing all Unicode characters that are in the subset.
- * @return a char array with all used Unicode characters
- */
- public char[] getSubsetChars() {
+ /** {@inheritDoc} */
+ public char[] getChars() {
char[] charArray = new char[usedGlyphsCount];
for (int i = 0; i < usedGlyphsCount; i++) {
- charArray[i] = getUnicodeForSubsetIndex(i);
+ charArray[i] = getUnicode(i);
}
return charArray;
}
- /**
- * Returns the number of glyphs in the subset.
- * @return the number of glyphs in the subset
- */
- public int getSubsetSize() {
+ /** {@inheritDoc} */
+ public int getNumberOfGlyphs() {
return this.usedGlyphsCount;
}
- /**
- * Returns a BitSet with bits set for each available glyph index in the subset.
- * @return a BitSet indicating available glyph indices
- */
- public BitSet getGlyphIndexBitSet() {
+ /** {@inheritDoc} */
+ public BitSet getGlyphIndices() {
BitSet bitset = new BitSet();
for (Integer cid : usedGlyphs.keySet()) {
- bitset.set(cid.intValue());
+ bitset.set(cid);
}
return bitset;
}
+ /** {@inheritDoc} */
+ public int[] getWidths() {
+ int[] widths = font.getWidths();
+ int[] tmpWidth = new int[getNumberOfGlyphs()];
+ for (int i = 0, c = getNumberOfGlyphs(); i < c; i++) {
+ int nwx = Math.max(0, getOriginalGlyphIndex(i));
+ tmpWidth[i] = widths[nwx];
+ }
+ return tmpWidth;
+ }
+
}
diff --git a/src/java/org/apache/fop/fonts/FontCacheManager.java b/src/java/org/apache/fop/fonts/FontCacheManager.java
index fb0a0322b..a4acd43a4 100644
--- a/src/java/org/apache/fop/fonts/FontCacheManager.java
+++ b/src/java/org/apache/fop/fonts/FontCacheManager.java
@@ -19,7 +19,7 @@
package org.apache.fop.fonts;
-import java.io.File;
+import java.net.URI;
import org.apache.fop.apps.FOPException;
@@ -30,24 +30,26 @@ import org.apache.fop.apps.FOPException;
public interface FontCacheManager {
/**
+ * Sets the font cache file given the URI pointing to the file.
+ * @param fontCacheURI the font cache URI
+ */
+ void setCacheFile(URI fontCacheURI);
+
+ /**
* Loads the font cache into memory from the given file.
- * @param file the serialized font cache
* @return the de-serialized font cache
*/
- FontCache load(File file);
+ FontCache load();
/**
* Serializes the font cache to file.
- * @param file the file to serialize the font cache to
* @throws FOPException if an error occurs serializing the font cache
*/
- void save(File file) throws FOPException;
+ void save() throws FOPException;
/**
* Deletes the font cache from the file-system.
- * @param file delete the serialized font cache
* @throws FOPException if an error occurs deleting the font cache
*/
- void delete(File file) throws FOPException;
-
+ void delete() throws FOPException;
}
diff --git a/src/java/org/apache/fop/fonts/FontCacheManagerFactory.java b/src/java/org/apache/fop/fonts/FontCacheManagerFactory.java
index 0236effce..c1d736b0d 100644
--- a/src/java/org/apache/fop/fonts/FontCacheManagerFactory.java
+++ b/src/java/org/apache/fop/fonts/FontCacheManagerFactory.java
@@ -20,6 +20,7 @@
package org.apache.fop.fonts;
import java.io.File;
+import java.net.URI;
import org.apache.fop.apps.FOPException;
@@ -50,11 +51,14 @@ public final class FontCacheManagerFactory {
private static final class FontCacheManagerImpl implements FontCacheManager {
+ /** Provides a font cache file path **/
+ private File cacheFile;
+
private FontCache fontCache;
- public FontCache load(File cacheFile) {
+ public FontCache load() {
if (fontCache == null) {
- fontCache = FontCache.loadFrom(cacheFile);
+ fontCache = FontCache.loadFrom(getCacheFile(false));
if (fontCache == null) {
fontCache = new FontCache();
}
@@ -62,31 +66,46 @@ public final class FontCacheManagerFactory {
return fontCache;
}
- public void save(File cacheFile) throws FOPException {
+ public void save() throws FOPException {
if (fontCache != null && fontCache.hasChanged()) {
- fontCache.saveTo(cacheFile);
+ fontCache.saveTo(getCacheFile(true));
}
}
- public void delete(File cacheFile) throws FOPException {
- if (!cacheFile.delete()) {
+ public void delete() throws FOPException {
+ if (!getCacheFile(true).delete()) {
throw new FOPException("Failed to flush the font cache file '" + cacheFile + "'.");
}
}
+
+ private File getCacheFile(boolean forWriting) {
+ if (cacheFile != null) {
+ return cacheFile;
+ }
+ return FontCache.getDefaultCacheFile(forWriting);
+ }
+
+ public void setCacheFile(URI fontCacheURI) {
+ cacheFile = new File(fontCacheURI);
+ }
}
private static final class DisabledFontCacheManager implements FontCacheManager {
- public FontCache load(File cacheFile) {
+ public FontCache load() {
return null;
}
- public void save(File cacheFile) throws FOPException {
+ public void save() throws FOPException {
// nop
}
- public void delete(File cacheFile) throws FOPException {
+ public void delete() throws FOPException {
throw new FOPException("Font Cache disabled");
}
+
+ public void setCacheFile(URI fontCacheURI) {
+ // nop
+ }
}
}
diff --git a/src/java/org/apache/fop/fonts/FontManager.java b/src/java/org/apache/fop/fonts/FontManager.java
index bff001f73..3df8a9078 100644
--- a/src/java/org/apache/fop/fonts/FontManager.java
+++ b/src/java/org/apache/fop/fonts/FontManager.java
@@ -19,7 +19,7 @@
package org.apache.fop.fonts;
-import java.io.File;
+import java.net.URI;
import java.util.List;
import org.apache.fop.apps.FOPException;
@@ -52,9 +52,6 @@ public class FontManager {
/** FontTriplet matcher for fonts that shall be referenced rather than embedded. */
private FontTriplet.Matcher referencedFontsMatcher;
- /** Provides a font cache file path **/
- private File cacheFile;
-
/**
* Main constructor
*
@@ -115,25 +112,10 @@ public class FontManager {
/**
* Sets the font cache file
- * @param cacheFile the font cache file
- */
- public void setCacheFile(File cacheFile) {
- this.cacheFile = cacheFile;
- }
-
- /**
- * Returns the font cache file
- * @return the font cache file
+ * @param cacheFileURI the URI of the font cache file
*/
- public File getCacheFile() {
- return getCacheFile(false);
- }
-
- private File getCacheFile(boolean writable) {
- if (cacheFile != null) {
- return cacheFile;
- }
- return FontCache.getDefaultCacheFile(writable);
+ public void setCacheFile(URI cacheFileURI) {
+ fontCacheManager.setCacheFile(resourceResolver.resolveFromBase(cacheFileURI));
}
/**
@@ -148,7 +130,7 @@ public class FontManager {
* @return the font cache
*/
public FontCache getFontCache() {
- return fontCacheManager.load(getCacheFile());
+ return fontCacheManager.load();
}
/**
@@ -157,7 +139,7 @@ public class FontManager {
* @throws FOPException fop exception
*/
public void saveCache() throws FOPException {
- fontCacheManager.save(getCacheFile());
+ fontCacheManager.save();
}
/**
@@ -165,7 +147,7 @@ public class FontManager {
* @throws FOPException if an error was thrown while deleting the cache
*/
public void deleteCache() throws FOPException {
- fontCacheManager.delete(getCacheFile(true));
+ fontCacheManager.delete();
}
/**
diff --git a/src/java/org/apache/fop/fonts/FontManagerConfigurator.java b/src/java/org/apache/fop/fonts/FontManagerConfigurator.java
index c4fe19444..fc2ce06a6 100644
--- a/src/java/org/apache/fop/fonts/FontManagerConfigurator.java
+++ b/src/java/org/apache/fop/fonts/FontManagerConfigurator.java
@@ -19,7 +19,6 @@
package org.apache.fop.fonts;
-import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
@@ -30,9 +29,10 @@ import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.xmlgraphics.io.ResourceResolver;
+
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.io.InternalResourceResolver;
-import org.apache.fop.apps.io.ResourceResolver;
import org.apache.fop.apps.io.ResourceResolverFactory;
import org.apache.fop.fonts.substitute.FontSubstitutions;
import org.apache.fop.fonts.substitute.FontSubstitutionsConfigurator;
@@ -72,6 +72,19 @@ public class FontManagerConfigurator {
* @throws FOPException if an exception occurs while processing the configuration
*/
public void configure(FontManager fontManager, boolean strict) throws FOPException {
+ if (cfg.getChild("font-base", false) != null) {
+ try {
+ URI fontBase = InternalResourceResolver.getBaseURI(cfg.getChild("font-base")
+ .getValue(null));
+ fontManager.setResourceResolver(ResourceResolverFactory.createInternalResourceResolver(
+ defaultBaseUri.resolve(fontBase), resourceResolver));
+ } catch (URISyntaxException use) {
+ LogUtil.handleException(log, use, true);
+ }
+ } else {
+ fontManager.setResourceResolver(ResourceResolverFactory.createInternalResourceResolver(
+ defaultBaseUri, resourceResolver));
+ }
// caching (fonts)
if (cfg.getChild("use-cache", false) != null) {
try {
@@ -79,27 +92,14 @@ public class FontManagerConfigurator {
fontManager.disableFontCache();
} else {
if (cfg.getChild("cache-file", false) != null) {
- fontManager.setCacheFile(new File(cfg.getChild("cache-file").getValue()));
+
+ fontManager.setCacheFile(URI.create(cfg.getChild("cache-file").getValue()));
}
}
} catch (ConfigurationException mfue) {
LogUtil.handleException(log, mfue, true);
}
}
- if (cfg.getChild("font-base", false) != null) {
- try {
- URI fontBase = InternalResourceResolver.getBaseURI(cfg.getChild("font-base").getValue(
- null));
- fontManager.setResourceResolver(ResourceResolverFactory.createInternalResourceResolver(
- defaultBaseUri.resolve(fontBase), resourceResolver));
- } catch (URISyntaxException use) {
- LogUtil.handleException(log, use, true);
- }
- } else {
- fontManager.setResourceResolver(ResourceResolverFactory.createInternalResourceResolver(
- defaultBaseUri, resourceResolver));
- }
-
// [GA] permit configuration control over base14 kerning; without this,
// there is no way for a user to enable base14 kerning other than by
// programmatic API;
diff --git a/src/java/org/apache/fop/fonts/FontReader.java b/src/java/org/apache/fop/fonts/FontReader.java
index 68c5c7177..0448c317e 100644
--- a/src/java/org/apache/fop/fonts/FontReader.java
+++ b/src/java/org/apache/fop/fonts/FontReader.java
@@ -157,7 +157,7 @@ public class FontReader extends DefaultHandler {
throws SAXException {
if (localName.equals("font-metrics")) {
if ("TYPE0".equals(attributes.getValue("type"))) {
- multiFont = new MultiByteFont(resourceResolver);
+ multiFont = new MultiByteFont(resourceResolver, EmbeddingMode.AUTO);
returnFont = multiFont;
isCID = true;
TTFReader.checkMetricsVersion(attributes);
diff --git a/src/java/org/apache/fop/fonts/LazyFont.java b/src/java/org/apache/fop/fonts/LazyFont.java
index 4c42387f2..fef42f74c 100644
--- a/src/java/org/apache/fop/fonts/LazyFont.java
+++ b/src/java/org/apache/fop/fonts/LazyFont.java
@@ -438,6 +438,9 @@ public class LazyFont extends Typeface implements FontDescriptor, Substitutable,
*/
public boolean isSubsetEmbedded() {
load(true);
+ if (realFont.isMultiByte() && this.embeddingMode == EmbeddingMode.FULL) {
+ return false;
+ }
return realFont.isMultiByte();
}
diff --git a/src/java/org/apache/fop/fonts/MultiByteFont.java b/src/java/org/apache/fop/fonts/MultiByteFont.java
index a460140cb..da454c504 100644
--- a/src/java/org/apache/fop/fonts/MultiByteFont.java
+++ b/src/java/org/apache/fop/fonts/MultiByteFont.java
@@ -21,6 +21,7 @@ package org.apache.fop.fonts;
import java.nio.CharBuffer;
import java.nio.IntBuffer;
+import java.util.BitSet;
import java.util.Map;
import org.apache.commons.logging.Log;
@@ -44,13 +45,13 @@ public class MultiByteFont extends CIDFont implements Substitutable, Positionabl
private static final Log log // CSOK: ConstantNameCheck
= LogFactory.getLog(MultiByteFont.class);
- private String ttcName = null;
+ private String ttcName;
private String encoding = "Identity-H";
- private int defaultWidth = 0;
+ private int defaultWidth;
private CIDFontType cidType = CIDFontType.CIDTYPE2;
- private CIDSubset subset = new CIDSubset();
+ private final CIDSet cidSet;
/* advanced typographic support */
private GlyphDefinitionTable gdef;
@@ -69,10 +70,15 @@ public class MultiByteFont extends CIDFont implements Substitutable, Positionabl
/**
* Default constructor
*/
- public MultiByteFont(InternalResourceResolver resourceResolver) {
+ public MultiByteFont(InternalResourceResolver resourceResolver, EmbeddingMode embeddingMode) {
super(resourceResolver);
- subset.setupFirstGlyph();
setFontType(FontType.TYPE0);
+ setEmbeddingMode(embeddingMode);
+ if (embeddingMode != EmbeddingMode.FULL) {
+ cidSet = new CIDSubset(this);
+ } else {
+ cidSet = new CIDFull(this);
+ }
}
/** {@inheritDoc} */
@@ -129,13 +135,16 @@ public class MultiByteFont extends CIDFont implements Substitutable, Positionabl
}
public boolean isSubsetEmbedded() {
+ if (getEmbeddingMode() == EmbeddingMode.FULL) {
+ return false;
+ }
return true;
}
/** {@inheritDoc} */
@Override
- public CIDSubset getCIDSubset() {
- return this.subset;
+ public CIDSet getCIDSet() {
+ return this.cidSet;
}
/** {@inheritDoc} */
@@ -147,7 +156,7 @@ public class MultiByteFont extends CIDFont implements Substitutable, Positionabl
/** {@inheritDoc} */
public int getWidth(int i, int size) {
if (isEmbeddable()) {
- int glyphIndex = subset.getGlyphIndexForSubsetIndex(i);
+ int glyphIndex = cidSet.getOriginalGlyphIndex(i);
return size * width[glyphIndex];
} else {
return size * width[i];
@@ -283,9 +292,39 @@ public class MultiByteFont extends CIDFont implements Substitutable, Positionabl
glyphIndex = findGlyphIndex(Typeface.NOT_FOUND);
}
if (isEmbeddable()) {
- glyphIndex = subset.mapSubsetChar(glyphIndex, c);
+ glyphIndex = cidSet.mapChar(glyphIndex, c);
}
- return (char)glyphIndex;
+ return (char) glyphIndex;
+ }
+
+ protected BitSet getGlyphIndices() {
+ BitSet bitset = new BitSet();
+ bitset.set(0);
+ bitset.set(1);
+ bitset.set(2);
+ for (int i = 0; i < cmap.length; i++) {
+ int start = cmap[i].getUnicodeStart();
+ int end = cmap[i].getUnicodeEnd();
+ int glyphIndex = cmap[i].getGlyphStartIndex();
+ while (start++ < end + 1) {
+ bitset.set(glyphIndex++);
+ }
+ }
+ return bitset;
+ }
+
+ protected char[] getChars() {
+ // the width array is set when the font is built
+ char[] chars = new char[width.length];
+ for (int i = 0; i < cmap.length; i++) {
+ int start = cmap[i].getUnicodeStart();
+ int end = cmap[i].getUnicodeEnd();
+ int glyphIndex = cmap[i].getGlyphStartIndex();
+ while (start < end + 1) {
+ chars[glyphIndex++] = (char) start++;
+ }
+ }
+ return chars;
}
/** {@inheritDoc} */
@@ -331,15 +370,7 @@ public class MultiByteFont extends CIDFont implements Substitutable, Positionabl
* @return Map Map of used Glyphs
*/
public Map<Integer, Integer> getUsedGlyphs() {
- return subset.getSubsetGlyphs();
- }
-
- /** @return an array of the chars used */
- public char[] getCharsUsed() {
- if (!isEmbeddable()) {
- return null;
- }
- return subset.getSubsetChars();
+ return cidSet.getGlyphs();
}
/**
diff --git a/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java b/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java
index c97b17211..a427fe54e 100644
--- a/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java
+++ b/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java
@@ -127,7 +127,7 @@ public class TTFFontLoader extends FontLoader {
}
if (isCid) {
- multiFont = new MultiByteFont(resourceResolver);
+ multiFont = new MultiByteFont(resourceResolver, embeddingMode);
returnFont = multiFont;
multiFont.setTTCName(ttcFontName);
} else {
diff --git a/src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java b/src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java
index 022ff462f..3aa340a4a 100644
--- a/src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java
+++ b/src/java/org/apache/fop/image/loader/batik/PreloaderSVG.java
@@ -45,6 +45,7 @@ import org.apache.xmlgraphics.image.loader.ImageSize;
import org.apache.xmlgraphics.image.loader.impl.AbstractImagePreloader;
import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM;
import org.apache.xmlgraphics.image.loader.util.ImageUtil;
+import org.apache.xmlgraphics.io.XmlSourceUtil;
import org.apache.xmlgraphics.util.MimeConstants;
import org.apache.xmlgraphics.util.UnitConv;
@@ -79,7 +80,7 @@ public class PreloaderSVG extends AbstractImagePreloader {
}
}
if (info != null) {
- ImageUtil.closeQuietly(src); //Image is fully read
+ XmlSourceUtil.closeQuietly(src); //Image is fully read
}
return info;
}
@@ -119,7 +120,7 @@ public class PreloaderSVG extends AbstractImagePreloader {
DOMSource domSrc = (DOMSource)src;
doc = (SVGDocument)domSrc.getNode();
} else {
- in = new UnclosableInputStream(ImageUtil.needInputStream(src));
+ in = new UnclosableInputStream(XmlSourceUtil.needInputStream(src));
int length = in.available();
in.mark(length + 1);
SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory(
diff --git a/src/java/org/apache/fop/image/loader/batik/PreloaderWMF.java b/src/java/org/apache/fop/image/loader/batik/PreloaderWMF.java
index 3bef0f41d..43341cbe6 100644
--- a/src/java/org/apache/fop/image/loader/batik/PreloaderWMF.java
+++ b/src/java/org/apache/fop/image/loader/batik/PreloaderWMF.java
@@ -38,6 +38,7 @@ import org.apache.xmlgraphics.image.loader.ImageInfo;
import org.apache.xmlgraphics.image.loader.ImageSize;
import org.apache.xmlgraphics.image.loader.impl.AbstractImagePreloader;
import org.apache.xmlgraphics.image.loader.util.ImageUtil;
+import org.apache.xmlgraphics.io.XmlSourceUtil;
import org.apache.fop.util.UnclosableInputStream;
@@ -69,7 +70,7 @@ public class PreloaderWMF extends AbstractImagePreloader {
}
}
if (info != null) {
- ImageUtil.closeQuietly(src); //Image is fully read
+ XmlSourceUtil.closeQuietly(src); //Image is fully read
}
return info;
}
@@ -88,7 +89,7 @@ public class PreloaderWMF extends AbstractImagePreloader {
ImageContext context) {
// parse document and get the size attributes of the svg element
- InputStream in = new UnclosableInputStream(ImageUtil.needInputStream(src));
+ InputStream in = new UnclosableInputStream(XmlSourceUtil.needInputStream(src));
try {
in.mark(4 + 1);
diff --git a/src/java/org/apache/fop/layoutmgr/AbstractBaseLayoutManager.java b/src/java/org/apache/fop/layoutmgr/AbstractBaseLayoutManager.java
index 8c213d7d5..5d7cc0b64 100644
--- a/src/java/org/apache/fop/layoutmgr/AbstractBaseLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/AbstractBaseLayoutManager.java
@@ -273,4 +273,11 @@ public abstract class AbstractBaseLayoutManager
throw new UnsupportedOperationException("Not implemented");
}
+ public void preserveChildrenAtEndOfLayout() {
+
+ }
+
+ public void recreateChildrenLMs() {
+
+ }
}
diff --git a/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java b/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java
index 0089f228f..3d64c436c 100644
--- a/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java
@@ -37,6 +37,7 @@ import org.apache.fop.fo.FONode;
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.flow.Marker;
import org.apache.fop.fo.flow.RetrieveMarker;
+import org.apache.fop.layoutmgr.table.TableLayoutManager;
/**
* The base class for most LayoutManagers.
@@ -67,6 +68,8 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager im
private int lastGeneratedPosition = -1;
private int smallestPosNumberChecked = Integer.MAX_VALUE;
+ private boolean preserveChildrenAtEndOfLayout;
+
/**
* Abstract layout manager.
*/
@@ -370,19 +373,20 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager im
}
/**
- * Registers the FO's markers on the current PageViewport
+ * Registers the FO's markers on the current PageViewport, and if applicable on the parent TableLM.
*
* @param isStarting boolean indicating whether the markers qualify as 'starting'
* @param isFirst boolean indicating whether the markers qualify as 'first'
* @param isLast boolean indicating whether the markers qualify as 'last'
*/
- protected void addMarkersToPage(boolean isStarting, boolean isFirst, boolean isLast) {
+ protected void registerMarkers(boolean isStarting, boolean isFirst, boolean isLast) {
if (this.markers != null) {
- getCurrentPV().addMarkers(
+ getCurrentPV().registerMarkers(
this.markers,
isStarting,
isFirst,
isLast);
+ possiblyRegisterMarkersForTables(markers, isStarting, isFirst, isLast);
}
}
@@ -419,11 +423,12 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager im
notifyEndOfLayout();
- /* References to the child LMs are no longer needed
- */
- childLMs = null;
- curChildLM = null;
- childLMiter = null;
+ if (!preserveChildrenAtEndOfLayout) {
+ // References to the child LMs are no longer needed
+ childLMs = null;
+ curChildLM = null;
+ childLMiter = null;
+ }
/* markers that qualify have been transferred to the page
*/
@@ -438,13 +443,21 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager im
|| lm instanceof PageSequenceLayoutManager)) {
lm = lm.getParent();
}
- if (lm instanceof FlowLayoutManager) {
+ if (lm instanceof FlowLayoutManager && !preserveChildrenAtEndOfLayout) {
fobj.clearChildNodes();
fobjIter = null;
}
}
}
+ /*
+ * Preserves the children LMs at the end of layout. This is necessary if the layout is expected to be
+ * repeated, as when using retrieve-table-markers.
+ */
+ public void preserveChildrenAtEndOfLayout() {
+ preserveChildrenAtEndOfLayout = true;
+ }
+
/** {@inheritDoc} */
@Override
public String toString() {
@@ -467,4 +480,34 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager im
lastGeneratedPosition = -1;
}
+ public void recreateChildrenLMs() {
+ childLMs = new ArrayList();
+ isFinished = false;
+ if (fobj == null) {
+ return;
+ }
+ fobjIter = fobj.getChildNodes();
+ int position = 0;
+ while (createNextChildLMs(position++)) {
+ //
+ }
+ childLMiter = new LMiter(this);
+ for (LMiter iter = new LMiter(this); iter.hasNext();) {
+ AbstractBaseLayoutManager alm = (AbstractBaseLayoutManager) iter.next();
+ alm.initialize();
+ alm.recreateChildrenLMs();
+ alm.preserveChildrenAtEndOfLayout();
+ }
+ curChildLM = getChildLM();
+ }
+
+ protected void possiblyRegisterMarkersForTables(Map<String, Marker> markers, boolean isStarting,
+ boolean isFirst, boolean isLast) {
+ LayoutManager lm = this.parentLayoutManager;
+ if (lm instanceof FlowLayoutManager || lm instanceof PageSequenceLayoutManager
+ || !(lm instanceof AbstractLayoutManager)) {
+ return;
+ }
+ ((AbstractLayoutManager) lm).possiblyRegisterMarkersForTables(markers, isStarting, isFirst, isLast);
+ }
}
diff --git a/src/java/org/apache/fop/layoutmgr/AbstractPageSequenceLayoutManager.java b/src/java/org/apache/fop/layoutmgr/AbstractPageSequenceLayoutManager.java
index f36cde158..edfb389ed 100644
--- a/src/java/org/apache/fop/layoutmgr/AbstractPageSequenceLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/AbstractPageSequenceLayoutManager.java
@@ -226,15 +226,14 @@ public abstract class AbstractPageSequenceLayoutManager extends AbstractLayoutMa
public RetrieveMarker resolveRetrieveMarker(RetrieveMarker rm) {
AreaTreeModel areaTreeModel = areaTreeHandler.getAreaTreeModel();
String name = rm.getRetrieveClassName();
- int pos = rm.getRetrievePosition();
int boundary = rm.getRetrieveBoundary();
// get marker from the current markers on area tree
- Marker mark = (Marker)getCurrentPV().getMarker(name, pos);
+ Marker mark = getCurrentPV().resolveMarker(rm);
if (mark == null && boundary != EN_PAGE) {
// go back over pages until mark found
// if document boundary then keep going
- boolean doc = boundary == EN_DOCUMENT;
+ boolean doc = (boundary == EN_DOCUMENT);
int seq = areaTreeModel.getPageSequenceCount();
int page = areaTreeModel.getPageCount(seq) - 1;
while (page < 0 && doc && seq > 1) {
@@ -243,7 +242,11 @@ public abstract class AbstractPageSequenceLayoutManager extends AbstractLayoutMa
}
while (page >= 0) {
PageViewport pv = areaTreeModel.getPage(seq, page);
- mark = (Marker)pv.getMarker(name, Constants.EN_LEWP);
+ int originalPosition = rm.getPosition();
+ rm.changePositionTo(Constants.EN_LEWP);
+ mark = (Marker) pv.resolveMarker(rm);
+ // this is probably not necessary since the RM will not be used again, but to be safe...
+ rm.changePositionTo(originalPosition);
if (mark != null) {
break;
}
diff --git a/src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java b/src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java
index c80982cce..0ed6cb69b 100644
--- a/src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java
+++ b/src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java
@@ -87,7 +87,7 @@ public final class AreaAdditionUtil {
}
if (bslm != null) {
- bslm.addMarkersToPage(
+ bslm.registerMarkers(
true,
bslm.isFirst(firstPos),
bslm.isLast(lastPos));
@@ -114,11 +114,10 @@ public final class AreaAdditionUtil {
}
if (bslm != null) {
- bslm.addMarkersToPage(
+ bslm.registerMarkers(
false,
bslm.isFirst(firstPos),
bslm.isLast(lastPos));
- bslm.checkEndOfLayout(lastPos);
}
diff --git a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java
index 920589657..d20215151 100644
--- a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java
@@ -806,7 +806,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager impl
addId();
- addMarkersToPage(true, isFirst(firstPos), isLast(lastPos));
+ registerMarkers(true, isFirst(firstPos), isLast(lastPos));
if (bcpos == null) {
// the Positions in positionList were inside the elements
@@ -826,7 +826,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager impl
bcpos.getBreaker().addContainedAreas(layoutContext);
}
- addMarkersToPage(false, isFirst(firstPos), isLast(lastPos));
+ registerMarkers(false, isFirst(firstPos), isLast(lastPos));
TraitSetter.addSpaceBeforeAfter(viewportBlockArea, layoutContext.getSpaceAdjust(),
effSpaceBefore, effSpaceAfter);
diff --git a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java
index a99b45620..f62d7f946 100644
--- a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java
@@ -312,7 +312,7 @@ public class BlockLayoutManager extends BlockStackingLayoutManager implements Co
addId();
- addMarkersToPage(true, isFirst(firstPos), isLast(lastPos));
+ registerMarkers(true, isFirst(firstPos), isLast(lastPos));
// the Positions in positionList were inside the elements
// created by the LineLM
@@ -327,7 +327,7 @@ public class BlockLayoutManager extends BlockStackingLayoutManager implements Co
childLM.addAreas(childPosIter, lc);
}
- addMarkersToPage(false, isFirst(firstPos), isLast(lastPos));
+ registerMarkers(false, isFirst(firstPos), isLast(lastPos));
TraitSetter.addSpaceBeforeAfter(curBlockArea, layoutContext.getSpaceAdjust(),
effSpaceBefore, effSpaceAfter);
diff --git a/src/java/org/apache/fop/layoutmgr/BreakElement.java b/src/java/org/apache/fop/layoutmgr/BreakElement.java
index 77e7f140b..f3f173d8c 100644
--- a/src/java/org/apache/fop/layoutmgr/BreakElement.java
+++ b/src/java/org/apache/fop/layoutmgr/BreakElement.java
@@ -21,6 +21,8 @@ package org.apache.fop.layoutmgr;
import java.util.List;
+import org.apache.fop.fo.Constants;
+
/**
* This class represents an unresolved break possibility.
*/
@@ -28,7 +30,7 @@ public class BreakElement extends UnresolvedListElement {
private int penaltyWidth;
private int penaltyValue;
- private int breakClass = -1;
+ private int breakClass;
private List pendingBeforeMarks;
private List pendingAfterMarks;
@@ -39,7 +41,7 @@ public class BreakElement extends UnresolvedListElement {
* @param context the layout context which contains the pending conditional elements
*/
public BreakElement(Position position, int penaltyValue, LayoutContext context) {
- this(position, penaltyValue, -1, context);
+ this(position, penaltyValue, Constants.EN_AUTO, context);
}
/**
@@ -80,7 +82,7 @@ public class BreakElement extends UnresolvedListElement {
super(position);
this.penaltyWidth = penaltyWidth;
this.penaltyValue = penaltyValue;
- this.breakClass = breakClass;
+ setBreakClass(breakClass);
this.pendingBeforeMarks = context.getPendingBeforeMarks();
this.pendingAfterMarks = context.getPendingAfterMarks();
}
@@ -142,13 +144,24 @@ public class BreakElement extends UnresolvedListElement {
*
* @param breakClass one of
* {@link org.apache.fop.fo.Constants#EN_AUTO},
+ * {@link org.apache.fop.fo.Constants#EN_LINE},
* {@link org.apache.fop.fo.Constants#EN_COLUMN},
* {@link org.apache.fop.fo.Constants#EN_PAGE},
* {@link org.apache.fop.fo.Constants#EN_EVEN_PAGE},
* {@link org.apache.fop.fo.Constants#EN_ODD_PAGE}.
*/
public void setBreakClass(int breakClass) {
- this.breakClass = breakClass;
+ switch (breakClass) {
+ case Constants.EN_AUTO:
+ case Constants.EN_LINE:
+ case Constants.EN_COLUMN:
+ case Constants.EN_PAGE:
+ case Constants.EN_EVEN_PAGE:
+ case Constants.EN_ODD_PAGE:
+ this.breakClass = breakClass;
+ break;
+ default: throw new IllegalArgumentException("Illegal value for break class: " + breakClass);
+ }
}
/** @return the pending border and padding elements at the before edge */
diff --git a/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java b/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java
index 76a1cb9e4..5f4aa5725 100644
--- a/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java
+++ b/src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java
@@ -31,6 +31,7 @@ import org.apache.commons.logging.LogFactory;
import org.apache.fop.area.AreaTreeHandler;
import org.apache.fop.fo.FOElementMapping;
import org.apache.fop.fo.FONode;
+import org.apache.fop.fo.FONode.FONodeIterator;
import org.apache.fop.fo.FOText;
import org.apache.fop.fo.FObjMixed;
import org.apache.fop.fo.extensions.ExternalDocument;
@@ -117,7 +118,7 @@ public class LayoutManagerMapping implements LayoutManagerMaker {
registerMaker(Block.class, new BlockLayoutManagerMaker());
registerMaker(Leader.class, new LeaderLayoutManagerMaker());
registerMaker(RetrieveMarker.class, new RetrieveMarkerLayoutManagerMaker());
- registerMaker(RetrieveTableMarker.class, new Maker());
+ registerMaker(RetrieveTableMarker.class, new RetrieveTableMarkerLayoutManagerMaker());
registerMaker(Character.class, new CharacterLayoutManagerMaker());
registerMaker(ExternalGraphic.class,
new ExternalGraphicLayoutManagerMaker());
@@ -407,6 +408,24 @@ public class LayoutManagerMapping implements LayoutManagerMaker {
}
}
+ public class RetrieveTableMarkerLayoutManagerMaker extends Maker {
+ public void make(FONode node, List lms) {
+ FONodeIterator baseIter = node.getChildNodes();
+ if (baseIter == null) {
+ // this happens when the retrieve-table-marker cannot be resolved yet
+ RetrieveTableMarker rtm = (RetrieveTableMarker) node;
+ RetrieveTableMarkerLayoutManager rtmlm = new RetrieveTableMarkerLayoutManager(rtm);
+ lms.add(rtmlm);
+ return;
+ }
+ while (baseIter.hasNext()) {
+ // this happens when the retrieve-table-marker has been resolved
+ FONode child = (FONode) baseIter.next();
+ makeLayoutManagers(child, lms);
+ }
+ }
+ }
+
/** a layout manager maker */
public class WrapperLayoutManagerMaker extends Maker {
/** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/layoutmgr/LocalBreaker.java b/src/java/org/apache/fop/layoutmgr/LocalBreaker.java
new file mode 100644
index 000000000..bb08446cc
--- /dev/null
+++ b/src/java/org/apache/fop/layoutmgr/LocalBreaker.java
@@ -0,0 +1,137 @@
+/*
+ * 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.layoutmgr;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.fop.fo.FObj;
+import org.apache.fop.layoutmgr.PageBreakingAlgorithm.PageBreakingLayoutListener;
+import org.apache.fop.layoutmgr.inline.TextLayoutManager;
+
+public abstract class LocalBreaker extends AbstractBreaker {
+ protected BlockStackingLayoutManager lm;
+ private int displayAlign;
+ private int ipd;
+ private int overflow = 0;
+
+ public LocalBreaker(BlockStackingLayoutManager lm, int ipd, int displayAlign) {
+ this.lm = lm;
+ this.ipd = ipd;
+ this.displayAlign = displayAlign;
+ }
+
+ /** {@inheritDoc} */
+ protected boolean isPartOverflowRecoveryActivated() {
+ // For side regions, this must be disabled because of wanted overflow.
+ return false;
+ }
+
+ public boolean isOverflow() {
+ return (this.overflow != 0);
+ }
+
+ public int getOverflowAmount() {
+ return this.overflow;
+ }
+
+ /** {@inheritDoc} */
+ protected PageBreakingLayoutListener createLayoutListener() {
+ return new PageBreakingLayoutListener() {
+
+ public void notifyOverflow(int part, int amount, FObj obj) {
+ if (LocalBreaker.this.overflow == 0) {
+ LocalBreaker.this.overflow = amount;
+ }
+ }
+
+ };
+ }
+
+ protected LayoutManager getTopLevelLM() {
+ return lm;
+ }
+
+ protected LayoutContext createLayoutContext() {
+ LayoutContext lc = super.createLayoutContext();
+ lc.setRefIPD(ipd);
+ return lc;
+ }
+
+ protected List getNextKnuthElements(LayoutContext context, int alignment) {
+ LayoutManager curLM; // currently active LM
+ List returnList = new LinkedList();
+
+ while ((curLM = lm.getChildLM()) != null) {
+ LayoutContext childLC = LayoutContext.newInstance();
+ childLC.setStackLimitBP(context.getStackLimitBP());
+ childLC.setRefIPD(context.getRefIPD());
+ childLC.setWritingMode(context.getWritingMode());
+
+ List returnedList = null;
+ // The following is a HACK! Ignore leading and trailing white space
+ boolean ignore = curLM instanceof TextLayoutManager;
+ if (!curLM.isFinished()) {
+ returnedList = curLM.getNextKnuthElements(childLC, alignment);
+ }
+ if (returnedList != null && !ignore) {
+ lm.wrapPositionElements(returnedList, returnList);
+ }
+ }
+ SpaceResolver.resolveElementList(returnList);
+ lm.setFinished(true);
+ return returnList;
+ }
+
+ protected int getCurrentDisplayAlign() {
+ return displayAlign;
+ }
+
+ protected boolean hasMoreContent() {
+ return !lm.isFinished();
+ }
+
+ protected void addAreas(PositionIterator posIter, LayoutContext context) {
+ AreaAdditionUtil.addAreas(lm, posIter, context);
+ }
+
+ protected void doPhase3(PageBreakingAlgorithm alg, int partCount, BlockSequence originalList,
+ BlockSequence effectiveList) {
+ if (partCount > 1) {
+ PageBreakPosition pos = (PageBreakPosition) alg.getPageBreaks().getFirst();
+ int firstPartLength = ElementListUtils.calcContentLength(effectiveList,
+ effectiveList.ignoreAtStart, pos.getLeafPos());
+ overflow += alg.totalWidth - firstPartLength;
+ }
+ // Rendering all parts (not just the first) at once for the case where the parts that
+ // overflow should be visible.
+ alg.removeAllPageBreaks();
+ // Directly add areas after finding the breaks
+ this.addAreas(alg, 1, originalList, effectiveList);
+ }
+
+ protected void finishPart(PageBreakingAlgorithm alg, PageBreakPosition pbp) {
+ // nop for static content
+ }
+
+ protected LayoutManager getCurrentChildLM() {
+ return null; // TODO NYI
+ }
+}
diff --git a/src/java/org/apache/fop/layoutmgr/RetrieveTableMarkerLayoutManager.java b/src/java/org/apache/fop/layoutmgr/RetrieveTableMarkerLayoutManager.java
new file mode 100644
index 000000000..9d0979a29
--- /dev/null
+++ b/src/java/org/apache/fop/layoutmgr/RetrieveTableMarkerLayoutManager.java
@@ -0,0 +1,75 @@
+/*
+ * 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.layoutmgr;
+
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.fop.fo.FONode;
+import org.apache.fop.fo.flow.RetrieveTableMarker;
+import org.apache.fop.layoutmgr.inline.InlineLevelLayoutManager;
+import org.apache.fop.layoutmgr.inline.LeafNodeLayoutManager;
+import org.apache.fop.layoutmgr.table.TableLayoutManager;
+
+public class RetrieveTableMarkerLayoutManager extends LeafNodeLayoutManager {
+
+ private static Log log = LogFactory.getLog(RetrieveTableMarkerLayoutManager.class);
+
+ public RetrieveTableMarkerLayoutManager(RetrieveTableMarker node) {
+ super(node);
+ }
+
+ /** {@inheritDoc} */
+ public List getNextKnuthElements(LayoutContext context, int alignment) {
+ setFinished(true);
+ FONode foNode = (FONode) getFObj();
+ foNode = getTableLayoutManager().resolveRetrieveTableMarker((RetrieveTableMarker) foNode);
+ if (foNode != null) {
+ // resolve the RTM and replace current LM by the resolved target LM
+ InlineLevelLayoutManager illm = (InlineLevelLayoutManager) getPSLM().getLayoutManagerMaker()
+ .makeLayoutManager(foNode);
+ if (illm instanceof RetrieveTableMarkerLayoutManager) {
+ // happens if the retrieve-marker was empty
+ return null;
+ }
+ illm.setParent(getParent());
+ illm.initialize();
+ return illm.getNextKnuthElements(context, alignment);
+ } else {
+ return null;
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void addAreas(PositionIterator posIter, LayoutContext context) {
+ }
+
+ private TableLayoutManager getTableLayoutManager() {
+ LayoutManager parentLM = getParent();
+ while (!(parentLM instanceof TableLayoutManager)) {
+ parentLM = parentLM.getParent();
+ }
+ TableLayoutManager tlm = (TableLayoutManager) parentLM;
+ return tlm;
+ }
+
+}
diff --git a/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java
index 403daceb3..058b02270 100644
--- a/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java
@@ -167,125 +167,22 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager {
return (StaticContent) fobj;
}
- private class StaticContentBreaker extends AbstractBreaker {
- private StaticContentLayoutManager lm;
- private int displayAlign;
- private int ipd;
- private int overflow = 0;
-
- public StaticContentBreaker(StaticContentLayoutManager lm, int ipd,
- int displayAlign) {
- this.lm = lm;
- this.ipd = ipd;
- this.displayAlign = displayAlign;
+ private class StaticContentBreaker extends LocalBreaker {
+
+ public StaticContentBreaker(StaticContentLayoutManager lm, int ipd, int displayAlign) {
+ super(lm, ipd, displayAlign);
}
/** {@inheritDoc} */
protected void observeElementList(List elementList) {
String elementListID = getStaticContentFO().getFlowName();
- String pageSequenceID = ((PageSequence)lm.getParent().getFObj()).getId();
+ String pageSequenceID = ((PageSequence) lm.getParent().getFObj()).getId();
if (pageSequenceID != null && pageSequenceID.length() > 0) {
elementListID += "-" + pageSequenceID;
}
ElementListObserver.observe(elementList, "static-content", elementListID);
}
- /** {@inheritDoc} */
- protected boolean isPartOverflowRecoveryActivated() {
- //For side regions, this must be disabled because of wanted overflow.
- return false;
- }
-
- public boolean isOverflow() {
- return (this.overflow != 0);
- }
-
- public int getOverflowAmount() {
- return this.overflow;
- }
-
- /** {@inheritDoc} */
- protected PageBreakingLayoutListener createLayoutListener() {
- return new PageBreakingLayoutListener() {
-
- public void notifyOverflow(int part, int amount, FObj obj) {
- if (StaticContentBreaker.this.overflow == 0) {
- StaticContentBreaker.this.overflow = amount;
- }
- }
-
- };
- }
-
- protected LayoutManager getTopLevelLM() {
- return lm;
- }
-
- protected LayoutContext createLayoutContext() {
- LayoutContext lc = super.createLayoutContext();
- lc.setRefIPD(ipd);
- return lc;
- }
-
- protected List getNextKnuthElements(LayoutContext context, int alignment) {
- LayoutManager curLM; // currently active LM
- List returnList = new LinkedList();
-
- while ((curLM = getChildLM()) != null) {
- LayoutContext childLC = LayoutContext.newInstance();
- childLC.setStackLimitBP(context.getStackLimitBP());
- childLC.setRefIPD(context.getRefIPD());
- childLC.setWritingMode(context.getWritingMode());
-
- List returnedList = null;
- //The following is a HACK! Ignore leading and trailing white space
- boolean ignore = curLM instanceof TextLayoutManager;
- if (!curLM.isFinished()) {
- returnedList = curLM.getNextKnuthElements(childLC, alignment);
- }
- if (returnedList != null && !ignore) {
- lm.wrapPositionElements(returnedList, returnList);
- }
- }
- SpaceResolver.resolveElementList(returnList);
- setFinished(true);
- return returnList;
- }
-
- protected int getCurrentDisplayAlign() {
- return displayAlign;
- }
-
- protected boolean hasMoreContent() {
- return !lm.isFinished();
- }
-
- protected void addAreas(PositionIterator posIter, LayoutContext context) {
- AreaAdditionUtil.addAreas(lm, posIter, context);
- }
-
- protected void doPhase3(PageBreakingAlgorithm alg, int partCount,
- BlockSequence originalList, BlockSequence effectiveList) {
- if (partCount > 1) {
- PageBreakPosition pos = (PageBreakPosition)alg.getPageBreaks().getFirst();
- int firstPartLength = ElementListUtils.calcContentLength(effectiveList,
- effectiveList.ignoreAtStart, pos.getLeafPos());
- overflow += alg.totalWidth - firstPartLength;
- }
- //Rendering all parts (not just the first) at once for the case where the parts that
- //overflow should be visible.
- alg.removeAllPageBreaks();
- //Directly add areas after finding the breaks
- this.addAreas(alg, 1, originalList, effectiveList);
- }
-
- protected void finishPart(PageBreakingAlgorithm alg, PageBreakPosition pbp) {
- //nop for static content
- }
-
- protected LayoutManager getCurrentChildLM() {
- return null; //TODO NYI
- }
}
/**
diff --git a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java
index 77ac8c4d6..ebf7a9ccb 100644
--- a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java
@@ -480,7 +480,7 @@ public class InlineLayoutManager extends InlineStackingLayoutManager {
context.getLeadingSpace().addSpace(new SpaceVal(getSpaceStart(), this));
}
- addMarkersToPage(
+ registerMarkers(
true,
!areaCreated,
lastPos == null || isLast(lastPos));
@@ -542,7 +542,7 @@ public class InlineLayoutManager extends InlineStackingLayoutManager {
setTraits(areaCreated, lastPos == null || !isLast(lastPos));
parentLayoutManager.addChildArea(getCurrentArea());
- addMarkersToPage(
+ registerMarkers(
false,
!areaCreated,
lastPos == null || isLast(lastPos));
diff --git a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java
index 00cd427d9..ac3f8f878 100644
--- a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java
@@ -649,6 +649,10 @@ public class LineLayoutManager extends InlineStackingLayoutManager
log.trace("Restarting line breaking from index " + restartPosition.getIndex());
int parIndex = restartPosition.getLeafPos();
KnuthSequence paragraph = knuthParagraphs.get(parIndex);
+ if (paragraph instanceof Paragraph) {
+ ((Paragraph) paragraph).ignoreAtStart = 0;
+ isFirstInBlock = false;
+ }
paragraph.subList(0, restartPosition.getIndex() + 1).clear();
Iterator<KnuthElement> iter = paragraph.iterator();
while (iter.hasNext() && !iter.next().isBox()) {
diff --git a/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java
index 480934bf3..61d8a891d 100644
--- a/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java
@@ -171,7 +171,7 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager
}
}
- addMarkersToPage(true, isFirst(firstPos), isLast(lastPos));
+ registerMarkers(true, isFirst(firstPos), isLast(lastPos));
PositionIterator childPosIter = new PositionIterator(positionList.listIterator());
while ((childLM = childPosIter.getNextChildLM()) != null) {
@@ -184,7 +184,7 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager
childLM.addAreas(childPosIter, lc);
}
- addMarkersToPage(false, isFirst(firstPos), isLast(lastPos));
+ registerMarkers(false, isFirst(firstPos), isLast(lastPos));
// We are done with this area add the background
TraitSetter.addBackground(curBlockArea,
diff --git a/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java
index 3204a867e..f017da381 100644
--- a/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java
@@ -136,7 +136,7 @@ public class ListItemContentLayoutManager extends BlockStackingLayoutManager imp
}
}
- addMarkersToPage(true, isFirst(firstPos), isLast(lastPos));
+ registerMarkers(true, isFirst(firstPos), isLast(lastPos));
PositionIterator childPosIter = new PositionIterator(positionList.listIterator());
while ((childLM = childPosIter.getNextChildLM()) != null) {
@@ -149,7 +149,7 @@ public class ListItemContentLayoutManager extends BlockStackingLayoutManager imp
childLM.addAreas(childPosIter, lc);
}
- addMarkersToPage(false, isFirst(firstPos), isLast(lastPos));
+ registerMarkers(false, isFirst(firstPos), isLast(lastPos));
flush();
diff --git a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java
index 32aa4c674..083e4ee1b 100644
--- a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java
@@ -509,7 +509,7 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager implements
}
}
- addMarkersToPage(true, isFirst(firstPos), isLast(lastPos));
+ registerMarkers(true, isFirst(firstPos), isLast(lastPos));
// use the first and the last ListItemPosition to determine the
// corresponding indexes in the original labelList and bodyList
@@ -563,7 +563,7 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager implements
}
curBlockArea.setBPD(itemBPD);
- addMarkersToPage(false, isFirst(firstPos), isLast(lastPos));
+ registerMarkers(false, isFirst(firstPos), isLast(lastPos));
// We are done with this area add the background
TraitSetter.addBackground(curBlockArea,
diff --git a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java
index 955dafabd..6b0ef6ebb 100644
--- a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java
+++ b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java
@@ -303,11 +303,16 @@ class RowPainter {
borderAfterWhich = ConditionalBorder.REST;
}
+ // when adding the areas for the TableCellLayoutManager this helps with the isLast trait
+ // if, say, the first cell of a row has content that fits in the page, but the content of
+ // the second cell does not fit this will assure that the isLast trait for the first cell
+ // will also be false
+ lastCellParts[i].pgu.getCellLM().setLastTrait(lastCellParts[i].isLastPart());
addAreasForCell(firstCellParts[i].pgu,
firstCellParts[i].start, lastCellParts[i].end,
actualRowHeight, borderBeforeWhich, borderAfterWhich,
lastOnPage);
- firstCellParts[i] = null;
+ firstCellParts[i] = null; // why? what about the lastCellParts[i]?
Arrays.fill(firstCellOnPage, i, i + currentGU.getCell().getNumberColumnsSpanned(),
false);
}
diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java
index 2ca5a26d1..f810d20c5 100644
--- a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java
@@ -21,6 +21,7 @@ package org.apache.fop.layoutmgr.table;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -28,19 +29,24 @@ import org.apache.commons.logging.LogFactory;
import org.apache.fop.area.Area;
import org.apache.fop.area.Block;
import org.apache.fop.area.Trait;
+import org.apache.fop.fo.flow.Marker;
import org.apache.fop.fo.flow.table.ConditionalBorder;
import org.apache.fop.fo.flow.table.GridUnit;
import org.apache.fop.fo.flow.table.PrimaryGridUnit;
import org.apache.fop.fo.flow.table.Table;
import org.apache.fop.fo.flow.table.TableCell;
import org.apache.fop.fo.flow.table.TableColumn;
+import org.apache.fop.fo.flow.table.TableFooter;
+import org.apache.fop.fo.flow.table.TableHeader;
import org.apache.fop.fo.flow.table.TablePart;
import org.apache.fop.fo.flow.table.TableRow;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo;
+import org.apache.fop.layoutmgr.AbstractLayoutManager;
import org.apache.fop.layoutmgr.AreaAdditionUtil;
import org.apache.fop.layoutmgr.BlockLevelLayoutManager;
import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
+import org.apache.fop.layoutmgr.ElementListObserver;
import org.apache.fop.layoutmgr.ElementListUtils;
import org.apache.fop.layoutmgr.Keep;
import org.apache.fop.layoutmgr.KnuthBox;
@@ -49,8 +55,10 @@ import org.apache.fop.layoutmgr.KnuthGlue;
import org.apache.fop.layoutmgr.KnuthPenalty;
import org.apache.fop.layoutmgr.LayoutContext;
import org.apache.fop.layoutmgr.LayoutManager;
+import org.apache.fop.layoutmgr.LocalBreaker;
import org.apache.fop.layoutmgr.Position;
import org.apache.fop.layoutmgr.PositionIterator;
+import org.apache.fop.layoutmgr.RetrieveTableMarkerLayoutManager;
import org.apache.fop.layoutmgr.SpaceResolver;
import org.apache.fop.layoutmgr.TraitSetter;
import org.apache.fop.traits.BorderProps;
@@ -79,6 +87,28 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
private int totalHeight;
private int usedBPD;
private boolean emptyCell = true;
+ private boolean isDescendantOfTableFooter;
+ private boolean isDescendantOfTableHeader;
+ private boolean hasRetrieveTableMarker;
+
+ // place holder for the addAreas arguments
+ private boolean savedAddAreasArguments;
+ private PositionIterator savedParentIter;
+ private LayoutContext savedLayoutContext;
+ private int[] savedSpannedGridRowHeights;
+ private int savedStartRow;
+ private int savedEndRow;
+ private int savedBorderBeforeWhich;
+ private int savedBorderAfterWhich;
+ private boolean savedFirstOnPage;
+ private boolean savedLastOnPage;
+ private RowPainter savedPainter;
+ private int savedFirstRowHeight;
+ // this is set to false when the table-cell has a retrieve-table-marker and is in the table-header
+ private boolean flushArea = true;
+
+ // this information is set by the RowPainter
+ private boolean isLastTrait;
/**
* Create a new Cell layout manager.
@@ -88,6 +118,11 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
public TableCellLayoutManager(TableCell node, PrimaryGridUnit pgu) {
super(node);
this.primaryGridUnit = pgu;
+ this.isDescendantOfTableHeader = node.getParent().getParent() instanceof TableHeader
+ || node.getParent() instanceof TableHeader;
+ this.isDescendantOfTableFooter = node.getParent().getParent() instanceof TableFooter
+ || node.getParent() instanceof TableFooter;
+ this.hasRetrieveTableMarker = node.hasRetrieveTableMarker();
}
/** @return the table-cell FO */
@@ -248,6 +283,84 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
totalHeight = h;
}
+ private void clearRetrieveTableMarkerChildNodes(List<LayoutManager> childrenLMs) {
+ if (childrenLMs == null) {
+ return;
+ }
+ int n = childrenLMs.size();
+ for (int j = 0; j < n; j++) {
+ LayoutManager lm = (LayoutManager) childrenLMs.get(j);
+ if (lm == null) {
+ return;
+ } else if (lm instanceof RetrieveTableMarkerLayoutManager) {
+ ((AbstractLayoutManager) lm).getFObj().clearChildNodes();
+ } else {
+ List<LayoutManager> lms = lm.getChildLMs();
+ clearRetrieveTableMarkerChildNodes(lms);
+ }
+ }
+ }
+
+ /**
+ * Checks whether the associated table cell of this LM is in a table header or footer.
+ * @return true if descendant of table header or footer
+ */
+ private boolean isDescendantOfTableHeaderOrFooter() {
+ return (isDescendantOfTableFooter || isDescendantOfTableHeader);
+ }
+
+ private void saveAddAreasArguments(PositionIterator parentIter, LayoutContext layoutContext,
+ int[] spannedGridRowHeights, int startRow, int endRow, int borderBeforeWhich,
+ int borderAfterWhich, boolean firstOnPage, boolean lastOnPage, RowPainter painter,
+ int firstRowHeight) {
+ // checks for savedAddAreasArguments and isDescendantOfTableHeader were already made but repeat them
+ if (savedAddAreasArguments) {
+ return;
+ }
+ if (isDescendantOfTableHeader) {
+ savedAddAreasArguments = true;
+ savedParentIter = null /* parentIter */;
+ savedLayoutContext = null /* layoutContext */;
+ savedSpannedGridRowHeights = spannedGridRowHeights;
+ savedStartRow = startRow;
+ savedEndRow = endRow;
+ savedBorderBeforeWhich = borderBeforeWhich;
+ savedBorderAfterWhich = borderAfterWhich;
+ savedFirstOnPage = firstOnPage;
+ savedLastOnPage = lastOnPage;
+ savedPainter = painter;
+ savedFirstRowHeight = firstRowHeight;
+ TableLayoutManager parentTableLayoutManager = getTableLayoutManager();
+ parentTableLayoutManager.saveTableHeaderTableCellLayoutManagers(this);
+ // this saving is done the first time the addArea() is called; since the retrieve-table-markers
+ // cannot be resolved at this time we do not want to flush the area; the area needs nevertheless
+ // be built so that space is allocated for it.
+ flushArea = false;
+ }
+ }
+
+ private TableLayoutManager getTableLayoutManager() {
+ LayoutManager parentLM = getParent();
+ while (!(parentLM instanceof TableLayoutManager)) {
+ parentLM = parentLM.getParent();
+ }
+ TableLayoutManager tlm = (TableLayoutManager) parentLM;
+ return tlm;
+ }
+
+ /**
+ * Calls the addAreas() using the original arguments.
+ */
+ protected void repeatAddAreas() {
+ if (savedAddAreasArguments) {
+ addAreas(savedParentIter, savedLayoutContext, savedSpannedGridRowHeights, savedStartRow,
+ savedEndRow, savedBorderBeforeWhich, savedBorderAfterWhich, savedFirstOnPage,
+ savedLastOnPage, savedPainter, savedFirstRowHeight);
+ // so that the arguments of the next table fragment header can be saved
+ savedAddAreasArguments = false;
+ }
+ }
+
/**
* Add the areas for the break points. The cell contains block stacking layout
* managers that add block areas.
@@ -407,7 +520,28 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
}
}
- AreaAdditionUtil.addAreas(this, parentIter, layoutContext);
+ if (isDescendantOfTableHeaderOrFooter()) {
+ if (hasRetrieveTableMarker) {
+ if (isDescendantOfTableHeader && !savedAddAreasArguments) {
+ saveAddAreasArguments(parentIter, layoutContext, spannedGridRowHeights, startRow, endRow,
+ borderBeforeWhich, borderAfterWhich, firstOnPage, lastOnPage, painter,
+ firstRowHeight);
+ }
+ recreateChildrenLMs();
+ int displayAlign = ((TableCell) this.getFObj()).getDisplayAlign();
+ TableCellBreaker breaker = new TableCellBreaker(this, cellIPD, displayAlign);
+ breaker.doLayout(usedBPD, false);
+ // this is needed so the next time the LMs are recreated they look like the originals; this
+ // is due to the fact that during the doLayout() above the FO tree changes when the
+ // retrieve-table-markers are resolved
+ clearRetrieveTableMarkerChildNodes(getChildLMs());
+ }
+ }
+
+ // if hasRetrieveTableMarker == true the areas were already added when the re-layout was done above
+ if (!hasRetrieveTableMarker) {
+ AreaAdditionUtil.addAreas(this, parentIter, layoutContext);
+ }
// Re-adjust the cell's bpd as it may have been modified by the previous call
// for some reason (?)
curBlockArea.setBPD(cellBPD);
@@ -418,7 +552,11 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
getTableCell().getCommonBorderPaddingBackground(), this);
}
- flush();
+ if (flushArea) {
+ flush();
+ } else {
+ flushArea = true;
+ }
curBlockArea = null;
@@ -604,4 +742,49 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
return true;
}
+ private class TableCellBreaker extends LocalBreaker {
+
+ public TableCellBreaker(TableCellLayoutManager lm, int ipd, int displayAlign) {
+ super(lm, ipd, displayAlign);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void observeElementList(List elementList) {
+ String elementListID = lm.getParent().getFObj().getId() + "-" + lm.getFObj().getId();
+ ElementListObserver.observe(elementList, "table-cell", elementListID);
+ }
+
+ }
+
+ /**
+ * Registers the FO's markers on the current PageViewport and parent Table.
+ *
+ * @param isStarting boolean indicating whether the markers qualify as 'starting'
+ * @param isFirst boolean indicating whether the markers qualify as 'first'
+ * @param isLast boolean indicating whether the markers qualify as 'last'
+ */
+ protected void registerMarkers(boolean isStarting, boolean isFirst, boolean isLast) {
+ Map<String, Marker> markers = getTableCell().getMarkers();
+ if (markers != null) {
+ getCurrentPV().registerMarkers(markers, isStarting, isFirst, isLast && isLastTrait);
+ if (!isDescendantOfTableHeaderOrFooter()) {
+ getTableLayoutManager().registerMarkers(markers, isStarting, isFirst, isLast && isLastTrait);
+ }
+ }
+ }
+
+ void setLastTrait(boolean isLast) {
+ isLastTrait = isLast;
+ }
+
+ /** {@inheritDoc} */
+ public void setParent(LayoutManager lm) {
+ this.parentLayoutManager = lm;
+ if (this.hasRetrieveTableMarker) {
+ this.getTableLayoutManager().flagAsHavingRetrieveTableMarker();
+ }
+ }
+
}
diff --git a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java
index ea8774716..d423b339d 100644
--- a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java
@@ -31,9 +31,11 @@ import org.apache.commons.logging.LogFactory;
import org.apache.fop.datatypes.PercentBaseContext;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.FObj;
+import org.apache.fop.fo.flow.Marker;
import org.apache.fop.fo.flow.table.EffRow;
import org.apache.fop.fo.flow.table.PrimaryGridUnit;
import org.apache.fop.fo.flow.table.Table;
+import org.apache.fop.fo.flow.table.TableBody;
import org.apache.fop.fo.flow.table.TablePart;
import org.apache.fop.layoutmgr.BreakElement;
import org.apache.fop.layoutmgr.ElementListUtils;
@@ -400,9 +402,13 @@ public class TableContentLayoutManager implements PercentBaseContext {
}
}
- Map markers = getTableLM().getTable().getMarkers();
+ // there may be table fragment markers stored; clear them since we are starting a new fragment
+ tableLM.clearTableFragmentMarkers();
+
+ // note: markers at table level are to be retrieved by the page, not by the table itself
+ Map<String, Marker> markers = getTableLM().getTable().getMarkers();
if (markers != null) {
- getTableLM().getCurrentPV().addMarkers(markers,
+ getTableLM().getCurrentPV().registerMarkers(markers,
true, getTableLM().isFirst(firstPos), getTableLM().isLast(lastCheckPos));
}
@@ -430,6 +436,10 @@ public class TableContentLayoutManager implements PercentBaseContext {
addBodyAreas(tablePositions.iterator(), painter, footerElements == null);
}
+ // if there are TCLMs saved because they have a RetrieveTableMarker, we repeat the header areas now;
+ // this can also be done after the areas for the footer are added but should be the same as here
+ tableLM.repeatAddAreasForSavedTableHeaderTableCellLayoutManagers();
+
if (footerElements != null) {
boolean ancestorTreatAsArtifact = layoutContext.treatAsArtifact();
layoutContext.setTreatAsArtifact(treatFooterAsArtifact);
@@ -442,7 +452,7 @@ public class TableContentLayoutManager implements PercentBaseContext {
this.usedBPD += painter.getAccumulatedBPD();
if (markers != null) {
- getTableLM().getCurrentPV().addMarkers(markers,
+ getTableLM().getCurrentPV().registerMarkers(markers,
false, getTableLM().isFirst(firstPos), getTableLM().isLast(lastCheckPos));
}
}
@@ -503,14 +513,20 @@ public class TableContentLayoutManager implements PercentBaseContext {
*/
private void addTablePartAreas(List positions, RowPainter painter, TablePart body,
boolean isFirstPos, boolean isLastPos, boolean lastInBody, boolean lastOnPage) {
- getTableLM().getCurrentPV().addMarkers(body.getMarkers(),
+ getTableLM().getCurrentPV().registerMarkers(body.getMarkers(),
true, isFirstPos, isLastPos);
+ if (body instanceof TableBody) {
+ getTableLM().registerMarkers(body.getMarkers(), true, isFirstPos, isLastPos);
+ }
painter.startTablePart(body);
for (Iterator iter = positions.iterator(); iter.hasNext();) {
painter.handleTableContentPosition((TableContentPosition) iter.next());
}
- getTableLM().getCurrentPV().addMarkers(body.getMarkers(),
+ getTableLM().getCurrentPV().registerMarkers(body.getMarkers(),
false, isFirstPos, isLastPos);
+ if (body instanceof TableBody) {
+ getTableLM().registerMarkers(body.getMarkers(), false, isFirstPos, isLastPos);
+ }
painter.endTablePart(lastInBody, lastOnPage);
}
diff --git a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java
index 5a4152c69..7d4c26546 100644
--- a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java
@@ -23,6 +23,7 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -33,12 +34,16 @@ import org.apache.fop.datatypes.LengthBase;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.FObj;
+import org.apache.fop.fo.flow.Marker;
+import org.apache.fop.fo.flow.Markers;
+import org.apache.fop.fo.flow.RetrieveTableMarker;
import org.apache.fop.fo.flow.table.Table;
import org.apache.fop.fo.flow.table.TableColumn;
import org.apache.fop.fo.properties.KeepProperty;
import org.apache.fop.layoutmgr.BlockLevelEventProducer;
import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
import org.apache.fop.layoutmgr.BreakElement;
+import org.apache.fop.layoutmgr.BreakOpportunity;
import org.apache.fop.layoutmgr.ConditionalElementListener;
import org.apache.fop.layoutmgr.KnuthElement;
import org.apache.fop.layoutmgr.KnuthGlue;
@@ -62,7 +67,7 @@ import org.apache.fop.util.BreakUtil;
* the render background.
*/
public class TableLayoutManager extends BlockStackingLayoutManager
- implements ConditionalElementListener {
+ implements ConditionalElementListener, BreakOpportunity {
/**
* logging instance
@@ -92,6 +97,15 @@ public class TableLayoutManager extends BlockStackingLayoutManager
private Position auxiliaryPosition;
+ // this holds a possible list of TCLMs that needed to have their addAreas() repeated
+ private List<TableCellLayoutManager> savedTCLMs;
+ private boolean areAllTCLMsSaved;
+
+ private Markers tableMarkers;
+ private Markers tableFragmentMarkers;
+
+ private boolean hasRetrieveTableMarker;
+
/**
* Temporary holder of column background informations for a table-cell's area.
*
@@ -559,4 +573,112 @@ public class TableLayoutManager extends BlockStackingLayoutManager
tableUnit = 0.0;
}
+ /**
+ * Saves a TableCellLayoutManager for later use.
+ *
+ * @param tclm a TableCellLayoutManager that has a RetrieveTableMarker
+ */
+ protected void saveTableHeaderTableCellLayoutManagers(TableCellLayoutManager tclm) {
+ if (savedTCLMs == null) {
+ savedTCLMs = new ArrayList<TableCellLayoutManager>();
+ }
+ if (!areAllTCLMsSaved) {
+ savedTCLMs.add(tclm);
+ }
+ }
+
+ /**
+ * Calls addAreas() for each of the saved TableCellLayoutManagers.
+ */
+ protected void repeatAddAreasForSavedTableHeaderTableCellLayoutManagers() {
+ if (savedTCLMs == null) {
+ return;
+ }
+ // if we get to this stage then we are at the footer of the table fragment; this means that no more
+ // different TCLM need to be saved (we already have all); we flag the list as being complete then
+ areAllTCLMsSaved = true;
+ for (int i = 0; i < savedTCLMs.size(); i++) {
+ TableCellLayoutManager tclm = savedTCLMs.get(i);
+ tclm.repeatAddAreas();
+ }
+ }
+
+ /**
+ * Resolves a RetrieveTableMarker by finding a qualifying Marker to which it is bound to.
+ * @param rtm the RetrieveTableMarker to be resolved
+ * @return a bound RetrieveTableMarker instance or null if no qualifying Marker found
+ */
+ public RetrieveTableMarker resolveRetrieveTableMarker(RetrieveTableMarker rtm) {
+ String name = rtm.getRetrieveClassName();
+ int originalPosition = rtm.getPosition();
+ boolean changedPosition = false;
+
+ Marker mark = null;
+ // try the primary retrieve scope area, which is the same as table-fragment
+ mark = (tableFragmentMarkers == null) ? null : tableFragmentMarkers.resolve(rtm);
+ if (mark == null && rtm.getBoundary() != Constants.EN_TABLE_FRAGMENT) {
+ rtm.changePositionTo(Constants.EN_LAST_ENDING);
+ changedPosition = true;
+ // try the page scope area
+ mark = getCurrentPV().resolveMarker(rtm);
+ if (mark == null && rtm.getBoundary() != Constants.EN_PAGE) {
+ // try the table scope area
+ mark = (tableMarkers == null) ? null : tableMarkers.resolve(rtm);
+ }
+ }
+ if (changedPosition) {
+ // so that the next time it is called looks unchanged
+ rtm.changePositionTo(originalPosition);
+ }
+ if (mark == null) {
+ log.debug("found no marker with name: " + name);
+ return null;
+ } else {
+ rtm.bindMarker(mark);
+ return rtm;
+ }
+ }
+
+ /**
+ * Register the markers for this table.
+ *
+ * @param marks the map of markers to add
+ * @param starting if the area being added is starting or ending
+ * @param isfirst if the area being added has is-first trait
+ * @param islast if the area being added has is-last trait
+ */
+ public void registerMarkers(Map<String, Marker> marks, boolean starting, boolean isfirst,
+ boolean islast) {
+ if (tableMarkers == null) {
+ tableMarkers = new Markers();
+ }
+ tableMarkers.register(marks, starting, isfirst, islast);
+ if (tableFragmentMarkers == null) {
+ tableFragmentMarkers = new Markers();
+ }
+ tableFragmentMarkers.register(marks, starting, isfirst, islast);
+ }
+
+ /**
+ * Clears the list of markers in the current table fragment. Should be called just before starting a new
+ * header (that belongs to the next table fragment).
+ */
+ protected void clearTableFragmentMarkers() {
+ tableFragmentMarkers = null;
+ }
+
+ public void flagAsHavingRetrieveTableMarker() {
+ hasRetrieveTableMarker = true;
+ }
+
+ protected void possiblyRegisterMarkersForTables(Map<String, Marker> markers, boolean isStarting,
+ boolean isFirst, boolean isLast) {
+ // note: if we allow table-footer after a table-body this check should not be made and the markers
+ // should be registered regardless because the retrieval may be done only in the footer
+ if (hasRetrieveTableMarker) {
+ registerMarkers(markers, isStarting, isFirst, isLast);
+ }
+ super.possiblyRegisterMarkersForTables(markers, isStarting, isFirst, isLast);
+ }
+
}
diff --git a/src/java/org/apache/fop/pdf/PDFDocument.java b/src/java/org/apache/fop/pdf/PDFDocument.java
index e46a22c4a..0b412842f 100644
--- a/src/java/org/apache/fop/pdf/PDFDocument.java
+++ b/src/java/org/apache/fop/pdf/PDFDocument.java
@@ -355,36 +355,20 @@ public class PDFDocument {
}
/**
- * Creates and returns a structure element.
- *
- * @param structureType the structure type of the new element (value for the
- * S entry)
- * @param parent the parent of the new structure element in the structure
- * hierarchy
- * @return a dictionary of type StructElem
+ * Adds the given element to the structure tree.
*/
- public PDFStructElem makeStructureElement(StructureType structureType, PDFObject parent) {
- PDFStructElem structElem = new PDFStructElem(parent, structureType);
+ public void registerStructureElement(PDFStructElem structElem) {
assignObjectNumber(structElem);
structureTreeElements.add(structElem);
- return structElem;
}
/**
- * Creates and returns a structure element.
- *
- * @param structureType the structure type of the new element (value for the
- * S entry)
- * @param parent the parent of the new structure element in the structure
- * hierarchy
- * @param scope the scope of the given table header element
- * @return a dictionary of type StructElem
+ * Assigns the given scope to the given element and adds it to the structure tree. The
+ * scope may not be added if it's not compatible with this document's PDF version.
*/
- public PDFStructElem makeStructureElement(StructureType structureType, PDFObject parent,
- Scope scope) {
- PDFStructElem structElem = makeStructureElement(structureType, parent);
+ public void registerStructureElement(PDFStructElem structElem, Scope scope) {
+ registerStructureElement(structElem);
versionController.addTableHeaderScopeAttribute(structElem, scope);
- return structElem;
}
/**
diff --git a/src/java/org/apache/fop/pdf/PDFEncoding.java b/src/java/org/apache/fop/pdf/PDFEncoding.java
index bf2799c70..64fd6f866 100644
--- a/src/java/org/apache/fop/pdf/PDFEncoding.java
+++ b/src/java/org/apache/fop/pdf/PDFEncoding.java
@@ -23,6 +23,9 @@ package org.apache.fop.pdf;
import java.util.Collections;
import java.util.Set;
+import org.apache.fop.fonts.CodePointMapping;
+import org.apache.fop.fonts.SingleByteEncoding;
+
/**
* Class representing an /Encoding object.
*
@@ -74,6 +77,38 @@ public class PDFEncoding extends PDFDictionary {
}
/**
+ * Creates a PDFEncoding instance from a CodePointMapping instance.
+ * @param encoding the code point mapping (encoding)
+ * @param fontName ...
+ * @return the PDF Encoding dictionary (or a String with the predefined encoding)
+ */
+ static Object createPDFEncoding(SingleByteEncoding encoding, String fontName) {
+ //If encoding type is null, return null which causes /Encoding to be omitted.
+ if (encoding == null) {
+ return null;
+ }
+ String encodingName = null;
+ SingleByteEncoding baseEncoding;
+ if (fontName.indexOf("Symbol") >= 0) {
+ baseEncoding = CodePointMapping.getMapping(CodePointMapping.SYMBOL_ENCODING);
+ encodingName = baseEncoding.getName();
+ } else {
+ baseEncoding = CodePointMapping.getMapping(CodePointMapping.STANDARD_ENCODING);
+ }
+ PDFEncoding pdfEncoding = new PDFEncoding(encodingName);
+ PDFEncoding.DifferencesBuilder builder = pdfEncoding.createDifferencesBuilder();
+ PDFArray differences = builder.buildDifferencesArray(baseEncoding, encoding);
+ // TODO This method should not be returning an Object with two different outcomes
+ // resulting in subsequent `if (X instanceof Y)` statements.
+ if (differences.length() > 0) {
+ pdfEncoding.setDifferences(differences);
+ return pdfEncoding;
+ } else {
+ return encodingName;
+ }
+ }
+
+ /**
* Indicates whether a given encoding is one of the predefined encodings.
* @param name the encoding name (ex. "StandardEncoding")
* @return true if it is a predefined encoding
@@ -83,6 +118,15 @@ public class PDFEncoding extends PDFDictionary {
}
/**
+ * Indicates whether the given encoding type is that of standard encoding
+ * @param name The encoding name
+ * @return Returns true if it is of type standard encoding
+ */
+ static boolean hasStandardEncoding(String encodingName) {
+ return encodingName.equals(STANDARD_ENCODING);
+ }
+
+ /**
* Creates and returns a new DifferencesBuilder instance for constructing the Differences
* array.
* @return the DifferencesBuilder
@@ -104,18 +148,44 @@ public class PDFEncoding extends PDFDictionary {
*/
public class DifferencesBuilder {
- private PDFArray differences = new PDFArray();
private int currentCode = -1;
/**
+ * Creates an array containing the differences between two single-byte.
+ * font encodings.
+ * @param encodingA The first single-byte encoding
+ * @param encodingB The second single-byte encoding
+ * @return The PDFArray of differences between encodings
+ */
+ public PDFArray buildDifferencesArray(SingleByteEncoding encodingA,
+ SingleByteEncoding encodingB) {
+ PDFArray differences = new PDFArray();
+ int start = -1;
+ String[] baseNames = encodingA.getCharNameMap();
+ String[] charNameMap = encodingB.getCharNameMap();
+ for (int i = 0, ci = charNameMap.length; i < ci; i++) {
+ String basec = baseNames[i];
+ String c = charNameMap[i];
+ if (!basec.equals(c)) {
+ if (start != i) {
+ addDifference(i, differences);
+ start = i;
+ }
+ addName(c, differences);
+ start++;
+ }
+ }
+ return differences;
+ }
+
+ /**
* Start a new difference.
* @param code the starting code index inside the encoding
* @return this builder instance
*/
- public DifferencesBuilder addDifference(int code) {
+ private void addDifference(int code, PDFArray differences) {
this.currentCode = code;
- this.differences.add(new Integer(code));
- return this;
+ differences.add(Integer.valueOf(code));
}
/**
@@ -123,28 +193,11 @@ public class PDFEncoding extends PDFDictionary {
* @param name the character name
* @return this builder instance
*/
- public DifferencesBuilder addName(String name) {
+ private void addName(String name, PDFArray differences) {
if (this.currentCode < 0) {
throw new IllegalStateException("addDifference(int) must be called first");
}
- this.differences.add(new PDFName(name));
- return this;
- }
-
- /**
- * Indicates whether any differences have been recorded.
- * @return true if there are differences.
- */
- public boolean hasDifferences() {
- return (this.differences.length() > 0);
- }
-
- /**
- * Creates and returns the PDFArray representing the Differences entry.
- * @return the Differences entry
- */
- public PDFArray toPDFArray() {
- return this.differences;
+ differences.add(new PDFName(name));
}
}
diff --git a/src/java/org/apache/fop/pdf/PDFFactory.java b/src/java/org/apache/fop/pdf/PDFFactory.java
index 633ce9dd1..31be73a00 100644
--- a/src/java/org/apache/fop/pdf/PDFFactory.java
+++ b/src/java/org/apache/fop/pdf/PDFFactory.java
@@ -44,9 +44,9 @@ import org.apache.xmlgraphics.java2d.color.NamedColorSpace;
import org.apache.xmlgraphics.xmp.Metadata;
import org.apache.fop.fonts.CIDFont;
-import org.apache.fop.fonts.CIDSubset;
import org.apache.fop.fonts.CodePointMapping;
import org.apache.fop.fonts.CustomFont;
+import org.apache.fop.fonts.EmbeddingMode;
import org.apache.fop.fonts.FontDescriptor;
import org.apache.fop.fonts.FontMetrics;
import org.apache.fop.fonts.FontType;
@@ -1369,23 +1369,14 @@ public class PDFFactory {
} else {
cidMetrics = (CIDFont)metrics;
}
- PDFCIDSystemInfo sysInfo
- = new PDFCIDSystemInfo(cidMetrics.getRegistry(),
- cidMetrics.getOrdering(),
- cidMetrics.getSupplement());
- PDFCIDFont cidFont = new PDFCIDFont(subsetFontName,
- cidMetrics.getCIDType(),
- cidMetrics.getDefaultWidth(),
- getSubsetWidths(cidMetrics), sysInfo,
- (PDFCIDFontDescriptor)pdfdesc);
+ PDFCIDSystemInfo sysInfo = new PDFCIDSystemInfo(cidMetrics.getRegistry(),
+ cidMetrics.getOrdering(), cidMetrics.getSupplement());
+ PDFCIDFont cidFont = new PDFCIDFont(subsetFontName, cidMetrics.getCIDType(),
+ cidMetrics.getDefaultWidth(), getFontWidths(cidMetrics), sysInfo,
+ (PDFCIDFontDescriptor) pdfdesc);
getDocument().registerObject(cidFont);
-
- PDFCMap cmap = new PDFToUnicodeCMap(
- cidMetrics.getCIDSubset().getSubsetChars(),
- "fop-ucs-H",
- new PDFCIDSystemInfo("Adobe",
- "Identity",
- 0), false);
+ PDFCMap cmap = new PDFToUnicodeCMap(cidMetrics.getCIDSet().getChars(), "fop-ucs-H",
+ new PDFCIDSystemInfo("Adobe", "Identity", 0), false);
getDocument().registerObject(cmap);
((PDFFontType0)font).setCMAP(cmap);
((PDFFontType0)font).setDescendantFonts(cidFont);
@@ -1469,61 +1460,18 @@ public class PDFFactory {
/**
* Creates a PDFEncoding instance from a CodePointMapping instance.
* @param encoding the code point mapping (encoding)
- * @param fontNameHint ...
+ * @param fontName ...
* @return the PDF Encoding dictionary (or a String with the predefined encoding)
*/
- public Object createPDFEncoding(SingleByteEncoding encoding, String fontNameHint) {
- SingleByteEncoding baseEncoding;
- if (fontNameHint.indexOf("Symbol") >= 0) {
- baseEncoding = CodePointMapping.getMapping(
- CodePointMapping.SYMBOL_ENCODING);
- } else {
- baseEncoding = CodePointMapping.getMapping(
- CodePointMapping.STANDARD_ENCODING);
- }
- PDFEncoding pdfEncoding = new PDFEncoding(baseEncoding.getName());
- PDFEncoding.DifferencesBuilder builder
- = pdfEncoding.createDifferencesBuilder();
- int start = -1;
- String[] baseNames = baseEncoding.getCharNameMap();
- String[] charNameMap = encoding.getCharNameMap();
- for (int i = 0, ci = charNameMap.length; i < ci; i++) {
- String basec = baseNames[i];
- String c = charNameMap[i];
- if (!basec.equals(c)) {
- if (start != i) {
- builder.addDifference(i);
- start = i;
- }
- builder.addName(c);
- start++;
- }
- }
- if (builder.hasDifferences()) {
- pdfEncoding.setDifferences(builder.toPDFArray());
- return pdfEncoding;
- } else {
- return baseEncoding.getName();
- }
+ public Object createPDFEncoding(SingleByteEncoding encoding, String fontName) {
+ return PDFEncoding.createPDFEncoding(encoding, fontName);
}
- /**
- * Creates and returns a width array with the widths of all the characters in the subset.
- * @param cidFont the font
- * @return the width array
- */
- public PDFWArray getSubsetWidths(CIDFont cidFont) {
+ private PDFWArray getFontWidths(CIDFont cidFont) {
// Create widths for reencoded chars
PDFWArray warray = new PDFWArray();
- int[] widths = cidFont.getWidths();
- CIDSubset subset = cidFont.getCIDSubset();
- int[] tmpWidth = new int[subset.getSubsetSize()];
-
- for (int i = 0, c = subset.getSubsetSize(); i < c; i++) {
- int nwx = Math.max(0, subset.getGlyphIndexForSubsetIndex(i));
- tmpWidth[i] = widths[nwx];
- }
- warray.addEntry(0, tmpWidth);
+ int[] widths = cidFont.getCIDSet().getWidths();
+ warray.addEntry(0, widths);
return warray;
}
@@ -1591,13 +1539,13 @@ public class PDFFactory {
}
private void buildCIDSet(PDFFontDescriptor descriptor, CIDFont cidFont) {
- BitSet cidSubset = cidFont.getCIDSubset().getGlyphIndexBitSet();
- PDFStream cidSet = makeStream(null, true);
- ByteArrayOutputStream baout = new ByteArrayOutputStream(cidSubset.length() / 8 + 1);
+ BitSet cidSet = cidFont.getCIDSet().getGlyphIndices();
+ PDFStream pdfStream = makeStream(null, true);
+ ByteArrayOutputStream baout = new ByteArrayOutputStream(cidSet.length() / 8 + 1);
int value = 0;
- for (int i = 0, c = cidSubset.length(); i < c; i++) {
+ for (int i = 0, c = cidSet.length(); i < c; i++) {
int shift = i % 8;
- boolean b = cidSubset.get(i);
+ boolean b = cidSet.get(i);
if (b) {
value |= 1 << 7 - shift;
}
@@ -1608,8 +1556,8 @@ public class PDFFactory {
}
baout.write(value);
try {
- cidSet.setData(baout.toByteArray());
- descriptor.setCIDSet(cidSet);
+ pdfStream.setData(baout.toByteArray());
+ descriptor.setCIDSet(pdfStream);
} catch (IOException ioe) {
log.error(
"Failed to write CIDSet [" + cidFont + "] "
@@ -1640,14 +1588,16 @@ public class PDFFactory {
if (desc.getFontType() == FontType.TYPE0) {
MultiByteFont mbfont = (MultiByteFont) font;
FontFileReader reader = new FontFileReader(in);
-
- TTFSubSetFile subset = new TTFSubSetFile();
- subset.readFont(reader, mbfont.getTTCName(), mbfont.getUsedGlyphs());
- byte[] subsetFont = subset.getFontSubset();
- // Only TrueType CID fonts are supported now
-
- embeddedFont = new PDFTTFStream(subsetFont.length);
- ((PDFTTFStream) embeddedFont).setData(subsetFont, subsetFont.length);
+ byte[] fontBytes;
+ if (font.getEmbeddingMode() == EmbeddingMode.FULL) {
+ fontBytes = reader.getAllBytes();
+ } else {
+ TTFSubSetFile ttfFile = new TTFSubSetFile();
+ ttfFile.readFont(reader, mbfont.getTTCName(), mbfont.getUsedGlyphs());
+ fontBytes = ttfFile.getFontSubset();
+ }
+ embeddedFont = new PDFTTFStream(fontBytes.length);
+ ((PDFTTFStream) embeddedFont).setData(fontBytes, fontBytes.length);
} else if (desc.getFontType() == FontType.TYPE1) {
PFBParser parser = new PFBParser();
PFBData pfb = parser.parsePFB(in);
diff --git a/src/java/org/apache/fop/pdf/PDFFont.java b/src/java/org/apache/fop/pdf/PDFFont.java
index 191fd223e..9b9d1c129 100644
--- a/src/java/org/apache/fop/pdf/PDFFont.java
+++ b/src/java/org/apache/fop/pdf/PDFFont.java
@@ -70,7 +70,7 @@ public class PDFFont extends PDFDictionary {
* @param encoding the encoding
*/
public void setEncoding(String encoding) {
- if (encoding != null) {
+ if (encoding != null && !PDFEncoding.hasStandardEncoding(encoding)) {
put("Encoding", new PDFName(encoding));
}
}
diff --git a/src/java/org/apache/fop/pdf/PDFStructElem.java b/src/java/org/apache/fop/pdf/PDFStructElem.java
index 28cebb3ee..8250318d7 100644
--- a/src/java/org/apache/fop/pdf/PDFStructElem.java
+++ b/src/java/org/apache/fop/pdf/PDFStructElem.java
@@ -32,7 +32,8 @@ import org.apache.fop.util.LanguageTags;
/**
* Class representing a PDF Structure Element.
*/
-public class PDFStructElem extends PDFDictionary implements StructureTreeElement, CompressedObject {
+public class PDFStructElem extends StructureHierarchyMember
+ implements StructureTreeElement, CompressedObject {
private StructureType structureType;
@@ -51,7 +52,7 @@ public class PDFStructElem extends PDFDictionary implements StructureTreeElement
* @param parent parent of this element
* @param structureType the structure type of this element
*/
- PDFStructElem(PDFObject parent, StructureType structureType) {
+ public PDFStructElem(PDFObject parent, StructureType structureType) {
this(parent);
this.structureType = structureType;
put("S", structureType.getName());
@@ -86,6 +87,7 @@ public class PDFStructElem extends PDFDictionary implements StructureTreeElement
*
* @param kid element to be added
*/
+ @Override
public void addKid(PDFObject kid) {
if (kids == null) {
kids = new ArrayList<PDFObject>();
diff --git a/src/java/org/apache/fop/pdf/PDFStructTreeRoot.java b/src/java/org/apache/fop/pdf/PDFStructTreeRoot.java
index 5f19bb2e2..ca6d82d22 100644
--- a/src/java/org/apache/fop/pdf/PDFStructTreeRoot.java
+++ b/src/java/org/apache/fop/pdf/PDFStructTreeRoot.java
@@ -22,7 +22,7 @@ package org.apache.fop.pdf;
/**
* Class representing a PDF /StructTreeRoot dictionary.
*/
-public class PDFStructTreeRoot extends PDFDictionary {
+public class PDFStructTreeRoot extends StructureHierarchyMember {
/**
* Creates a new /StructTreeRoot dictionary.
@@ -49,6 +49,7 @@ public class PDFStructTreeRoot extends PDFDictionary {
*
* @param kid an object to be added to the K entry
*/
+ @Override
public void addKid(PDFObject kid) {
getKids().add(kid);
}
diff --git a/src/java/org/apache/fop/pdf/StandardStructureTypes.java b/src/java/org/apache/fop/pdf/StandardStructureTypes.java
index dc045e180..69550119a 100644
--- a/src/java/org/apache/fop/pdf/StandardStructureTypes.java
+++ b/src/java/org/apache/fop/pdf/StandardStructureTypes.java
@@ -111,6 +111,11 @@ public final class StandardStructureTypes {
return name;
}
+ @Override
+ public String toString() {
+ return name.toString().substring(1);
+ }
+
}
private static final Map<String, StructureType> STRUCTURE_TYPES = new HashMap<String, StructureType>();
diff --git a/src/java/org/apache/fop/apps/io/Resource.java b/src/java/org/apache/fop/pdf/StructureHierarchyMember.java
index 0a8b8c22a..e3be92102 100644
--- a/src/java/org/apache/fop/apps/io/Resource.java
+++ b/src/java/org/apache/fop/pdf/StructureHierarchyMember.java
@@ -17,43 +17,21 @@
/* $Id$ */
-package org.apache.fop.apps.io;
-
-import java.io.FilterInputStream;
-import java.io.InputStream;
+package org.apache.fop.pdf;
/**
- * This class represents a resolved resource. The type property is used by FOP to identify the resource
- * content.
+ * An element in the document's structure tree. This can be either the structure tree root
+ * or a structure element.
*
+ * @see "Section 10.6, <q>Logical Structure</q> of the PDF Reference, 4th edition (PDF 1.5)"
*/
-public class Resource extends FilterInputStream {
-
- private final String type;
-
- /**
- * @param type resource type
- * @param inputStream input stream of the resource
- */
- public Resource(String type, InputStream inputStream) {
- super(inputStream);
- this.type = type;
- }
+public abstract class StructureHierarchyMember extends PDFDictionary {
/**
- * Constructs a resource of 'unknown' type.
+ * Adds the given object to the array of kids.
*
- * @param inputStream input stream of the resource
- */
- public Resource(InputStream inputStream) {
- this("unknown", inputStream);
- }
-
- /**
- * @return the resource type
+ * @param kid an object to be added to the K entry
*/
- public String getType() {
- return this.type;
- }
+ public abstract void addKid(PDFObject kid);
}
diff --git a/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java b/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java
index a82c27bac..5a0732c84 100644
--- a/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java
+++ b/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java
@@ -328,7 +328,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.
*/
@@ -48,6 +50,27 @@ public class AFPPageSetup extends AFPExtensionAttachment {
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.
*
* @param elementName the name of the setup code object, may be null
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/src/java/org/apache/fop/render/bitmap/AbstractBitmapDocumentHandler.java b/src/java/org/apache/fop/render/bitmap/AbstractBitmapDocumentHandler.java
index 262caa53b..8d0ce14ac 100644
--- a/src/java/org/apache/fop/render/bitmap/AbstractBitmapDocumentHandler.java
+++ b/src/java/org/apache/fop/render/bitmap/AbstractBitmapDocumentHandler.java
@@ -84,7 +84,7 @@ public abstract class AbstractBitmapDocumentHandler extends AbstractBinaryWritin
super(context);
//Set target resolution
int dpi = Math.round(context.getUserAgent().getTargetResolution());
- getSettings().getWriterParams().setResolution(dpi);
+ getSettings().setResolution(dpi);
Map renderingOptions = getUserAgent().getRendererOptions();
setTargetBitmapSize((Dimension)renderingOptions.get(TARGET_BITMAP_SIZE));
diff --git a/src/java/org/apache/fop/render/bitmap/BitmapRenderingSettings.java b/src/java/org/apache/fop/render/bitmap/BitmapRenderingSettings.java
index d239fe0fd..4363f1d5e 100644
--- a/src/java/org/apache/fop/render/bitmap/BitmapRenderingSettings.java
+++ b/src/java/org/apache/fop/render/bitmap/BitmapRenderingSettings.java
@@ -107,4 +107,27 @@ public class BitmapRenderingSettings extends Java2DRenderingSettings {
return this.qualityRendering;
}
+ /**
+ * Sets the compression method for the image writer.
+ * @param compressionMethod the compression method name
+ */
+ public void setCompressionMethod(String compressionMethod) {
+ writerParams.setCompressionMethod(compressionMethod);
+ }
+
+ /**
+ * Returns the compression method being used by the image writer.
+ * @return the compression method in use
+ */
+ public String getCompressionMethod() {
+ return writerParams.getCompressionMethod();
+ }
+
+ /**
+ * Sets the resolution of the output image.
+ * @param dpi the dots-per-inch of the image
+ */
+ public void setResolution(int dpi) {
+ writerParams.setResolution(dpi);
+ }
}
diff --git a/src/java/org/apache/fop/render/bitmap/TIFFCompressionValue.java b/src/java/org/apache/fop/render/bitmap/TIFFCompressionValue.java
new file mode 100644
index 000000000..4e9c3bd26
--- /dev/null
+++ b/src/java/org/apache/fop/render/bitmap/TIFFCompressionValue.java
@@ -0,0 +1,98 @@
+/*
+ * 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.render.bitmap;
+
+import java.awt.image.BufferedImage;
+
+/**
+ * Compression constants for TIFF image output.
+ */
+public enum TIFFCompressionValue {
+ /** No compression */
+ NONE("NONE"),
+ /** JPEG compression */
+ JPEG("JPEG"),
+ /** Packbits (RLE) compression */
+ PACKBITS("PackBits"),
+ /** Deflate compression */
+ DEFLATE("Deflate"),
+ /** LZW compression */
+ LZW("LZW"),
+ /** ZLib compression */
+ ZLIB("ZLib"),
+ /** CCITT Group 3 (T.4) compression */
+ CCITT_T4("CCITT T.4", BufferedImage.TYPE_BYTE_BINARY, true),
+ /** CCITT Group 4 (T.6) compression */
+ CCITT_T6("CCITT T.6", BufferedImage.TYPE_BYTE_BINARY, true);
+
+ private final String name;
+ private final int imageType;
+ private boolean isCcitt;
+
+ private TIFFCompressionValue(String name, int imageType, boolean isCcitt) {
+ this.name = name;
+ this.imageType = imageType;
+ this.isCcitt = isCcitt;
+ }
+
+ private TIFFCompressionValue(String name) {
+ this(name, BufferedImage.TYPE_INT_ARGB, false);
+ }
+
+ /**
+ * Returns the name of this compression type.
+ * @return the compression name
+ */
+ String getName() {
+ return name;
+ }
+
+ /**
+ * Returns an image type for this compression type, a constant from {@link BufferedImage} e.g.
+ * {@link BufferedImage#TYPE_INT_ARGB} for {@link #ZLIB}
+ * @return the image type
+ */
+ int getImageType() {
+ return imageType;
+ }
+
+ /**
+ * Returns whether or not this compression type is a CCITT type.
+ * @return true if the compression type is CCITT
+ */
+ boolean hasCCITTCompression() {
+ return isCcitt;
+ }
+
+ /**
+ * Return the TIFF compression constant given the string representing the type. In the case that
+ * the name doesn't match any of the compression values, <code>null</code> is returned.
+ * @param name the compression type name
+ * @return the compression constant
+ */
+ static TIFFCompressionValue getType(String name) {
+ for (TIFFCompressionValue tiffConst : TIFFCompressionValue.values()) {
+ if (tiffConst.name.equalsIgnoreCase(name)) {
+ return tiffConst;
+ }
+ }
+ return null;
+ }
+}
diff --git a/src/java/org/apache/fop/render/bitmap/TIFFCompressionValues.java b/src/java/org/apache/fop/render/bitmap/TIFFCompressionValues.java
deleted file mode 100644
index 71649022e..000000000
--- a/src/java/org/apache/fop/render/bitmap/TIFFCompressionValues.java
+++ /dev/null
@@ -1,61 +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.render.bitmap;
-
-/**
- * Constants for TIFF output.
- */
-public enum TIFFCompressionValues {
- /** No compression */
- NONE("NONE"),
- /** JPEG compression */
- JPEG("JPEG"),
- /** Packbits (RLE) compression */
- PACKBITS("PackBits"),
- /** Deflate compression */
- DEFLATE("Deflate"),
- /** LZW compression */
- LZW("LZW"),
- /** ZLib compression */
- ZLIB("ZLib"),
- /** CCITT Group 4 (T.6) compression */
- CCITT_T6("CCITT T.6"), //CCITT Group 4
- /** CCITT Group 3 (T.4) compression */
- CCITT_T4("CCITT T.4"); //CCITT Group 3
-
- private final String name;
-
- private TIFFCompressionValues(String name) {
- this.name = name;
- }
-
- public String getName() {
- return name;
- }
-
- public static TIFFCompressionValues getValue(String name) {
- for (TIFFCompressionValues tiffConst : TIFFCompressionValues.values()) {
- if (tiffConst.name.equalsIgnoreCase(name)) {
- return tiffConst;
- }
- }
- return null;
- }
-}
diff --git a/src/java/org/apache/fop/render/bitmap/TIFFDocumentHandler.java b/src/java/org/apache/fop/render/bitmap/TIFFDocumentHandler.java
index 48e79520f..0de02c766 100644
--- a/src/java/org/apache/fop/render/bitmap/TIFFDocumentHandler.java
+++ b/src/java/org/apache/fop/render/bitmap/TIFFDocumentHandler.java
@@ -19,6 +19,8 @@
package org.apache.fop.render.bitmap;
+import org.apache.xmlgraphics.image.writer.ResolutionUnit;
+
import org.apache.fop.apps.MimeConstants;
import org.apache.fop.render.bitmap.TIFFRendererConfig.TIFFRendererConfigParser;
import org.apache.fop.render.intermediate.IFContext;
@@ -32,6 +34,7 @@ public class TIFFDocumentHandler extends AbstractBitmapDocumentHandler {
TIFFDocumentHandler(IFContext context) {
super(context);
+ getSettings().getWriterParams().setResolutionUnit(ResolutionUnit.CENTIMETER);
}
/** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/render/bitmap/TIFFRenderer.java b/src/java/org/apache/fop/render/bitmap/TIFFRenderer.java
index 5b75a372c..48da62ef7 100644
--- a/src/java/org/apache/fop/render/bitmap/TIFFRenderer.java
+++ b/src/java/org/apache/fop/render/bitmap/TIFFRenderer.java
@@ -38,7 +38,6 @@ import org.apache.commons.logging.Log;
import org.apache.xmlgraphics.image.GraphicsUtil;
import org.apache.xmlgraphics.image.rendered.FormatRed;
import org.apache.xmlgraphics.image.writer.ImageWriter;
-import org.apache.xmlgraphics.image.writer.ImageWriterParams;
import org.apache.xmlgraphics.image.writer.ImageWriterRegistry;
import org.apache.xmlgraphics.image.writer.MultiImageWriter;
@@ -47,9 +46,9 @@ import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.MimeConstants;
import org.apache.fop.render.java2d.Java2DRenderer;
-import static org.apache.fop.render.bitmap.TIFFCompressionValues.CCITT_T4;
-import static org.apache.fop.render.bitmap.TIFFCompressionValues.CCITT_T6;
-import static org.apache.fop.render.bitmap.TIFFCompressionValues.PACKBITS;
+import static org.apache.fop.render.bitmap.TIFFCompressionValue.CCITT_T4;
+import static org.apache.fop.render.bitmap.TIFFCompressionValue.CCITT_T6;
+import static org.apache.fop.render.bitmap.TIFFCompressionValue.PACKBITS;
/**
* <p>
@@ -74,11 +73,7 @@ import static org.apache.fop.render.bitmap.TIFFCompressionValues.PACKBITS;
*/
public class TIFFRenderer extends Java2DRenderer {
- /** ImageWriter parameters */
- private ImageWriterParams writerParams;
-
- /** Image Type as parameter for the BufferedImage constructor (see BufferedImage.TYPE_*) */
- private int bufferedImageType = BufferedImage.TYPE_INT_ARGB;
+ private BitmapRenderingSettings imageSettings;
private OutputStream outputStream;
@@ -94,11 +89,11 @@ public class TIFFRenderer extends Java2DRenderer {
*/
public TIFFRenderer(FOUserAgent userAgent) {
super(userAgent);
- writerParams = new ImageWriterParams();
- writerParams.setCompressionMethod(PACKBITS.getName());
-
+ imageSettings = new BitmapRenderingSettings();
+ imageSettings.setCompressionMethod(PACKBITS.getName());
+ imageSettings.setBufferedImageType(BufferedImage.TYPE_INT_ARGB);
int dpi = Math.round(userAgent.getTargetResolution());
- writerParams.setResolution(dpi);
+ imageSettings.setResolution(dpi);
}
/** {@inheritDoc} */
@@ -129,7 +124,7 @@ public class TIFFRenderer extends Java2DRenderer {
// Write all pages/images
while (pageImagesItr.hasNext()) {
RenderedImage img = (RenderedImage) pageImagesItr.next();
- multiWriter.writeImage(img, writerParams);
+ multiWriter.writeImage(img, imageSettings.getWriterParams());
}
} finally {
multiWriter.close();
@@ -139,7 +134,7 @@ public class TIFFRenderer extends Java2DRenderer {
if (pageImagesItr.hasNext()) {
renderedImage = (RenderedImage) pageImagesItr.next();
}
- writer.writeImage(renderedImage, outputStream, writerParams);
+ writer.writeImage(renderedImage, outputStream, imageSettings.getWriterParams());
if (pageImagesItr.hasNext()) {
BitmapRendererEventProducer eventProducer
= BitmapRendererEventProducer.Provider.get(
@@ -156,7 +151,7 @@ public class TIFFRenderer extends Java2DRenderer {
/** {@inheritDoc} */
protected BufferedImage getBufferedImage(int bitmapWidth, int bitmapHeight) {
- return new BufferedImage(bitmapWidth, bitmapHeight, bufferedImageType);
+ return new BufferedImage(bitmapWidth, bitmapHeight, imageSettings.getBufferedImageType());
}
/** Private inner class to lazy page rendering. */
@@ -195,7 +190,7 @@ public class TIFFRenderer extends Java2DRenderer {
throw new NoSuchElementException(e.getMessage());
}
- TIFFCompressionValues compression = TIFFCompressionValues.getValue(writerParams.getCompressionMethod());
+ TIFFCompressionValue compression = TIFFCompressionValue.getType(imageSettings.getCompressionMethod());
if (compression == CCITT_T4 || compression == CCITT_T6) {
return pageImage;
} else {
@@ -226,11 +221,14 @@ public class TIFFRenderer extends Java2DRenderer {
/** @param bufferedImageType an image type */
public void setBufferedImageType(int bufferedImageType) {
- this.bufferedImageType = bufferedImageType;
+ imageSettings.setBufferedImageType(bufferedImageType);
}
- /** @return image writer parameters */
- public ImageWriterParams getWriterParams() {
- return writerParams;
+ /**
+ * Returns the settings for the image rendering.
+ * @return the image rendering settings
+ */
+ public BitmapRenderingSettings getRenderingSettings() {
+ return imageSettings;
}
}
diff --git a/src/java/org/apache/fop/render/bitmap/TIFFRendererConfig.java b/src/java/org/apache/fop/render/bitmap/TIFFRendererConfig.java
index 5417ecc1e..1e44397f6 100644
--- a/src/java/org/apache/fop/render/bitmap/TIFFRendererConfig.java
+++ b/src/java/org/apache/fop/render/bitmap/TIFFRendererConfig.java
@@ -23,21 +23,24 @@ import java.util.EnumMap;
import org.apache.avalon.framework.configuration.Configuration;
-import org.apache.xmlgraphics.util.MimeConstants;
-
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.apps.MimeConstants;
import org.apache.fop.fonts.DefaultFontConfig;
import org.apache.fop.fonts.DefaultFontConfig.DefaultFontConfigParser;
import org.apache.fop.render.RendererConfigOption;
+import static org.apache.fop.render.bitmap.TIFFCompressionValue.PACKBITS;
+
/**
* The renderer configuration object for the TIFF renderer.
*/
public final class TIFFRendererConfig extends BitmapRendererConfig {
public enum TIFFRendererOption implements RendererConfigOption {
- COMPRESSION("compression", TIFFCompressionValues.PACKBITS);
+ COMPRESSION("compression", PACKBITS),
+ /** option to encode one row per strip or a all rows in a single strip*/
+ SINGLE_STRIP("single-strip", Boolean.FALSE);
private final String name;
private final Object defaultValue;
@@ -63,8 +66,16 @@ public final class TIFFRendererConfig extends BitmapRendererConfig {
super(fontConfig);
}
- public TIFFCompressionValues getCompressionType() {
- return (TIFFCompressionValues) params.get(TIFFRendererOption.COMPRESSION);
+ public TIFFCompressionValue getCompressionType() {
+ return (TIFFCompressionValue) params.get(TIFFRendererOption.COMPRESSION);
+ }
+
+ /**
+ * @return True if all rows are contained in a single strip, False each strip contains one row or null
+ * if not set.
+ */
+ public Boolean isSingleStrip() {
+ return (Boolean) params.get(TIFFRendererOption.SINGLE_STRIP);
}
/**
@@ -92,9 +103,10 @@ public final class TIFFRendererConfig extends BitmapRendererConfig {
.parse(cfg, userAgent.validateStrictly()));
super.build(config, userAgent, cfg);
if (cfg != null) {
- setParam(TIFFRendererOption.COMPRESSION,
- TIFFCompressionValues.getValue(getValue(cfg,
- TIFFRendererOption.COMPRESSION)));
+ setParam(TIFFRendererOption.COMPRESSION,
+ TIFFCompressionValue.getType(getValue(cfg, TIFFRendererOption.COMPRESSION)));
+ setParam(TIFFRendererOption.SINGLE_STRIP, Boolean.valueOf(getValue(cfg,
+ TIFFRendererOption.SINGLE_STRIP)));
}
return config;
}
diff --git a/src/java/org/apache/fop/render/bitmap/TIFFRendererConfigurator.java b/src/java/org/apache/fop/render/bitmap/TIFFRendererConfigurator.java
index b10f2a381..19abb8131 100644
--- a/src/java/org/apache/fop/render/bitmap/TIFFRendererConfigurator.java
+++ b/src/java/org/apache/fop/render/bitmap/TIFFRendererConfigurator.java
@@ -19,13 +19,9 @@
package org.apache.fop.render.bitmap;
-import java.awt.image.BufferedImage;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.apache.xmlgraphics.image.writer.ImageWriterParams;
-
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.render.Renderer;
@@ -33,9 +29,7 @@ import org.apache.fop.render.RendererConfig.RendererConfigParser;
import org.apache.fop.render.bitmap.TIFFRendererConfig.TIFFRendererConfigParser;
import org.apache.fop.render.intermediate.IFDocumentHandler;
-import static org.apache.fop.render.bitmap.TIFFCompressionValues.CCITT_T4;
-import static org.apache.fop.render.bitmap.TIFFCompressionValues.CCITT_T6;
-import static org.apache.fop.render.bitmap.TIFFCompressionValues.NONE;
+import static org.apache.fop.render.bitmap.TIFFCompressionValue.NONE;
/**
* TIFF Renderer configurator
@@ -62,43 +56,40 @@ public class TIFFRendererConfigurator extends BitmapRendererConfigurator {
final TIFFRendererConfig config = (TIFFRendererConfig) getRendererConfig(renderer);
if (config != null) {
TIFFRenderer tiffRenderer = (TIFFRenderer) renderer;
- //set compression
- tiffRenderer.setBufferedImageType(getCompressionType(config, tiffRenderer.getWriterParams()));
+ setCompressionMethod(config.getCompressionType(), tiffRenderer.getRenderingSettings());
}
super.configure(renderer);
}
- private int getCompressionType(TIFFRendererConfig config, ImageWriterParams writerParms)
- throws FOPException {
- //Some compression formats need a special image format:
- TIFFCompressionValues compression = config.getCompressionType();
+ private void setCompressionMethod(TIFFCompressionValue compression,
+ BitmapRenderingSettings settings) throws FOPException {
if (compression != null) {
if (compression != NONE) {
- writerParms.setCompressionMethod(compression.getName());
+ settings.setCompressionMethod(compression.getName());
}
if (LOG.isInfoEnabled()) {
LOG.info("TIFF compression set to " + compression.getName());
}
+ if (compression.hasCCITTCompression()) {
+ settings.setBufferedImageType(compression.getImageType());
+ }
}
- return getBufferedImageTypeFor(compression);
}
- private int getBufferedImageTypeFor(TIFFCompressionValues compressionType) {
- if (compressionType == CCITT_T6 || compressionType == CCITT_T4) {
- return BufferedImage.TYPE_BYTE_BINARY;
- } else {
- return BufferedImage.TYPE_INT_ARGB;
- }
+ private boolean isSingleStrip(TIFFRendererConfig config) {
+ Boolean singleRowPerStrip = config.isSingleStrip();
+ return singleRowPerStrip == null ? false : singleRowPerStrip;
}
- /** {@inheritDoc} */
+ @Override
public void configure(IFDocumentHandler documentHandler) throws FOPException {
- final TIFFRendererConfig tiffConfig = (TIFFRendererConfig) getRendererConfig(documentHandler);
- if (tiffConfig != null) {
+ final TIFFRendererConfig config = (TIFFRendererConfig) getRendererConfig(documentHandler);
+ if (config != null) {
TIFFDocumentHandler tiffHandler = (TIFFDocumentHandler) documentHandler;
BitmapRenderingSettings settings = tiffHandler.getSettings();
configure(documentHandler, settings, new TIFFRendererConfigParser());
- settings.setBufferedImageType(getCompressionType(tiffConfig, settings.getWriterParams()));
+ setCompressionMethod(config.getCompressionType(), settings);
+ settings.getWriterParams().setSingleStrip(isSingleStrip(config));
}
}
diff --git a/src/java/org/apache/fop/render/pdf/FOToPDFRoleMap.java b/src/java/org/apache/fop/render/pdf/FOToPDFRoleMap.java
deleted file mode 100644
index 68bfd8686..000000000
--- a/src/java/org/apache/fop/render/pdf/FOToPDFRoleMap.java
+++ /dev/null
@@ -1,162 +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.render.pdf;
-
-import java.util.Map;
-
-import org.apache.fop.events.EventBroadcaster;
-import org.apache.fop.pdf.PDFObject;
-import org.apache.fop.pdf.PDFStructElem;
-import org.apache.fop.pdf.StandardStructureTypes;
-import org.apache.fop.pdf.StructureType;
-
-/**
- * This class provides the standard mappings from Formatting Objects to PDF structure types.
- */
-final class FOToPDFRoleMap {
-
- private static final Map<String, Mapper> DEFAULT_MAPPINGS = new java.util.HashMap<String, Mapper>();
-
- static {
- // Create the standard mappings
- // Declarations and Pagination and Layout Formatting Objects
- addMapping("root", StandardStructureTypes.Grouping.DOCUMENT);
- addMapping("page-sequence", StandardStructureTypes.Grouping.PART);
- addMapping("flow", StandardStructureTypes.Grouping.SECT);
- addMapping("static-content", StandardStructureTypes.Grouping.SECT);
- // Block-level Formatting Objects
- addMapping("block", StandardStructureTypes.Paragraphlike.P);
- addMapping("block-container", StandardStructureTypes.Grouping.DIV);
- // Inline-level Formatting Objects
- addMapping("character", StandardStructureTypes.InlineLevelStructure.SPAN);
- addMapping("external-graphic", StandardStructureTypes.Illustration.FIGURE);
- addMapping("instream-foreign-object", StandardStructureTypes.Illustration.FIGURE);
- addMapping("inline", StandardStructureTypes.InlineLevelStructure.SPAN);
- addMapping("inline-container", StandardStructureTypes.Grouping.DIV);
- addMapping("page-number", StandardStructureTypes.InlineLevelStructure.QUOTE);
- addMapping("page-number-citation", StandardStructureTypes.InlineLevelStructure.QUOTE);
- addMapping("page-number-citation-last", StandardStructureTypes.InlineLevelStructure.QUOTE);
- // Formatting Objects for Tables
- addMapping("table-and-caption", StandardStructureTypes.Grouping.DIV);
- addMapping("table", StandardStructureTypes.Table.TABLE);
- addMapping("table-caption", StandardStructureTypes.Grouping.CAPTION);
- addMapping("table-header", StandardStructureTypes.Table.THEAD);
- addMapping("table-footer", StandardStructureTypes.Table.TFOOT);
- addMapping("table-body", StandardStructureTypes.Table.TBODY);
- addMapping("table-row", StandardStructureTypes.Table.TR);
- addMapping("table-cell", new TableCellMapper());
- // Formatting Objects for Lists
- addMapping("list-block", StandardStructureTypes.List.L);
- addMapping("list-item", StandardStructureTypes.List.LI);
- addMapping("list-item-body", StandardStructureTypes.List.LBODY);
- addMapping("list-item-label", StandardStructureTypes.List.LBL);
- // Dynamic Effects: Link and Multi Formatting Objects
- addMapping("basic-link", StandardStructureTypes.InlineLevelStructure.LINK);
- // Out-of-Line Formatting Objects
- addMapping("float", StandardStructureTypes.Grouping.DIV);
- addMapping("footnote", StandardStructureTypes.InlineLevelStructure.NOTE);
- addMapping("footnote-body", StandardStructureTypes.Grouping.SECT);
- addMapping("wrapper", StandardStructureTypes.InlineLevelStructure.SPAN);
- addMapping("marker", StandardStructureTypes.Grouping.PRIVATE);
- }
-
- private static void addMapping(String fo, StructureType structureType) {
- addMapping(fo, new SimpleMapper(structureType));
- }
-
- private static void addMapping(String fo, Mapper mapper) {
- DEFAULT_MAPPINGS.put(fo, mapper);
- }
-
-
- /**
- * Maps a Formatting Object to a PDFName representing the associated structure type.
- * @param fo the formatting object's local name
- * @param role the value of the formatting object's role property
- * @param parent the parent of the structure element to be mapped
- * @param eventBroadcaster the event broadcaster
- * @return the structure type or null if no match could be found
- */
- public static StructureType mapFormattingObject(String fo, String role,
- PDFObject parent, EventBroadcaster eventBroadcaster) {
- StructureType type = null;
- if (role == null) {
- type = getDefaultMappingFor(fo, parent);
- } else {
- type = StandardStructureTypes.get(role);
- if (type == null) {
- type = getDefaultMappingFor(fo, parent);
- PDFEventProducer.Provider.get(eventBroadcaster).nonStandardStructureType(fo,
- fo, role, type.toString().substring(1));
- }
- }
- assert type != null;
- return type;
- }
-
- /**
- * Maps a Formatting Object to a PDFName representing the associated structure type.
- * @param fo the formatting object's local name
- * @param parent the parent of the structure element to be mapped
- * @return the structure type or NonStruct if no match could be found
- */
- private static StructureType getDefaultMappingFor(String fo, PDFObject parent) {
- Mapper mapper = DEFAULT_MAPPINGS.get(fo);
- if (mapper != null) {
- return mapper.getStructureType(parent);
- } else {
- return StandardStructureTypes.Grouping.NON_STRUCT;
- }
- }
-
- private interface Mapper {
- StructureType getStructureType(PDFObject parent);
- }
-
- private static class SimpleMapper implements Mapper {
-
- private StructureType structureType;
-
- public SimpleMapper(StructureType structureType) {
- this.structureType = structureType;
- }
-
- public StructureType getStructureType(PDFObject parent) {
- return structureType;
- }
-
- }
-
- private static class TableCellMapper implements Mapper {
-
- public StructureType getStructureType(PDFObject parent) {
- PDFStructElem grandParent = ((PDFStructElem) parent).getParentStructElem();
- //TODO What to do with cells from table-footer? Currently they are mapped on TD.
- if (grandParent.getStructureType() == StandardStructureTypes.Table.THEAD) {
- return StandardStructureTypes.Table.TH;
- } else {
- return StandardStructureTypes.Table.TD;
- }
- }
-
- }
-
- private FOToPDFRoleMap() { }
-}
diff --git a/src/java/org/apache/fop/render/pdf/PDFEventProducer.java b/src/java/org/apache/fop/render/pdf/PDFEventProducer.java
index 40062f73f..4b8253867 100644
--- a/src/java/org/apache/fop/render/pdf/PDFEventProducer.java
+++ b/src/java/org/apache/fop/render/pdf/PDFEventProducer.java
@@ -59,12 +59,11 @@ public interface PDFEventProducer extends EventProducer {
* Custom structure type is not standard as per the PDF reference.
*
* @param source the event source
- * @param fo the local name of the formatting object having the custom type
* @param type custom structure type
* @param fallback default structure type used as a fallback
* @event.severity WARN
*/
- void nonStandardStructureType(Object source, String fo, String type, String fallback);
+ void nonStandardStructureType(Object source, String type, String fallback);
/**
* The encryption length must be a multiple of 8 between 40 and 128.
diff --git a/src/java/org/apache/fop/render/pdf/PDFStructureTreeBuilder.java b/src/java/org/apache/fop/render/pdf/PDFStructureTreeBuilder.java
index 1377bbfce..031224ffb 100644
--- a/src/java/org/apache/fop/render/pdf/PDFStructureTreeBuilder.java
+++ b/src/java/org/apache/fop/render/pdf/PDFStructureTreeBuilder.java
@@ -21,24 +21,266 @@ package org.apache.fop.render.pdf;
import java.util.LinkedList;
import java.util.Locale;
+import java.util.Map;
import org.xml.sax.Attributes;
+import org.xml.sax.helpers.AttributesImpl;
import org.apache.fop.accessibility.StructureTreeElement;
import org.apache.fop.accessibility.StructureTreeEventHandler;
import org.apache.fop.events.EventBroadcaster;
import org.apache.fop.fo.extensions.ExtensionElementMapping;
+import org.apache.fop.fo.extensions.InternalElementMapping;
+import org.apache.fop.fo.pagination.Flow;
import org.apache.fop.pdf.PDFFactory;
-import org.apache.fop.pdf.PDFObject;
import org.apache.fop.pdf.PDFParentTree;
import org.apache.fop.pdf.PDFStructElem;
import org.apache.fop.pdf.PDFStructTreeRoot;
import org.apache.fop.pdf.StandardStructureAttributes.Table.Scope;
+import org.apache.fop.pdf.StandardStructureTypes;
+import org.apache.fop.pdf.StandardStructureTypes.Grouping;
import org.apache.fop.pdf.StandardStructureTypes.Table;
+import org.apache.fop.pdf.StructureHierarchyMember;
import org.apache.fop.pdf.StructureType;
+import org.apache.fop.util.XMLUtil;
class PDFStructureTreeBuilder implements StructureTreeEventHandler {
+ private static final String ROLE = "role";
+
+ private static final Map<String, StructureElementBuilder> BUILDERS
+ = new java.util.HashMap<String, StructureElementBuilder>();
+
+ private static final StructureElementBuilder DEFAULT_BUILDER
+ = new DefaultStructureElementBuilder(Grouping.NON_STRUCT);
+
+ static {
+ // Declarations and Pagination and Layout Formatting Objects
+ StructureElementBuilder regionBuilder = new RegionBuilder();
+ addBuilder("root", StandardStructureTypes.Grouping.DOCUMENT);
+ addBuilder("page-sequence", new PageSequenceBuilder());
+ addBuilder("static-content", regionBuilder);
+ addBuilder("flow", regionBuilder);
+ // Block-level Formatting Objects
+ addBuilder("block", StandardStructureTypes.Paragraphlike.P);
+ addBuilder("block-container", StandardStructureTypes.Grouping.DIV);
+ // Inline-level Formatting Objects
+ addBuilder("character", StandardStructureTypes.InlineLevelStructure.SPAN);
+ addBuilder("external-graphic", new ImageBuilder());
+ addBuilder("instream-foreign-object", new ImageBuilder());
+ addBuilder("inline", StandardStructureTypes.InlineLevelStructure.SPAN);
+ addBuilder("inline-container", StandardStructureTypes.Grouping.DIV);
+ addBuilder("page-number", StandardStructureTypes.InlineLevelStructure.QUOTE);
+ addBuilder("page-number-citation", StandardStructureTypes.InlineLevelStructure.QUOTE);
+ addBuilder("page-number-citation-last", StandardStructureTypes.InlineLevelStructure.QUOTE);
+ // Formatting Objects for Tables
+ addBuilder("table-and-caption", StandardStructureTypes.Grouping.DIV);
+ addBuilder("table", new TableBuilder());
+ addBuilder("table-caption", StandardStructureTypes.Grouping.CAPTION);
+ addBuilder("table-header", StandardStructureTypes.Table.THEAD);
+ addBuilder("table-footer", new TableFooterBuilder());
+ addBuilder("table-body", StandardStructureTypes.Table.TBODY);
+ addBuilder("table-row", StandardStructureTypes.Table.TR);
+ addBuilder("table-cell", new TableCellBuilder());
+ // Formatting Objects for Lists
+ addBuilder("list-block", StandardStructureTypes.List.L);
+ addBuilder("list-item", StandardStructureTypes.List.LI);
+ addBuilder("list-item-body", StandardStructureTypes.List.LBODY);
+ addBuilder("list-item-label", StandardStructureTypes.List.LBL);
+ // Dynamic Effects: Link and Multi Formatting Objects
+ addBuilder("basic-link", StandardStructureTypes.InlineLevelStructure.LINK);
+ // Out-of-Line Formatting Objects
+ addBuilder("float", StandardStructureTypes.Grouping.DIV);
+ addBuilder("footnote", StandardStructureTypes.InlineLevelStructure.NOTE);
+ addBuilder("footnote-body", StandardStructureTypes.Grouping.SECT);
+ addBuilder("wrapper", StandardStructureTypes.InlineLevelStructure.SPAN);
+ addBuilder("marker", StandardStructureTypes.Grouping.PRIVATE);
+
+ addBuilder("#PCDATA", new PlaceholderBuilder());
+ }
+
+ private static void addBuilder(String fo, StructureType structureType) {
+ addBuilder(fo, new DefaultStructureElementBuilder(structureType));
+ }
+
+ private static void addBuilder(String fo, StructureElementBuilder mapper) {
+ BUILDERS.put(fo, mapper);
+ }
+
+ private interface StructureElementBuilder {
+
+ PDFStructElem build(StructureHierarchyMember parent, Attributes attributes, PDFFactory pdfFactory,
+ EventBroadcaster eventBroadcaster);
+
+ }
+
+ private static class DefaultStructureElementBuilder implements StructureElementBuilder {
+
+ private final StructureType defaultStructureType;
+
+ DefaultStructureElementBuilder(StructureType structureType) {
+ this.defaultStructureType = structureType;
+ }
+
+ public final PDFStructElem build(StructureHierarchyMember parent, Attributes attributes,
+ PDFFactory pdfFactory, EventBroadcaster eventBroadcaster) {
+ String role = attributes.getValue(ROLE);
+ StructureType structureType;
+ if (role == null) {
+ structureType = defaultStructureType;
+ } else {
+ structureType = StandardStructureTypes.get(role);
+ if (structureType == null) {
+ structureType = defaultStructureType;
+ PDFEventProducer.Provider.get(eventBroadcaster).nonStandardStructureType(role, role,
+ structureType.toString());
+ }
+ }
+ PDFStructElem structElem = createStructureElement(parent, structureType);
+ setAttributes(structElem, attributes);
+ addKidToParent(structElem, parent, attributes);
+ registerStructureElement(structElem, pdfFactory, attributes);
+ return structElem;
+ }
+
+ protected PDFStructElem createStructureElement(StructureHierarchyMember parent,
+ StructureType structureType) {
+ return new PDFStructElem(parent, structureType);
+ }
+
+ protected void setAttributes(PDFStructElem structElem, Attributes attributes) {
+ }
+
+ protected void addKidToParent(PDFStructElem kid, StructureHierarchyMember parent,
+ Attributes attributes) {
+ parent.addKid(kid);
+ }
+
+ protected void registerStructureElement(PDFStructElem structureElement, PDFFactory pdfFactory,
+ Attributes attributes) {
+ pdfFactory.getDocument().registerStructureElement(structureElement);
+ }
+
+ }
+
+ private static class PageSequenceBuilder extends DefaultStructureElementBuilder {
+
+ PageSequenceBuilder() {
+ super(StandardStructureTypes.Grouping.PART);
+ }
+
+ @Override
+ protected PDFStructElem createStructureElement(StructureHierarchyMember parent,
+ StructureType structureType) {
+ return new PageSequenceStructElem(parent, structureType);
+ }
+
+ }
+
+ private static class RegionBuilder extends DefaultStructureElementBuilder {
+
+ RegionBuilder() {
+ super(StandardStructureTypes.Grouping.SECT);
+ }
+
+ @Override
+ protected void addKidToParent(PDFStructElem kid, StructureHierarchyMember parent,
+ Attributes attributes) {
+ String flowName = attributes.getValue(Flow.FLOW_NAME);
+ ((PageSequenceStructElem) parent).addContent(flowName, kid);
+ }
+
+ }
+
+ private static class ImageBuilder extends DefaultStructureElementBuilder {
+
+ ImageBuilder() {
+ super(StandardStructureTypes.Illustration.FIGURE);
+ }
+
+ @Override
+ protected void setAttributes(PDFStructElem structElem, Attributes attributes) {
+ String altTextNode = attributes.getValue(ExtensionElementMapping.URI, "alt-text");
+ if (altTextNode == null) {
+ altTextNode = "No alternate text specified";
+ }
+ structElem.put("Alt", altTextNode);
+ }
+
+ }
+
+ private static class TableBuilder extends DefaultStructureElementBuilder {
+
+ TableBuilder() {
+ super(StandardStructureTypes.Table.TABLE);
+ }
+
+ @Override
+ protected PDFStructElem createStructureElement(StructureHierarchyMember parent,
+ StructureType structureType) {
+ return new TableStructElem(parent, structureType);
+ }
+ }
+
+ private static class TableFooterBuilder extends DefaultStructureElementBuilder {
+
+ public TableFooterBuilder() {
+ super(StandardStructureTypes.Table.TFOOT);
+ }
+
+ @Override
+ protected void addKidToParent(PDFStructElem kid, StructureHierarchyMember parent,
+ Attributes attributes) {
+ ((TableStructElem) parent).addTableFooter(kid);
+ }
+ }
+
+ private static class TableCellBuilder extends DefaultStructureElementBuilder {
+
+ TableCellBuilder() {
+ super(StandardStructureTypes.Table.TD);
+ }
+
+ @Override
+ protected void registerStructureElement(PDFStructElem structureElement, PDFFactory pdfFactory,
+ Attributes attributes) {
+ if (structureElement.getStructureType() == Table.TH) {
+ String scopeAttribute = attributes.getValue(InternalElementMapping.URI,
+ InternalElementMapping.SCOPE);
+ Scope scope = (scopeAttribute == null)
+ ? Scope.COLUMN
+ : Scope.valueOf(scopeAttribute.toUpperCase(Locale.ENGLISH));
+ pdfFactory.getDocument().registerStructureElement(structureElement, scope);
+ } else {
+ pdfFactory.getDocument().registerStructureElement(structureElement);
+ }
+ }
+
+ @Override
+ protected void setAttributes(PDFStructElem structElem, Attributes attributes) {
+ String columnSpan = attributes.getValue("number-columns-spanned");
+ if (columnSpan != null) {
+ structElem.setTableAttributeColSpan(Integer.parseInt(columnSpan));
+ }
+ String rowSpan = attributes.getValue("number-rows-spanned");
+ if (rowSpan != null) {
+ structElem.setTableAttributeRowSpan(Integer.parseInt(rowSpan));
+ }
+ }
+
+ }
+
+ private static class PlaceholderBuilder implements StructureElementBuilder {
+
+ public PDFStructElem build(StructureHierarchyMember parent, Attributes attributes,
+ PDFFactory pdfFactory, EventBroadcaster eventBroadcaster) {
+ PDFStructElem elem = new PDFStructElem.Placeholder(parent);
+ parent.addKid(elem);
+ return elem;
+ }
+
+ }
+
private PDFFactory pdfFactory;
private EventBroadcaster eventBroadcaster;
@@ -51,6 +293,10 @@ class PDFStructureTreeBuilder implements StructureTreeEventHandler {
this.pdfFactory = pdfFactory;
}
+ void setEventBroadcaster(EventBroadcaster eventBroadcaster) {
+ this.eventBroadcaster = eventBroadcaster;
+ }
+
void setLogicalStructureHandler(PDFLogicalStructureHandler logicalStructureHandler) {
createRootStructureElement(logicalStructureHandler);
}
@@ -59,93 +305,53 @@ class PDFStructureTreeBuilder implements StructureTreeEventHandler {
assert rootStructureElement == null;
PDFParentTree parentTree = logicalStructureHandler.getParentTree();
PDFStructTreeRoot structTreeRoot = pdfFactory.getDocument().makeStructTreeRoot(parentTree);
- rootStructureElement = createStructureElement("root", structTreeRoot, null);
- structTreeRoot.addKid(rootStructureElement);
+ rootStructureElement = createStructureElement("root", structTreeRoot,
+ new AttributesImpl(), pdfFactory, eventBroadcaster);
}
- void setEventBroadcaster(EventBroadcaster eventBroadcaster) {
- this.eventBroadcaster = eventBroadcaster;
- }
+ private static PDFStructElem createStructureElement(String name, StructureHierarchyMember parent,
+ Attributes attributes, PDFFactory pdfFactory, EventBroadcaster eventBroadcaster) {
+ StructureElementBuilder builder = BUILDERS.get(name);
+ if (builder == null) {
+ // TODO is a fallback really necessary?
+ builder = DEFAULT_BUILDER;
+ }
+ return builder.build(parent, attributes, pdfFactory, eventBroadcaster);
+ }
public void startPageSequence(Locale language, String role) {
ancestors = new LinkedList<PDFStructElem>();
- PDFStructElem structElem = createStructureElement("page-sequence", rootStructureElement, role);
+ AttributesImpl attributes = new AttributesImpl();
+ attributes.addAttribute("", ROLE, ROLE, XMLUtil.CDATA, role);
+ PDFStructElem structElem = createStructureElement("page-sequence",
+ rootStructureElement, attributes, pdfFactory, eventBroadcaster);
if (language != null) {
structElem.setLanguage(language);
}
- rootStructureElement.addKid(structElem);
ancestors.add(structElem);
}
- private PDFStructElem createStructureElement(String name, PDFObject parent, String role) {
- StructureType structureType = FOToPDFRoleMap.mapFormattingObject(name, role, parent,
- eventBroadcaster);
- if (structureType == Table.TH) {
- return pdfFactory.getDocument().makeStructureElement(structureType, parent, Scope.COLUMN);
- } else {
- return pdfFactory.getDocument().makeStructureElement(structureType, parent);
- }
- }
-
public void endPageSequence() {
}
public StructureTreeElement startNode(String name, Attributes attributes) {
PDFStructElem parent = ancestors.getFirst();
- String role = attributes.getValue("role");
- PDFStructElem structElem = createStructureElement(name, parent, role);
- setSpanAttributes(structElem, attributes);
- parent.addKid(structElem);
+ PDFStructElem structElem = createStructureElement(name, parent, attributes,
+ pdfFactory, eventBroadcaster);
ancestors.addFirst(structElem);
return structElem;
}
- private void setSpanAttributes(PDFStructElem structElem, Attributes attributes) {
- String columnSpan = attributes.getValue("number-columns-spanned");
- if (columnSpan != null) {
- structElem.setTableAttributeColSpan(Integer.parseInt(columnSpan));
- }
- String rowSpan = attributes.getValue("number-rows-spanned");
- if (rowSpan != null) {
- structElem.setTableAttributeRowSpan(Integer.parseInt(rowSpan));
- }
- }
-
public void endNode(String name) {
- removeFirstAncestor();
- }
-
- private void removeFirstAncestor() {
ancestors.removeFirst();
}
public StructureTreeElement startImageNode(String name, Attributes attributes) {
- PDFStructElem parent = ancestors.getFirst();
- String role = attributes.getValue("role");
- PDFStructElem structElem = createStructureElement(name, parent, role);
- parent.addKid(structElem);
- String altTextNode = attributes.getValue(ExtensionElementMapping.URI, "alt-text");
- if (altTextNode != null) {
- structElem.put("Alt", altTextNode);
- } else {
- structElem.put("Alt", "No alternate text specified");
- }
- ancestors.addFirst(structElem);
- return structElem;
+ return startNode(name, attributes);
}
public StructureTreeElement startReferencedNode(String name, Attributes attributes) {
- PDFStructElem parent = ancestors.getFirst();
- String role = attributes.getValue("role");
- PDFStructElem structElem;
- if ("#PCDATA".equals(name)) {
- structElem = new PDFStructElem.Placeholder(parent);
- } else {
- structElem = createStructureElement(name, parent, role);
- }
- parent.addKid(structElem);
- ancestors.addFirst(structElem);
- return structElem;
+ return startNode(name, attributes);
}
}
diff --git a/src/java/org/apache/fop/render/pdf/PageSequenceStructElem.java b/src/java/org/apache/fop/render/pdf/PageSequenceStructElem.java
new file mode 100644
index 000000000..09d5b81a2
--- /dev/null
+++ b/src/java/org/apache/fop/render/pdf/PageSequenceStructElem.java
@@ -0,0 +1,79 @@
+/*
+ * 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.render.pdf;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.fop.pdf.PDFArray;
+import org.apache.fop.pdf.PDFObject;
+import org.apache.fop.pdf.PDFStructElem;
+import org.apache.fop.pdf.StructureType;
+
+class PageSequenceStructElem extends PDFStructElem {
+
+ private List<PDFStructElem> regionBefores = new ArrayList<PDFStructElem>();
+
+ private List<PDFStructElem> regionAfters = new ArrayList<PDFStructElem>();
+
+ private List<PDFStructElem> regionStarts = new ArrayList<PDFStructElem>();
+
+ private List<PDFStructElem> regionEnds = new ArrayList<PDFStructElem>();
+
+ PageSequenceStructElem(PDFObject parent, StructureType structureType) {
+ super(parent, structureType);
+ }
+
+ void addContent(String flowName, PDFStructElem content) {
+ if (flowName.equals("xsl-region-before")) {
+ regionBefores.add(content);
+ } else if (flowName.equals("xsl-region-after")) {
+ regionAfters.add(content);
+ } else if (flowName.equals("xsl-region-start")) {
+ regionStarts.add(content);
+ } else if (flowName.equals("xsl-region-end")) {
+ regionEnds.add(content);
+ } else {
+ addKid(content);
+ }
+ }
+
+ @Override
+ protected boolean attachKids() {
+ assert !kids.isEmpty();
+ PDFArray k = new PDFArray();
+ addRegions(k, regionBefores);
+ addRegions(k, regionStarts);
+ addRegions(k, kids);
+ addRegions(k, regionEnds);
+ addRegions(k, regionAfters);
+ put("K", k);
+ return true;
+ }
+
+ private void addRegions(PDFArray k, List<? extends PDFObject> regions) {
+ if (!regions.isEmpty()) {
+ for (PDFObject kid : regions) {
+ k.add(kid);
+ }
+ }
+ }
+
+}
diff --git a/src/java/org/apache/fop/render/pdf/TableStructElem.java b/src/java/org/apache/fop/render/pdf/TableStructElem.java
new file mode 100644
index 000000000..c44acb25c
--- /dev/null
+++ b/src/java/org/apache/fop/render/pdf/TableStructElem.java
@@ -0,0 +1,48 @@
+/*
+ * 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.render.pdf;
+
+import org.apache.fop.pdf.PDFObject;
+import org.apache.fop.pdf.PDFStructElem;
+import org.apache.fop.pdf.StructureType;
+
+class TableStructElem extends PDFStructElem {
+
+ private PDFStructElem tableFooter;
+
+ public TableStructElem(PDFObject parent, StructureType structureType) {
+ super(parent, structureType);
+ }
+
+ void addTableFooter(PDFStructElem footer) {
+ assert tableFooter == null;
+ tableFooter = footer;
+ }
+
+ @Override
+ protected boolean attachKids() {
+ assert !kids.isEmpty();
+ if (tableFooter != null) {
+ kids.add(tableFooter);
+ }
+ return super.attachKids();
+ }
+
+}
diff --git a/src/java/org/apache/fop/render/ps/PSDocumentHandler.java b/src/java/org/apache/fop/render/ps/PSDocumentHandler.java
index 0ec5fdda6..897ed8fb8 100644
--- a/src/java/org/apache/fop/render/ps/PSDocumentHandler.java
+++ b/src/java/org/apache/fop/render/ps/PSDocumentHandler.java
@@ -39,6 +39,7 @@ import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.xmlgraphics.io.TempResourceURIGenerator;
import org.apache.xmlgraphics.java2d.Dimension2DDouble;
import org.apache.xmlgraphics.ps.DSCConstants;
import org.apache.xmlgraphics.ps.PSDictionary;
@@ -53,7 +54,6 @@ import org.apache.xmlgraphics.ps.dsc.events.DSCCommentBoundingBox;
import org.apache.xmlgraphics.ps.dsc.events.DSCCommentHiResBoundingBox;
import org.apache.fop.apps.MimeConstants;
-import org.apache.fop.apps.io.TempResourceURIGenerator;
import org.apache.fop.render.intermediate.AbstractBinaryWritingIFDocumentHandler;
import org.apache.fop.render.intermediate.IFContext;
import org.apache.fop.render.intermediate.IFDocumentHandlerConfigurator;
diff --git a/src/java/org/apache/fop/render/ps/PSFontUtils.java b/src/java/org/apache/fop/render/ps/PSFontUtils.java
index c99bb21e1..9e810c824 100644
--- a/src/java/org/apache/fop/render/ps/PSFontUtils.java
+++ b/src/java/org/apache/fop/render/ps/PSFontUtils.java
@@ -38,7 +38,7 @@ import org.apache.xmlgraphics.ps.dsc.ResourceTracker;
import org.apache.fop.fonts.Base14Font;
import org.apache.fop.fonts.CIDFontType;
-import org.apache.fop.fonts.CIDSubset;
+import org.apache.fop.fonts.CIDSet;
import org.apache.fop.fonts.CMapSegment;
import org.apache.fop.fonts.CustomFont;
import org.apache.fop.fonts.EmbeddingMode;
@@ -457,15 +457,17 @@ public class PSFontUtils extends org.apache.xmlgraphics.ps.PSFontUtils {
// TODO /FontInfo
gen.write("/CIDCount ");
- CIDSubset cidSubset = font.getCIDSubset();
- int subsetSize = cidSubset.getSubsetSize();
- gen.write(subsetSize);
+ CIDSet cidSet = font.getCIDSet();
+ int numberOfGlyphs = cidSet.getNumberOfGlyphs();
+ gen.write(numberOfGlyphs);
gen.writeln(" def");
gen.writeln("/GDBytes 2 def"); // TODO always 2?
gen.writeln("/CIDMap [<");
int colCount = 0;
int lineCount = 1;
- for (int cid = 0; cid < subsetSize; cid++) {
+ int nextBitSet = 0;
+ int previousBitSet = 0;
+ for (int cid = 0; cid < numberOfGlyphs; cid++) {
if (colCount++ == 20) {
gen.newLine();
colCount = 1;
@@ -478,7 +480,23 @@ public class PSFontUtils extends org.apache.xmlgraphics.ps.PSFontUtils {
if (font.getEmbeddingMode() != EmbeddingMode.FULL) {
gid = HexEncoder.encode(cid, 4);
} else {
- gid = HexEncoder.encode(cidSubset.getGlyphIndexForSubsetIndex(cid), 4);
+ previousBitSet = nextBitSet;
+ nextBitSet = cidSet.getGlyphIndices().nextSetBit(nextBitSet);
+ while (previousBitSet++ < nextBitSet) {
+ // if there are gaps in the indices we pad them with zeros
+ gen.write("0000");
+ cid++;
+ if (colCount++ == 20) {
+ gen.newLine();
+ colCount = 1;
+ if (lineCount++ == 800) {
+ gen.writeln("> <");
+ lineCount = 1;
+ }
+ }
+ }
+ gid = HexEncoder.encode(nextBitSet, 4);
+ nextBitSet++;
}
gen.write(gid);
}
diff --git a/src/java/org/apache/fop/servlet/FopServlet.java b/src/java/org/apache/fop/servlet/FopServlet.java
index 9dcf10a2b..c65b6af3b 100644
--- a/src/java/org/apache/fop/servlet/FopServlet.java
+++ b/src/java/org/apache/fop/servlet/FopServlet.java
@@ -41,14 +41,15 @@ import javax.xml.transform.stream.StreamSource;
import org.apache.commons.io.output.ByteArrayOutputStream;
+import org.apache.xmlgraphics.io.Resource;
+import org.apache.xmlgraphics.io.ResourceResolver;
+
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.Fop;
import org.apache.fop.apps.FopFactory;
import org.apache.fop.apps.FopFactoryBuilder;
import org.apache.fop.apps.MimeConstants;
-import org.apache.fop.apps.io.Resource;
-import org.apache.fop.apps.io.ResourceResolver;
/**
* Example servlet to generate a PDF from a servlet.