Browse Source

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
tags/fop-2_5
Simon Steiner 4 years ago
parent
commit
895a332bd6

+ 3
- 0
fop-core/src/main/java/org/apache/fop/accessibility/Accessibility.java View File

@@ -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.

+ 61
- 0
fop-core/src/main/java/org/apache/fop/accessibility/fo/Event.java View File

@@ -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);
}
}

+ 406
- 122
fop-core/src/main/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverter.java View File

@@ -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);
}


+ 14
- 0
fop-core/src/main/java/org/apache/fop/apps/FOUserAgent.java View File

@@ -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;
}
}
}

+ 3
- 0
fop-core/src/main/java/org/apache/fop/apps/FopConfParser.java View File

@@ -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);
}

+ 4
- 0
fop-core/src/main/java/org/apache/fop/apps/FopFactory.java View File

@@ -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();

+ 19
- 0
fop-core/src/main/java/org/apache/fop/apps/FopFactoryBuilder.java View File

@@ -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;
}

+ 1
- 0
fop-core/src/main/java/org/apache/fop/apps/FopFactoryConfig.java View File

@@ -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.

+ 52
- 0
fop-core/src/test/java/org/apache/fop/accessibility/fo/FO2StructureTreeConverterTestCase.java View File

@@ -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;
}


+ 7
- 2
fop-core/src/test/java/org/apache/fop/apps/FopConfBuilder.java View File

@@ -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

+ 7
- 1
fop-core/src/test/java/org/apache/fop/apps/FopConfParserTestCase.java View File

@@ -89,10 +89,16 @@ 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;

+ 5
- 0
fop-core/src/test/java/org/apache/fop/apps/MutableConfig.java View File

@@ -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();
}

Loading…
Cancel
Save