summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Steiner <ssteiner@apache.org>2020-01-29 11:28:26 +0000
committerSimon Steiner <ssteiner@apache.org>2020-01-29 11:28:26 +0000
commit895a332bd65c6c3d5410c95fff61b576cdabfd8b (patch)
tree5eb6e537f87362b930cde2705bf4665ad81e69fb
parented7ad907820b7221402d14bcea49646f6fa62384 (diff)
downloadxmlgraphics-fop-895a332bd65c6c3d5410c95fff61b576cdabfd8b.tar.gz
xmlgraphics-fop-895a332bd65c6c3d5410c95fff61b576cdabfd8b.zip
FOP-2909: Hide empty blocks from structure tree
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1873298 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--fop-core/src/main/java/org/apache/fop/accessibility/Accessibility.java3
-rw-r--r--fop-core/src/main/java/org/apache/fop/accessibility/fo/Event.java61
-rw-r--r--fop-core/src/main/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverter.java528
-rw-r--r--fop-core/src/main/java/org/apache/fop/apps/FOUserAgent.java14
-rw-r--r--fop-core/src/main/java/org/apache/fop/apps/FopConfParser.java3
-rw-r--r--fop-core/src/main/java/org/apache/fop/apps/FopFactory.java4
-rw-r--r--fop-core/src/main/java/org/apache/fop/apps/FopFactoryBuilder.java19
-rw-r--r--fop-core/src/main/java/org/apache/fop/apps/FopFactoryConfig.java1
-rw-r--r--fop-core/src/test/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverterTestCase.java52
-rw-r--r--fop-core/src/test/java/org/apache/fop/apps/FopConfBuilder.java9
-rw-r--r--fop-core/src/test/java/org/apache/fop/apps/FopConfParserTestCase.java8
-rw-r--r--fop-core/src/test/java/org/apache/fop/apps/MutableConfig.java5
12 files changed, 582 insertions, 125 deletions
diff --git a/fop-core/src/main/java/org/apache/fop/accessibility/Accessibility.java b/fop-core/src/main/java/org/apache/fop/accessibility/Accessibility.java
index 88ec6dbdd..8a28a94d6 100644
--- a/fop-core/src/main/java/org/apache/fop/accessibility/Accessibility.java
+++ b/fop-core/src/main/java/org/apache/fop/accessibility/Accessibility.java
@@ -28,6 +28,9 @@ public final class Accessibility {
/** Constant string for the rendering options key to enable accessibility features. */
public static final String ACCESSIBILITY = "accessibility";
+ /** Constant string for the rendering options key to suppress empty tags from structure tree. */
+ public static final String KEEP_EMPTY_TAGS = "keep-empty-tags";
+
/**
* The value to be set on the 'role' property for the element and its descendants to
* be considered as artifacts.
diff --git a/fop-core/src/main/java/org/apache/fop/accessibility/fo/Event.java b/fop-core/src/main/java/org/apache/fop/accessibility/fo/Event.java
new file mode 100644
index 000000000..d76345558
--- /dev/null
+++ b/fop-core/src/main/java/org/apache/fop/accessibility/fo/Event.java
@@ -0,0 +1,61 @@
+/*
+ * 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;
+
+class Event {
+ private List<Event> children = new ArrayList<Event>();
+ protected FOEventHandler eventHandler;
+ protected Event parent;
+ protected boolean hasContent;
+
+ public Event(FO2StructureTreeConverter structureTreeConverter) {
+ eventHandler = structureTreeConverter.converter;
+ }
+
+ public Event(Event parent) {
+ this.parent = parent;
+ }
+
+ public void run() {
+ if (hasContent()) {
+ for (Event e : children) {
+ e.run();
+ }
+ }
+ children.clear();
+ }
+
+ private boolean hasContent() {
+ for (Event e : children) {
+ if (e.hasContent()) {
+ return true;
+ }
+ }
+ return hasContent;
+ }
+
+ public void add(Event child) {
+ children.add(child);
+ }
+}
diff --git a/fop-core/src/main/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverter.java b/fop-core/src/main/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverter.java
index 4614a7005..2381f2f03 100644
--- a/fop-core/src/main/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverter.java
+++ b/fop-core/src/main/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverter.java
@@ -73,7 +73,7 @@ import org.apache.fop.fo.properties.CommonAccessibilityHolder;
public class FO2StructureTreeConverter extends DelegatingFOEventHandler {
/** The top of the {@link converters} stack. */
- private FOEventHandler converter;
+ protected FOEventHandler converter;
private Stack<FOEventHandler> converters = new Stack<FOEventHandler>();
@@ -99,6 +99,42 @@ public class FO2StructureTreeConverter extends DelegatingFOEventHandler {
}
+ private Event root = new Event((Event) null);
+ private Event currentNode = root;
+
+ private void startContent(Event event, boolean hasContent) {
+ if (getUserAgent().isKeepEmptyTags()) {
+ event.run();
+ } else {
+ Event node = new Event(currentNode);
+ event.hasContent = hasContent;
+ node.add(event);
+ currentNode.add(node);
+ currentNode = node;
+ }
+ }
+
+ private void content(Event event, boolean hasContent) {
+ if (getUserAgent().isKeepEmptyTags()) {
+ event.run();
+ } else {
+ currentNode.add(event);
+ event.hasContent = hasContent;
+ }
+ }
+
+ private void endContent(Event event) {
+ if (getUserAgent().isKeepEmptyTags()) {
+ event.run();
+ } else {
+ currentNode.add(event);
+ currentNode = currentNode.parent;
+ if (currentNode == root) {
+ root.run();
+ }
+ }
+ }
+
/**
* Creates a new instance.
*
@@ -149,51 +185,83 @@ public class FO2StructureTreeConverter extends DelegatingFOEventHandler {
}
@Override
- public void startPageNumber(PageNumber pagenum) {
- converter.startPageNumber(pagenum);
+ public void startPageNumber(final PageNumber pagenum) {
+ startContent(new Event(this) {
+ public void run() {
+ eventHandler.startPageNumber(pagenum);
+ }
+ }, true);
super.startPageNumber(pagenum);
}
@Override
- public void endPageNumber(PageNumber pagenum) {
- converter.endPageNumber(pagenum);
+ public void endPageNumber(final PageNumber pagenum) {
+ endContent(new Event(this) {
+ public void run() {
+ eventHandler.endPageNumber(pagenum);
+ }
+ });
super.endPageNumber(pagenum);
}
@Override
- public void startPageNumberCitation(PageNumberCitation pageCite) {
- converter.startPageNumberCitation(pageCite);
+ public void startPageNumberCitation(final PageNumberCitation pageCite) {
+ startContent(new Event(this) {
+ public void run() {
+ eventHandler.startPageNumberCitation(pageCite);
+ }
+ }, true);
super.startPageNumberCitation(pageCite);
}
@Override
- public void endPageNumberCitation(PageNumberCitation pageCite) {
- converter.endPageNumberCitation(pageCite);
+ public void endPageNumberCitation(final PageNumberCitation pageCite) {
+ endContent(new Event(this) {
+ public void run() {
+ eventHandler.endPageNumberCitation(pageCite);
+ }
+ });
super.endPageNumberCitation(pageCite);
}
@Override
- public void startPageNumberCitationLast(PageNumberCitationLast pageLast) {
- converter.startPageNumberCitationLast(pageLast);
+ public void startPageNumberCitationLast(final PageNumberCitationLast pageLast) {
+ startContent(new Event(this) {
+ public void run() {
+ eventHandler.startPageNumberCitationLast(pageLast);
+ }
+ }, true);
super.startPageNumberCitationLast(pageLast);
}
@Override
- public void endPageNumberCitationLast(PageNumberCitationLast pageLast) {
- converter.endPageNumberCitationLast(pageLast);
+ public void endPageNumberCitationLast(final PageNumberCitationLast pageLast) {
+ endContent(new Event(this) {
+ public void run() {
+ eventHandler.endPageNumberCitationLast(pageLast);
+ }
+ });
super.endPageNumberCitationLast(pageLast);
}
@Override
- public void startStatic(StaticContent staticContent) {
+ public void startStatic(final StaticContent staticContent) {
handleStartArtifact(staticContent);
- converter.startStatic(staticContent);
+ startContent(new Event(this) {
+ public void run() {
+ eventHandler.startStatic(staticContent);
+ }
+ }, true);
super.startStatic(staticContent);
}
@Override
- public void endStatic(StaticContent staticContent) {
- converter.endStatic(staticContent);
+ public void endStatic(final StaticContent staticContent) {
+ endContent(new Event(this) {
+ public void run() {
+ eventHandler.endStatic(staticContent);
+ }
+ });
handleEndArtifact(staticContent);
super.endStatic(staticContent);
}
@@ -211,277 +279,457 @@ public class FO2StructureTreeConverter extends DelegatingFOEventHandler {
}
@Override
- public void startBlock(Block bl) {
- converter.startBlock(bl);
+ public void startBlock(final Block bl) {
+ startContent(new Event(this) {
+ public void run() {
+ eventHandler.startBlock(bl);
+ }
+ }, false);
super.startBlock(bl);
}
@Override
- public void endBlock(Block bl) {
- converter.endBlock(bl);
+ public void endBlock(final Block bl) {
+ endContent(new Event(this) {
+ public void run() {
+ eventHandler.endBlock(bl);
+ }
+ });
super.endBlock(bl);
}
@Override
- public void startBlockContainer(BlockContainer blc) {
- converter.startBlockContainer(blc);
+ public void startBlockContainer(final BlockContainer blc) {
+ startContent(new Event(this) {
+ public void run() {
+ eventHandler.startBlockContainer(blc);
+ }
+ }, false);
super.startBlockContainer(blc);
}
@Override
- public void endBlockContainer(BlockContainer blc) {
- converter.endBlockContainer(blc);
+ public void endBlockContainer(final BlockContainer blc) {
+ endContent(new Event(this) {
+ public void run() {
+ eventHandler.endBlockContainer(blc);
+ }
+ });
super.endBlockContainer(blc);
}
@Override
- public void startInline(Inline inl) {
- converter.startInline(inl);
+ public void startInline(final Inline inl) {
+ startContent(new Event(this) {
+ public void run() {
+ eventHandler.startInline(inl);
+ }
+ }, true);
super.startInline(inl);
}
@Override
- public void endInline(Inline inl) {
- converter.endInline(inl);
+ public void endInline(final Inline inl) {
+ endContent(new Event(this) {
+ public void run() {
+ eventHandler.endInline(inl);
+ }
+ });
super.endInline(inl);
}
@Override
- public void startTable(Table tbl) {
- converter.startTable(tbl);
+ public void startTable(final Table tbl) {
+ startContent(new Event(this) {
+ public void run() {
+ eventHandler.startTable(tbl);
+ }
+ }, true);
super.startTable(tbl);
}
@Override
- public void endTable(Table tbl) {
- converter.endTable(tbl);
+ public void endTable(final Table tbl) {
+ endContent(new Event(this) {
+ public void run() {
+ eventHandler.endTable(tbl);
+ }
+ });
super.endTable(tbl);
}
@Override
- public void startColumn(TableColumn tc) {
- converter.startColumn(tc);
+ public void startColumn(final TableColumn tc) {
+ startContent(new Event(this) {
+ public void run() {
+ eventHandler.startColumn(tc);
+ }
+ }, true);
super.startColumn(tc);
}
@Override
- public void endColumn(TableColumn tc) {
- converter.endColumn(tc);
+ public void endColumn(final TableColumn tc) {
+ endContent(new Event(this) {
+ public void run() {
+ eventHandler.endColumn(tc);
+ }
+ });
super.endColumn(tc);
}
@Override
- public void startHeader(TableHeader header) {
- converter.startHeader(header);
+ public void startHeader(final TableHeader header) {
+ startContent(new Event(this) {
+ public void run() {
+ eventHandler.startHeader(header);
+ }
+ }, true);
super.startHeader(header);
}
@Override
- public void endHeader(TableHeader header) {
- converter.endHeader(header);
+ public void endHeader(final TableHeader header) {
+ endContent(new Event(this) {
+ public void run() {
+ eventHandler.endHeader(header);
+ }
+ });
super.endHeader(header);
}
@Override
- public void startFooter(TableFooter footer) {
- converter.startFooter(footer);
+ public void startFooter(final TableFooter footer) {
+ startContent(new Event(this) {
+ public void run() {
+ eventHandler.startFooter(footer);
+ }
+ }, true);
super.startFooter(footer);
}
@Override
- public void endFooter(TableFooter footer) {
- converter.endFooter(footer);
+ public void endFooter(final TableFooter footer) {
+ endContent(new Event(this) {
+ public void run() {
+ eventHandler.endFooter(footer);
+ }
+ });
super.endFooter(footer);
}
@Override
- public void startBody(TableBody body) {
- converter.startBody(body);
+ public void startBody(final TableBody body) {
+ startContent(new Event(this) {
+ public void run() {
+ eventHandler.startBody(body);
+ }
+ }, true);
super.startBody(body);
}
@Override
- public void endBody(TableBody body) {
- converter.endBody(body);
+ public void endBody(final TableBody body) {
+ endContent(new Event(this) {
+ public void run() {
+ eventHandler.endBody(body);
+ }
+ });
super.endBody(body);
}
@Override
- public void startRow(TableRow tr) {
- converter.startRow(tr);
+ public void startRow(final TableRow tr) {
+ startContent(new Event(this) {
+ public void run() {
+ eventHandler.startRow(tr);
+ }
+ }, true);
super.startRow(tr);
}
@Override
- public void endRow(TableRow tr) {
- converter.endRow(tr);
+ public void endRow(final TableRow tr) {
+ endContent(new Event(this) {
+ public void run() {
+ eventHandler.endRow(tr);
+ }
+ });
super.endRow(tr);
}
@Override
- public void startCell(TableCell tc) {
- converter.startCell(tc);
+ public void startCell(final TableCell tc) {
+ startContent(new Event(this) {
+ public void run() {
+ eventHandler.startCell(tc);
+ }
+ }, true);
super.startCell(tc);
}
@Override
- public void endCell(TableCell tc) {
- converter.endCell(tc);
+ public void endCell(final TableCell tc) {
+ endContent(new Event(this) {
+ public void run() {
+ eventHandler.endCell(tc);
+ }
+ });
super.endCell(tc);
}
@Override
- public void startList(ListBlock lb) {
- converter.startList(lb);
+ public void startList(final ListBlock lb) {
+ startContent(new Event(this) {
+ public void run() {
+ eventHandler.startList(lb);
+ }
+ }, true);
super.startList(lb);
}
@Override
- public void endList(ListBlock lb) {
- converter.endList(lb);
+ public void endList(final ListBlock lb) {
+ endContent(new Event(this) {
+ public void run() {
+ eventHandler.endList(lb);
+ }
+ });
super.endList(lb);
}
@Override
- public void startListItem(ListItem li) {
- converter.startListItem(li);
+ public void startListItem(final ListItem li) {
+ startContent(new Event(this) {
+ public void run() {
+ eventHandler.startListItem(li);
+ }
+ }, true);
super.startListItem(li);
}
@Override
- public void endListItem(ListItem li) {
- converter.endListItem(li);
+ public void endListItem(final ListItem li) {
+ endContent(new Event(this) {
+ public void run() {
+ eventHandler.endListItem(li);
+ }
+ });
super.endListItem(li);
}
@Override
- public void startListLabel(ListItemLabel listItemLabel) {
- converter.startListLabel(listItemLabel);
+ public void startListLabel(final ListItemLabel listItemLabel) {
+ startContent(new Event(this) {
+ public void run() {
+ eventHandler.startListLabel(listItemLabel);
+ }
+ }, true);
super.startListLabel(listItemLabel);
}
@Override
- public void endListLabel(ListItemLabel listItemLabel) {
- converter.endListLabel(listItemLabel);
+ public void endListLabel(final ListItemLabel listItemLabel) {
+ endContent(new Event(this) {
+ public void run() {
+ eventHandler.endListLabel(listItemLabel);
+ }
+ });
super.endListLabel(listItemLabel);
}
@Override
- public void startListBody(ListItemBody listItemBody) {
- converter.startListBody(listItemBody);
+ public void startListBody(final ListItemBody listItemBody) {
+ startContent(new Event(this) {
+ public void run() {
+ eventHandler.startListBody(listItemBody);
+ }
+ }, true);
super.startListBody(listItemBody);
}
@Override
- public void endListBody(ListItemBody listItemBody) {
- converter.endListBody(listItemBody);
+ public void endListBody(final ListItemBody listItemBody) {
+ endContent(new Event(this) {
+ public void run() {
+ eventHandler.endListBody(listItemBody);
+ }
+ });
super.endListBody(listItemBody);
}
@Override
public void startMarkup() {
- converter.startMarkup();
+ startContent(new Event(this) {
+ public void run() {
+ eventHandler.startMarkup();
+ }
+ }, true);
super.startMarkup();
}
@Override
public void endMarkup() {
- converter.endMarkup();
+ endContent(new Event(this) {
+ public void run() {
+ eventHandler.endMarkup();
+ }
+ });
super.endMarkup();
}
@Override
- public void startLink(BasicLink basicLink) {
- converter.startLink(basicLink);
+ public void startLink(final BasicLink basicLink) {
+ startContent(new Event(this) {
+ public void run() {
+ eventHandler.startLink(basicLink);
+ }
+ }, true);
super.startLink(basicLink);
}
@Override
- public void endLink(BasicLink basicLink) {
- converter.endLink(basicLink);
+ public void endLink(final BasicLink basicLink) {
+ endContent(new Event(this) {
+ public void run() {
+ eventHandler.endLink(basicLink);
+ }
+ });
super.endLink(basicLink);
}
@Override
- public void image(ExternalGraphic eg) {
- converter.image(eg);
+ public void image(final ExternalGraphic eg) {
+ content(new Event(this) {
+ public void run() {
+ eventHandler.image(eg);
+ }
+ }, true);
super.image(eg);
}
@Override
public void pageRef() {
- converter.pageRef();
+ content(new Event(this) {
+ public void run() {
+ eventHandler.pageRef();
+ }
+ }, true);
super.pageRef();
}
@Override
- public void startInstreamForeignObject(InstreamForeignObject ifo) {
- converter.startInstreamForeignObject(ifo);
+ public void startInstreamForeignObject(final InstreamForeignObject ifo) {
+ startContent(new Event(this) {
+ public void run() {
+ eventHandler.startInstreamForeignObject(ifo);
+ }
+ }, true);
super.startInstreamForeignObject(ifo);
}
@Override
- public void endInstreamForeignObject(InstreamForeignObject ifo) {
- converter.endInstreamForeignObject(ifo);
+ public void endInstreamForeignObject(final InstreamForeignObject ifo) {
+ endContent(new Event(this) {
+ public void run() {
+ eventHandler.endInstreamForeignObject(ifo);
+ }
+ });
super.endInstreamForeignObject(ifo);
}
@Override
- public void startFootnote(Footnote footnote) {
- converter.startFootnote(footnote);
+ public void startFootnote(final Footnote footnote) {
+ startContent(new Event(this) {
+ public void run() {
+ eventHandler.startFootnote(footnote);
+ }
+ }, true);
super.startFootnote(footnote);
}
@Override
- public void endFootnote(Footnote footnote) {
- converter.endFootnote(footnote);
+ public void endFootnote(final Footnote footnote) {
+ endContent(new Event(this) {
+ public void run() {
+ eventHandler.endFootnote(footnote);
+ }
+ });
super.endFootnote(footnote);
}
@Override
- public void startFootnoteBody(FootnoteBody body) {
- converter.startFootnoteBody(body);
+ public void startFootnoteBody(final FootnoteBody body) {
+ startContent(new Event(this) {
+ public void run() {
+ eventHandler.startFootnoteBody(body);
+ }
+ }, true);
super.startFootnoteBody(body);
}
@Override
- public void endFootnoteBody(FootnoteBody body) {
- converter.endFootnoteBody(body);
+ public void endFootnoteBody(final FootnoteBody body) {
+ endContent(new Event(this) {
+ public void run() {
+ eventHandler.endFootnoteBody(body);
+ }
+ });
super.endFootnoteBody(body);
}
@Override
- public void startLeader(Leader l) {
+ public void startLeader(final Leader l) {
converters.push(converter);
converter = eventSwallower;
- converter.startLeader(l);
+ startContent(new Event(this) {
+ public void run() {
+ eventHandler.startLeader(l);
+ }
+ }, true);
super.startLeader(l);
}
@Override
- public void endLeader(Leader l) {
- converter.endLeader(l);
+ public void endLeader(final Leader l) {
+ endContent(new Event(this) {
+ public void run() {
+ eventHandler.endLeader(l);
+ }
+ });
converter = converters.pop();
super.endLeader(l);
}
@Override
- public void startWrapper(Wrapper wrapper) {
+ public void startWrapper(final Wrapper wrapper) {
handleStartArtifact(wrapper);
- converter.startWrapper(wrapper);
+ startContent(new Event(this) {
+ public void run() {
+ eventHandler.startWrapper(wrapper);
+ }
+ }, true);
super.startWrapper(wrapper);
}
@Override
- public void endWrapper(Wrapper wrapper) {
- converter.endWrapper(wrapper);
+ public void endWrapper(final Wrapper wrapper) {
+ endContent(new Event(this) {
+ public void run() {
+ eventHandler.endWrapper(wrapper);
+ }
+ });
handleEndArtifact(wrapper);
super.endWrapper(wrapper);
}
@Override
- public void startRetrieveMarker(RetrieveMarker retrieveMarker) {
- converter.startRetrieveMarker(retrieveMarker);
+ public void startRetrieveMarker(final RetrieveMarker retrieveMarker) {
+ startContent(new Event(this) {
+ public void run() {
+ eventHandler.startRetrieveMarker(retrieveMarker);
+ }
+ }, true);
saveState(retrieveMarker);
super.startRetrieveMarker(retrieveMarker);
}
@@ -491,15 +739,23 @@ public class FO2StructureTreeConverter extends DelegatingFOEventHandler {
}
@Override
- public void endRetrieveMarker(RetrieveMarker retrieveMarker) {
- converter.endRetrieveMarker(retrieveMarker);
+ public void endRetrieveMarker(final RetrieveMarker retrieveMarker) {
+ endContent(new Event(this) {
+ public void run() {
+ eventHandler.endRetrieveMarker(retrieveMarker);
+ }
+ });
super.endRetrieveMarker(retrieveMarker);
}
@Override
- public void restoreState(RetrieveMarker retrieveMarker) {
+ public void restoreState(final RetrieveMarker retrieveMarker) {
restoreRetrieveMarkerState(retrieveMarker);
- converter.restoreState(retrieveMarker);
+ content(new Event(this) {
+ public void run() {
+ eventHandler.restoreState(retrieveMarker);
+ }
+ }, true);
super.restoreState(retrieveMarker);
}
@@ -511,46 +767,74 @@ public class FO2StructureTreeConverter extends DelegatingFOEventHandler {
}
@Override
- public void startRetrieveTableMarker(RetrieveTableMarker retrieveTableMarker) {
- converter.startRetrieveTableMarker(retrieveTableMarker);
+ public void startRetrieveTableMarker(final RetrieveTableMarker retrieveTableMarker) {
+ startContent(new Event(this) {
+ public void run() {
+ eventHandler.startRetrieveTableMarker(retrieveTableMarker);
+ }
+ }, true);
saveState(retrieveTableMarker);
super.startRetrieveTableMarker(retrieveTableMarker);
}
@Override
- public void endRetrieveTableMarker(RetrieveTableMarker retrieveTableMarker) {
- converter.endRetrieveTableMarker(retrieveTableMarker);
+ public void endRetrieveTableMarker(final RetrieveTableMarker retrieveTableMarker) {
+ endContent(new Event(this) {
+ public void run() {
+ eventHandler.endRetrieveTableMarker(retrieveTableMarker);
+ }
+ });
super.endRetrieveTableMarker(retrieveTableMarker);
}
@Override
- public void restoreState(RetrieveTableMarker retrieveTableMarker) {
+ public void restoreState(final RetrieveTableMarker retrieveTableMarker) {
restoreRetrieveMarkerState(retrieveTableMarker);
- converter.restoreState(retrieveTableMarker);
+ currentNode.add(new Event(this) {
+ public void run() {
+ eventHandler.restoreState(retrieveTableMarker);
+ }
+ });
super.restoreState(retrieveTableMarker);
}
@Override
- public void character(Character c) {
- converter.character(c);
+ public void character(final Character c) {
+ content(new Event(this) {
+ public void run() {
+ eventHandler.character(c);
+ }
+ }, true);
super.character(c);
}
@Override
- public void characters(FOText foText) {
- converter.characters(foText);
+ public void characters(final FOText foText) {
+ content(new Event(this) {
+ public void run() {
+ eventHandler.characters(foText);
+ }
+ }, foText.length() > 0);
super.characters(foText);
}
@Override
- public void startExternalDocument(ExternalDocument document) {
- converter.startExternalDocument(document);
+ public void startExternalDocument(final ExternalDocument document) {
+ startContent(new Event(this) {
+ public void run() {
+ eventHandler.startExternalDocument(document);
+ }
+ }, true);
super.startExternalDocument(document);
}
@Override
- public void endExternalDocument(ExternalDocument document) {
- converter.endExternalDocument(document);
+ public void endExternalDocument(final ExternalDocument document) {
+ endContent(new Event(this) {
+ public void run() {
+ eventHandler.endExternalDocument(document);
+ }
+ });
super.endExternalDocument(document);
}
diff --git a/fop-core/src/main/java/org/apache/fop/apps/FOUserAgent.java b/fop-core/src/main/java/org/apache/fop/apps/FOUserAgent.java
index 3fd2c9167..9b1566d2e 100644
--- a/fop-core/src/main/java/org/apache/fop/apps/FOUserAgent.java
+++ b/fop-core/src/main/java/org/apache/fop/apps/FOUserAgent.java
@@ -149,6 +149,7 @@ public class FOUserAgent {
this.resourceResolver = resourceResolver;
setTargetResolution(factory.getTargetResolution());
setAccessibility(factory.isAccessibilityEnabled());
+ setKeepEmptyTags(factory.isKeepEmptyTags());
imageSessionContext = new AbstractImageSessionContext(factory.getFallbackResolver()) {
public ImageContext getParentContext() {
@@ -817,4 +818,17 @@ public class FOUserAgent {
public HyphenationTreeCache getHyphenationTreeCache() {
return factory.getHyphenationTreeCache();
}
+
+ public void setKeepEmptyTags(boolean b) {
+ getRendererOptions().put(Accessibility.KEEP_EMPTY_TAGS, b);
+ }
+
+ public boolean isKeepEmptyTags() {
+ Boolean enabled = (Boolean)getRendererOptions().get(Accessibility.KEEP_EMPTY_TAGS);
+ if (enabled != null) {
+ return enabled;
+ } else {
+ return true;
+ }
+ }
}
diff --git a/fop-core/src/main/java/org/apache/fop/apps/FopConfParser.java b/fop-core/src/main/java/org/apache/fop/apps/FopConfParser.java
index 7dcbae34c..04b020277 100644
--- a/fop-core/src/main/java/org/apache/fop/apps/FopConfParser.java
+++ b/fop-core/src/main/java/org/apache/fop/apps/FopConfParser.java
@@ -38,6 +38,7 @@ 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.accessibility.Accessibility;
import org.apache.fop.apps.io.InternalResourceResolver;
import org.apache.fop.apps.io.ResourceResolverFactory;
import org.apache.fop.configuration.Configuration;
@@ -185,6 +186,8 @@ public class FopConfParser {
if (cfg.getChild("accessibility", false) != null) {
try {
fopFactoryBuilder.setAccessibility(cfg.getChild("accessibility").getValueAsBoolean());
+ fopFactoryBuilder.setKeepEmptyTags(
+ cfg.getChild("accessibility").getAttributeAsBoolean(Accessibility.KEEP_EMPTY_TAGS, true));
} catch (ConfigurationException e) {
LogUtil.handleException(log, e, false);
}
diff --git a/fop-core/src/main/java/org/apache/fop/apps/FopFactory.java b/fop-core/src/main/java/org/apache/fop/apps/FopFactory.java
index e2f81b140..35a0bc373 100644
--- a/fop-core/src/main/java/org/apache/fop/apps/FopFactory.java
+++ b/fop-core/src/main/java/org/apache/fop/apps/FopFactory.java
@@ -328,6 +328,10 @@ public final class FopFactory implements ImageContext {
return config.isAccessibilityEnabled();
}
+ boolean isKeepEmptyTags() {
+ return config.isKeepEmptyTags();
+ }
+
/** @see FopFactoryConfig#getImageManager() */
public ImageManager getImageManager() {
return config.getImageManager();
diff --git a/fop-core/src/main/java/org/apache/fop/apps/FopFactoryBuilder.java b/fop-core/src/main/java/org/apache/fop/apps/FopFactoryBuilder.java
index 84f85cdbd..3fd8414fb 100644
--- a/fop-core/src/main/java/org/apache/fop/apps/FopFactoryBuilder.java
+++ b/fop-core/src/main/java/org/apache/fop/apps/FopFactoryBuilder.java
@@ -160,6 +160,11 @@ public final class FopFactoryBuilder {
return this;
}
+ public FopFactoryBuilder setKeepEmptyTags(boolean b) {
+ fopFactoryConfigBuilder.setKeepEmptyTags(b);
+ return this;
+ }
+
/**
* Sets the {@link LayoutManagerMaker} so that users can configure how FOP creates
* {@link org.apache.fop.layoutmgr.LayoutManager}s.
@@ -330,6 +335,8 @@ public final class FopFactoryBuilder {
private boolean accessibility;
+ private boolean keepEmptyTags = true;
+
private LayoutManagerMaker layoutManagerMaker;
private URI baseURI;
@@ -385,6 +392,10 @@ public final class FopFactoryBuilder {
return accessibility;
}
+ public boolean isKeepEmptyTags() {
+ return keepEmptyTags;
+ }
+
/** {@inheritDoc} */
public LayoutManagerMaker getLayoutManagerMakerOverride() {
return layoutManagerMaker;
@@ -485,6 +496,7 @@ public final class FopFactoryBuilder {
private interface FopFactoryConfigBuilder {
void setAccessibility(boolean enableAccessibility);
+ void setKeepEmptyTags(boolean b);
void setLayoutManagerMakerOverride(LayoutManagerMaker lmMaker);
@@ -531,6 +543,9 @@ public final class FopFactoryBuilder {
public void setAccessibility(boolean enableAccessibility) {
throwIllegalStateException();
}
+ public void setKeepEmptyTags(boolean b) {
+ throwIllegalStateException();
+ }
public void setLayoutManagerMakerOverride(LayoutManagerMaker lmMaker) {
throwIllegalStateException();
@@ -612,6 +627,10 @@ public final class FopFactoryBuilder {
config.accessibility = enableAccessibility;
}
+ public void setKeepEmptyTags(boolean b) {
+ config.keepEmptyTags = b;
+ }
+
public void setLayoutManagerMakerOverride(LayoutManagerMaker lmMaker) {
config.layoutManagerMaker = lmMaker;
}
diff --git a/fop-core/src/main/java/org/apache/fop/apps/FopFactoryConfig.java b/fop-core/src/main/java/org/apache/fop/apps/FopFactoryConfig.java
index 37482244b..69b7b25e9 100644
--- a/fop-core/src/main/java/org/apache/fop/apps/FopFactoryConfig.java
+++ b/fop-core/src/main/java/org/apache/fop/apps/FopFactoryConfig.java
@@ -67,6 +67,7 @@ public interface FopFactoryConfig {
* @return true if accessibility features have been requested
*/
boolean isAccessibilityEnabled();
+ boolean isKeepEmptyTags();
/**
* Returns the overriding LayoutManagerMaker instance, if any.
diff --git a/fop-core/src/test/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverterTestCase.java b/fop-core/src/test/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverterTestCase.java
index eddd90ec4..ef7b57f47 100644
--- a/fop-core/src/test/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverterTestCase.java
+++ b/fop-core/src/test/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverterTestCase.java
@@ -19,12 +19,15 @@
package org.apache.fop.accessibility.fo;
+import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.io.StringWriter;
+import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
@@ -33,6 +36,7 @@ import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;
@@ -44,6 +48,7 @@ import org.w3c.dom.Document;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -132,6 +137,52 @@ public class FO2StructureTreeConverterTestCase {
assertNull(d.getStructureTreeEventHandler().startNode("table-body", null, null));
}
+ @Test
+ public void testRemoveBlocks() throws Exception {
+ compare("<fo:root xmlns:fo=\"http://www.w3.org/1999/XSL/Format\">\n"
+ + " <fo:layout-master-set>\n"
+ + " <fo:simple-page-master master-name=\"simple\">\n"
+ + " <fo:region-body />\n"
+ + " </fo:simple-page-master>\n"
+ + " </fo:layout-master-set>\n"
+ + " <fo:page-sequence master-reference=\"simple\">\n"
+ + " <fo:flow flow-name=\"xsl-region-body\">\n"
+ + " <fo:block/>"
+ + " <fo:block><fo:block/></fo:block>\n"
+ + " <fo:block>a</fo:block>\n"
+ + " </fo:flow>\n"
+ + " </fo:page-sequence>\n"
+ + "</fo:root>\n",
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ + "<structure-tree-sequence>\n"
+ + "<structure-tree xmlns=\"http://xmlgraphics.apache.org/fop/intermediate\" "
+ + "xmlns:foi=\"http://xmlgraphics.apache.org/fop/internal\" "
+ + "xmlns:fox=\"http://xmlgraphics.apache.org/fop/extensions\">\n"
+ + "<fo:flow xmlns:fo=\"http://www.w3.org/1999/XSL/Format\" flow-name=\"xsl-region-body\">\n"
+ + "<fo:block>\n"
+ + "<marked-content/>\n"
+ + "</fo:block>\n"
+ + "</fo:flow>\n"
+ + "</structure-tree>\n"
+ + "</structure-tree-sequence>\n");
+ }
+
+ private void compare(final String fo, String tree) throws Exception {
+ foLoader = new FOLoader("") {
+ public InputStream getFoInputStream() {
+ return new ByteArrayInputStream(fo.getBytes());
+ }
+ };
+ DOMResult actualStructureTree = buildActualStructureTree();
+ Document doc = (Document) actualStructureTree.getNode();
+ StringWriter sw = new StringWriter();
+ TransformerFactory tf = TransformerFactory.newInstance();
+ Transformer transformer = tf.newTransformer();
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+ transformer.transform(new DOMSource(doc), new StreamResult(sw));
+ assertEquals(tree, sw.toString());
+ }
+
private void testConverter(String foResourceName) throws Exception {
foLoader = new FOLoader(foResourceName);
DOMResult expectedStructureTree = loadExpectedStructureTree();
@@ -216,6 +267,7 @@ public class FO2StructureTreeConverterTestCase {
private static FOUserAgent createFOUserAgent(FODocumentParser documentParser) {
FOUserAgent userAgent = documentParser.createFOUserAgent();
userAgent.setAccessibility(true);
+ userAgent.setKeepEmptyTags(false);
return userAgent;
}
diff --git a/fop-core/src/test/java/org/apache/fop/apps/FopConfBuilder.java b/fop-core/src/test/java/org/apache/fop/apps/FopConfBuilder.java
index 8ad0192d6..f8a3d2822 100644
--- a/fop-core/src/test/java/org/apache/fop/apps/FopConfBuilder.java
+++ b/fop-core/src/test/java/org/apache/fop/apps/FopConfBuilder.java
@@ -43,6 +43,7 @@ import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
+import org.apache.fop.accessibility.Accessibility;
import org.apache.fop.render.RendererConfigOption;
/**
@@ -137,8 +138,12 @@ public class FopConfBuilder implements FontConfigurator<FopConfBuilder> {
* @param setAccessibility true to enable accessibility features
* @return <b>this</b>
*/
- public FopConfBuilder setAccessibility(boolean setAccessibility) {
- return createElement("accessibility", String.valueOf(setAccessibility));
+ public FopConfBuilder setAccessibility(boolean setAccessibility, boolean keepEmptyTags) {
+ Element el = fopConfDOM.createElement(Accessibility.ACCESSIBILITY);
+ el.setAttribute(Accessibility.KEEP_EMPTY_TAGS, String.valueOf(keepEmptyTags));
+ el.appendChild(fopConfDOM.createTextNode(String.valueOf(setAccessibility)));
+ root.appendChild(el);
+ return this;
}
@Deprecated
diff --git a/fop-core/src/test/java/org/apache/fop/apps/FopConfParserTestCase.java b/fop-core/src/test/java/org/apache/fop/apps/FopConfParserTestCase.java
index dc794fdb8..d632c02f3 100644
--- a/fop-core/src/test/java/org/apache/fop/apps/FopConfParserTestCase.java
+++ b/fop-core/src/test/java/org/apache/fop/apps/FopConfParserTestCase.java
@@ -89,11 +89,17 @@ public class FopConfParserTestCase {
@Test
public void testAccessibility() {
- builder.setAccessibility(false);
+ builder.setAccessibility(false, true);
assertFalse(buildFactory().isAccessibilityEnabled());
}
@Test
+ public void testAccessibilityKeepEmptyTags() {
+ builder.setAccessibility(true, false);
+ assertFalse(buildFactory().isKeepEmptyTags());
+ }
+
+ @Test
public void testSourceResolution() {
float srcRes = 123.456f;
builder.setSourceResolution(srcRes);
diff --git a/fop-core/src/test/java/org/apache/fop/apps/MutableConfig.java b/fop-core/src/test/java/org/apache/fop/apps/MutableConfig.java
index 201408235..2f70f4124 100644
--- a/fop-core/src/test/java/org/apache/fop/apps/MutableConfig.java
+++ b/fop-core/src/test/java/org/apache/fop/apps/MutableConfig.java
@@ -52,6 +52,11 @@ public final class MutableConfig implements FopFactoryConfig {
return delegate.isAccessibilityEnabled();
}
+
+ public boolean isKeepEmptyTags() {
+ return delegate.isKeepEmptyTags();
+ }
+
public LayoutManagerMaker getLayoutManagerMakerOverride() {
return delegate.getLayoutManagerMakerOverride();
}