From bb52ebbf88d5df3d74f03f2ef8a5652222dd701f Mon Sep 17 00:00:00 2001 From: Simon Steiner Date: Tue, 2 Jul 2019 13:19:54 +0000 Subject: [PATCH] FOP-2871: Render space for accessible pdf git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1862426 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/fop/area/AreaTreeHandler.java | 2 +- .../org/apache/fop/area/inline/TextArea.java | 14 +-- .../org/apache/fop/area/inline/WordArea.java | 20 +++-- .../fop/layoutmgr/LayoutManagerMapping.java | 60 +++++++------ .../layoutmgr/inline/TextLayoutManager.java | 14 ++- .../intermediate/AbstractIFPainter.java | 4 + .../fop/render/intermediate/IFPainter.java | 3 + .../fop/render/intermediate/IFParser.java | 3 +- .../fop/render/intermediate/IFRenderer.java | 10 ++- .../fop/render/intermediate/IFSerializer.java | 11 ++- .../org/apache/fop/render/pdf/PDFPainter.java | 8 ++ ...TableMarkerLayoutManagerMakerTestCase.java | 4 +- .../intermediate/IFRendererTestCase.java | 86 +++++++++++++++++++ 13 files changed, 191 insertions(+), 48 deletions(-) create mode 100644 fop-core/src/test/java/org/apache/fop/render/intermediate/IFRendererTestCase.java diff --git a/fop-core/src/main/java/org/apache/fop/area/AreaTreeHandler.java b/fop-core/src/main/java/org/apache/fop/area/AreaTreeHandler.java index fda5ad07b..d3a17732b 100644 --- a/fop-core/src/main/java/org/apache/fop/area/AreaTreeHandler.java +++ b/fop-core/src/main/java/org/apache/fop/area/AreaTreeHandler.java @@ -106,7 +106,7 @@ public class AreaTreeHandler extends FOEventHandler { this.lmMaker = userAgent.getLayoutManagerMakerOverride(); if (lmMaker == null) { - lmMaker = new LayoutManagerMapping(); + lmMaker = new LayoutManagerMapping(userAgent); } this.idTracker = new IDTracker(); diff --git a/fop-core/src/main/java/org/apache/fop/area/inline/TextArea.java b/fop-core/src/main/java/org/apache/fop/area/inline/TextArea.java index a03e536ce..a14a6aeb6 100644 --- a/fop-core/src/main/java/org/apache/fop/area/inline/TextArea.java +++ b/fop-core/src/main/java/org/apache/fop/area/inline/TextArea.java @@ -88,12 +88,11 @@ public class TextArea extends AbstractTextArea { * @param gposAdjustments array of general position adjustments or null if none apply * @param blockProgressionOffset the offset for the next area */ - public void addWord( - String word, int ipd, int[] letterAdjust, int[] levels, - int[][] gposAdjustments, int blockProgressionOffset) { + public void addWord(String word, int ipd, int[] letterAdjust, int[] levels, int[][] gposAdjustments, + int blockProgressionOffset, boolean nextIsSpace) { int minWordLevel = findMinLevel(levels, getBidiLevel()); - WordArea wordArea = new WordArea( - blockProgressionOffset, minWordLevel, word, letterAdjust, levels, gposAdjustments); + WordArea wordArea = new WordArea(blockProgressionOffset, minWordLevel, word, letterAdjust, levels, + gposAdjustments, false, nextIsSpace); wordArea.setIPD(ipd); wordArea.setChangeBarList(getChangeBarList()); addChildArea(wordArea); @@ -101,6 +100,11 @@ public class TextArea extends AbstractTextArea { updateLevel(minWordLevel); } + public void addWord(String word, int ipd, int[] letterAdjust, int[] levels, int[][] gposAdjustments, + int blockProgressionOffset) { + addWord(word, ipd, letterAdjust, levels, gposAdjustments, blockProgressionOffset, false); + } + /** * Create and add a SpaceArea child to this TextArea * diff --git a/fop-core/src/main/java/org/apache/fop/area/inline/WordArea.java b/fop-core/src/main/java/org/apache/fop/area/inline/WordArea.java index a00d7112b..55a44e681 100644 --- a/fop-core/src/main/java/org/apache/fop/area/inline/WordArea.java +++ b/fop-core/src/main/java/org/apache/fop/area/inline/WordArea.java @@ -54,6 +54,7 @@ public class WordArea extends InlineArea { * its original logical order. */ protected boolean reversed; + private boolean nextIsSpace; /** * Create a word area @@ -66,9 +67,8 @@ public class WordArea extends InlineArea { * @param gposAdjustments array of general position adjustments or null if none apply * @param reversed true if word is known to be reversed at construction time */ - public WordArea( - int blockProgressionOffset, int level, String word, int[] letterAdjust, int[] levels, - int[][] gposAdjustments, boolean reversed) { + public WordArea(int blockProgressionOffset, int level, String word, int[] letterAdjust, int[] levels, + int[][] gposAdjustments, boolean reversed, boolean nextIsSpace) { super(blockProgressionOffset, level); int length = (word != null) ? word.length() : 0; this.word = word; @@ -76,6 +76,12 @@ public class WordArea extends InlineArea { this.levels = maybePopulateLevels(levels, level, length); this.gposAdjustments = maybeAdjustLength(gposAdjustments, length); this.reversed = reversed; + this.nextIsSpace = nextIsSpace; + } + + public WordArea(int blockProgressionOffset, int level, String word, int[] letterAdjust, int[] levels, + int[][] gposAdjustments, boolean reversed) { + this(blockProgressionOffset, level, word, letterAdjust, levels, gposAdjustments, reversed, false); } /** @@ -89,8 +95,8 @@ public class WordArea extends InlineArea { * @param gposAdjustments array of general position adjustments or null if none apply */ public WordArea( - int blockProgressionOffset, int level, String word, int[] letterAdjust, int[] levels, - int[][] gposAdjustments) { + int blockProgressionOffset, int level, String word, int[] letterAdjust, int[] levels, + int[][] gposAdjustments) { this (blockProgressionOffset, level, word, letterAdjust, levels, gposAdjustments, false); } @@ -231,6 +237,10 @@ public class WordArea extends InlineArea { return reversed; } + public boolean isNextIsSpace() { + return nextIsSpace; + } + /* * If int[] array is not of specified length, then create * a new copy of the first length entries. diff --git a/fop-core/src/main/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java b/fop-core/src/main/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java index 3a706a325..4ab176b9e 100644 --- a/fop-core/src/main/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java +++ b/fop-core/src/main/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java @@ -28,6 +28,7 @@ import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.fop.apps.FOUserAgent; import org.apache.fop.area.AreaTreeHandler; import org.apache.fop.fo.FOElementMapping; import org.apache.fop.fo.FONode; @@ -104,8 +105,11 @@ public class LayoutManagerMapping implements LayoutManagerMaker { /** The map of LayoutManagerMakers */ private final Map makers = new HashMap(); + private FOUserAgent userAgent; + /** default constructor */ - public LayoutManagerMapping() { + public LayoutManagerMapping(FOUserAgent userAgent) { + this.userAgent = userAgent; initialize(); } @@ -176,7 +180,7 @@ public class LayoutManagerMapping implements LayoutManagerMaker { } } } else { - maker.make(node, lms); + maker.make(node, lms, userAgent); } } @@ -239,7 +243,7 @@ public class LayoutManagerMapping implements LayoutManagerMaker { * @param node the associated FO node * @param lms a list of layout managers to which new manager is to be added */ - public void make(FONode node, List lms) { + public void make(FONode node, List lms, FOUserAgent userAgent) { // no layout manager } } @@ -247,10 +251,10 @@ public class LayoutManagerMapping implements LayoutManagerMaker { /** a layout manager maker */ public static class FOTextLayoutManagerMaker extends Maker { /** {@inheritDoc} */ - public void make(FONode node, List lms) { + public void make(FONode node, List lms, FOUserAgent userAgent) { FOText foText = (FOText) node; if (foText.length() > 0) { - lms.add(new TextLayoutManager(foText)); + lms.add(new TextLayoutManager(foText, userAgent)); } } } @@ -258,7 +262,7 @@ public class LayoutManagerMapping implements LayoutManagerMaker { /** a layout manager maker */ public static class BidiOverrideLayoutManagerMaker extends Maker { /** {@inheritDoc} */ - public void make(FONode node, List lms) { + public void make(FONode node, List lms, FOUserAgent userAgent) { if (node instanceof BidiOverride) { lms.add(new BidiLayoutManager((BidiOverride) node)); } @@ -268,7 +272,7 @@ public class LayoutManagerMapping implements LayoutManagerMaker { /** a layout manager maker */ public static class InlineLayoutManagerMaker extends Maker { /** {@inheritDoc} */ - public void make(FONode node, List lms) { + public void make(FONode node, List lms, FOUserAgent userAgent) { lms.add(new InlineLayoutManager((InlineLevel) node)); } } @@ -276,7 +280,7 @@ public class LayoutManagerMapping implements LayoutManagerMaker { /** a layout manager maker */ public static class FootnoteLayoutManagerMaker extends Maker { /** {@inheritDoc} */ - public void make(FONode node, List lms) { + public void make(FONode node, List lms, FOUserAgent userAgent) { lms.add(new FootnoteLayoutManager((Footnote) node)); } } @@ -284,7 +288,7 @@ public class LayoutManagerMapping implements LayoutManagerMaker { /** a layout manager maker */ public static class InlineContainerLayoutManagerMaker extends Maker { /** {@inheritDoc} */ - public void make(FONode node, List lms) { + public void make(FONode node, List lms, FOUserAgent userAgent) { lms.add(new InlineContainerLayoutManager((InlineContainer) node)); } } @@ -292,7 +296,7 @@ public class LayoutManagerMapping implements LayoutManagerMaker { /** a layout manager maker */ public static class BasicLinkLayoutManagerMaker extends Maker { /** {@inheritDoc} */ - public void make(FONode node, List lms) { + public void make(FONode node, List lms, FOUserAgent userAgent) { lms.add(new BasicLinkLayoutManager((BasicLink) node)); } } @@ -300,7 +304,7 @@ public class LayoutManagerMapping implements LayoutManagerMaker { /** a layout manager maker */ public static class BlockLayoutManagerMaker extends Maker { /** {@inheritDoc} */ - public void make(FONode node, List lms) { + public void make(FONode node, List lms, FOUserAgent userAgent) { lms.add(new BlockLayoutManager((Block) node)); } } @@ -308,7 +312,7 @@ public class LayoutManagerMapping implements LayoutManagerMaker { /** a layout manager maker */ public static class LeaderLayoutManagerMaker extends Maker { /** {@inheritDoc} */ - public void make(FONode node, List lms) { + public void make(FONode node, List lms, FOUserAgent userAgent) { lms.add(new LeaderLayoutManager((Leader) node)); } } @@ -316,7 +320,7 @@ public class LayoutManagerMapping implements LayoutManagerMaker { /** a layout manager maker */ public static class CharacterLayoutManagerMaker extends Maker { /** {@inheritDoc} */ - public void make(FONode node, List lms) { + public void make(FONode node, List lms, FOUserAgent userAgent) { Character foCharacter = (Character) node; if (foCharacter.getCharacter() != CharUtilities.CODE_EOT) { lms.add(new CharacterLayoutManager(foCharacter)); @@ -327,7 +331,7 @@ public class LayoutManagerMapping implements LayoutManagerMaker { /** a layout manager maker */ public static class ExternalGraphicLayoutManagerMaker extends Maker { /** {@inheritDoc} */ - public void make(FONode node, List lms) { + public void make(FONode node, List lms, FOUserAgent userAgent) { ExternalGraphic eg = (ExternalGraphic) node; if (!eg.getSrc().equals("")) { lms.add(new ExternalGraphicLayoutManager(eg)); @@ -338,7 +342,7 @@ public class LayoutManagerMapping implements LayoutManagerMaker { /** a layout manager maker */ public static class BlockContainerLayoutManagerMaker extends Maker { /** {@inheritDoc} */ - public void make(FONode node, List lms) { + public void make(FONode node, List lms, FOUserAgent userAgent) { lms.add(new BlockContainerLayoutManager((BlockContainer) node)); } } @@ -346,7 +350,7 @@ public class LayoutManagerMapping implements LayoutManagerMaker { /** a layout manager maker */ public static class ListItemLayoutManagerMaker extends Maker { /** {@inheritDoc} */ - public void make(FONode node, List lms) { + public void make(FONode node, List lms, FOUserAgent userAgent) { lms.add(new ListItemLayoutManager((ListItem) node)); } } @@ -354,7 +358,7 @@ public class LayoutManagerMapping implements LayoutManagerMaker { /** a layout manager maker */ public static class ListBlockLayoutManagerMaker extends Maker { /** {@inheritDoc} */ - public void make(FONode node, List lms) { + public void make(FONode node, List lms, FOUserAgent userAgent) { lms.add(new ListBlockLayoutManager((ListBlock) node)); } } @@ -362,7 +366,7 @@ public class LayoutManagerMapping implements LayoutManagerMaker { /** a layout manager maker */ public static class InstreamForeignObjectLayoutManagerMaker extends Maker { /** {@inheritDoc} */ - public void make(FONode node, List lms) { + public void make(FONode node, List lms, FOUserAgent userAgent) { lms.add(new InstreamForeignObjectLM((InstreamForeignObject) node)); } } @@ -370,7 +374,7 @@ public class LayoutManagerMapping implements LayoutManagerMaker { /** a layout manager maker */ public static class PageNumberLayoutManagerMaker extends Maker { /** {@inheritDoc} */ - public void make(FONode node, List lms) { + public void make(FONode node, List lms, FOUserAgent userAgent) { lms.add(new PageNumberLayoutManager((PageNumber) node)); } } @@ -378,7 +382,7 @@ public class LayoutManagerMapping implements LayoutManagerMaker { /** a layout manager maker */ public static class PageNumberCitationLayoutManagerMaker extends Maker { /** {@inheritDoc} */ - public void make(FONode node, List lms) { + public void make(FONode node, List lms, FOUserAgent userAgent) { lms.add(new PageNumberCitationLayoutManager((PageNumberCitation) node)); } } @@ -386,7 +390,7 @@ public class LayoutManagerMapping implements LayoutManagerMaker { /** a layout manager maker */ public static class PageNumberCitationLastLayoutManagerMaker extends Maker { /** {@inheritDoc} */ - public void make(FONode node, List lms) { + public void make(FONode node, List lms, FOUserAgent userAgent) { lms.add(new PageNumberCitationLastLayoutManager((PageNumberCitationLast) node)); } } @@ -394,7 +398,7 @@ public class LayoutManagerMapping implements LayoutManagerMaker { /** a layout manager maker */ public static class TableLayoutManagerMaker extends Maker { /** {@inheritDoc} */ - public void make(FONode node, List lms) { + public void make(FONode node, List lms, FOUserAgent userAgent) { Table table = (Table) node; TableLayoutManager tlm = new TableLayoutManager(table); lms.add(tlm); @@ -404,7 +408,7 @@ public class LayoutManagerMapping implements LayoutManagerMaker { /** a layout manager maker */ public class RetrieveMarkerLayoutManagerMaker extends Maker { /** {@inheritDoc} */ - public void make(FONode node, List lms) { + public void make(FONode node, List lms, FOUserAgent userAgent) { Iterator baseIter; baseIter = node.getChildNodes(); if (baseIter == null) { @@ -418,7 +422,7 @@ public class LayoutManagerMapping implements LayoutManagerMaker { } public class RetrieveTableMarkerLayoutManagerMaker extends Maker { - public void make(FONode node, List lms) { + public void make(FONode node, List lms, FOUserAgent userAgent) { FONodeIterator baseIter = node.getChildNodes(); if (baseIter == null) { // this happens when the retrieve-table-marker cannot be resolved yet @@ -438,7 +442,7 @@ public class LayoutManagerMapping implements LayoutManagerMaker { /** a layout manager maker */ public class WrapperLayoutManagerMaker extends Maker { /** {@inheritDoc} */ - public void make(FONode node, List lms) { + public void make(FONode node, List lms, FOUserAgent userAgent) { //We insert the wrapper LM before it's children so an ID //on the node can be registered on a page. lms.add(new WrapperLayoutManager((Wrapper)node)); @@ -457,7 +461,7 @@ public class LayoutManagerMapping implements LayoutManagerMaker { public class MultiSwitchLayoutManagerMaker extends Maker { @Override - public void make(FONode node, List lms) { + public void make(FONode node, List lms, FOUserAgent userAgent) { lms.add(new MultiSwitchLayoutManager((MultiSwitch) node)); } } @@ -465,13 +469,13 @@ public class LayoutManagerMapping implements LayoutManagerMaker { public class MultiCaseLayoutManagerMaker extends Maker { @Override - public void make(FONode node, List lms) { + public void make(FONode node, List lms, FOUserAgent userAgent) { lms.add(new MultiCaseLayoutManager((MultiCase) node)); } } public static class FloatLayoutManagerMaker extends Maker { - public void make(FONode node, List lms) { + public void make(FONode node, List lms, FOUserAgent userAgent) { lms.add(new FloatLayoutManager((Float) node)); } } diff --git a/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java b/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java index 8611cbda5..7d2c79fd6 100644 --- a/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java +++ b/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java @@ -28,6 +28,7 @@ import java.util.ListIterator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.fop.apps.FOUserAgent; import org.apache.fop.area.Trait; import org.apache.fop.area.inline.TextArea; import org.apache.fop.fo.Constants; @@ -132,15 +133,17 @@ public class TextLayoutManager extends LeafNodeLayoutManager { private final Position auxiliaryPosition = new LeafPosition(this, -1); + private FOUserAgent userAgent; /** * Create a Text layout manager. * * @param node The FOText object to be rendered */ - public TextLayoutManager(FOText node) { + public TextLayoutManager(FOText node, FOUserAgent userAgent) { foText = node; letterSpaceAdjustArray = new MinOptMax[node.length() + 1]; mappings = new ArrayList(); + this.userAgent = userAgent; } private KnuthPenalty makeZeroWidthPenalty(int penaltyValue) { @@ -507,8 +510,13 @@ public class TextLayoutManager extends LeafNodeLayoutManager { if (!gposAdjusted) { gposAdjustments = null; } - textArea.addWord(wordChars.toString(), wordIPD, letterSpaceAdjust, - getNonEmptyLevels(), gposAdjustments, blockProgressionOffset); + textArea.addWord(wordChars.toString(), wordIPD, letterSpaceAdjust, getNonEmptyLevels(), gposAdjustments, + blockProgressionOffset, isWordSpace(endIndex + 1)); + } + + private boolean isWordSpace(int mappingIndex) { + return userAgent.isAccessibilityEnabled() + && mappingIndex < mappings.size() - 1 && getGlyphMapping(mappingIndex).isSpace; } private int[] getNonEmptyLevels() { diff --git a/fop-core/src/main/java/org/apache/fop/render/intermediate/AbstractIFPainter.java b/fop-core/src/main/java/org/apache/fop/render/intermediate/AbstractIFPainter.java index 694871bd8..19383be00 100644 --- a/fop-core/src/main/java/org/apache/fop/render/intermediate/AbstractIFPainter.java +++ b/fop-core/src/main/java/org/apache/fop/render/intermediate/AbstractIFPainter.java @@ -465,4 +465,8 @@ public abstract class AbstractIFPainter implements return true; } + public void drawText(int x, int y, int letterSpacing, int wordSpacing, + int[][] dp, String text, boolean nextIsSpace) throws IFException { + drawText(x, y, letterSpacing, wordSpacing, dp, text); + } } diff --git a/fop-core/src/main/java/org/apache/fop/render/intermediate/IFPainter.java b/fop-core/src/main/java/org/apache/fop/render/intermediate/IFPainter.java index d43b5cb85..863f97c7c 100644 --- a/fop-core/src/main/java/org/apache/fop/render/intermediate/IFPainter.java +++ b/fop-core/src/main/java/org/apache/fop/render/intermediate/IFPainter.java @@ -162,6 +162,9 @@ public interface IFPainter { void drawText(int x, int y, int letterSpacing, int wordSpacing, int[][] dp, String text) throws IFException; + void drawText(int x, int y, int letterSpacing, int wordSpacing, int[][] dp, String text, boolean nextIsSpace) + throws IFException; + /** * Restricts the current clipping region with the given rectangle. * @param rect the rectangle's coordinates and extent diff --git a/fop-core/src/main/java/org/apache/fop/render/intermediate/IFParser.java b/fop-core/src/main/java/org/apache/fop/render/intermediate/IFParser.java index 8d562e465..241d74fc3 100644 --- a/fop-core/src/main/java/org/apache/fop/render/intermediate/IFParser.java +++ b/fop-core/src/main/java/org/apache/fop/render/intermediate/IFParser.java @@ -656,7 +656,8 @@ public class IFParser implements IFConstants { if (isHyphenated) { documentHandler.getContext().setHyphenated(isHyphenated); } - painter.drawText(x, y, letterSpacing, wordSpacing, dp, content.toString()); + boolean nextIsSpace = Boolean.valueOf(lastAttributes.getValue("next-is-space")); + painter.drawText(x, y, letterSpacing, wordSpacing, dp, content.toString(), nextIsSpace); documentHandler.getContext().setHyphenated(false); resetStructureTreeElement(); } diff --git a/fop-core/src/main/java/org/apache/fop/render/intermediate/IFRenderer.java b/fop-core/src/main/java/org/apache/fop/render/intermediate/IFRenderer.java index 471068370..c0c70934c 100644 --- a/fop-core/src/main/java/org/apache/fop/render/intermediate/IFRenderer.java +++ b/fop-core/src/main/java/org/apache/fop/render/intermediate/IFRenderer.java @@ -1085,6 +1085,7 @@ public class IFRenderer extends AbstractPathOrientedRenderer { font, (AbstractTextArea) parentArea); } + textUtil.nextIsSpace = word.isNextIsSpace(); super.renderWord(word); } @@ -1172,7 +1173,7 @@ public class IFRenderer extends AbstractPathOrientedRenderer { private int starty; private int tls; private int tws; - // private final static boolean COMBINED = false; // no longer referenced + private boolean nextIsSpace; void addChar(char ch) { text.append(ch); @@ -1234,7 +1235,7 @@ public class IFRenderer extends AbstractPathOrientedRenderer { trimAdjustments(dp, text.length()), text.toString()); } else { */ painter.drawText(startx, starty, tls, tws, - trimAdjustments(dp, text.length()), text.toString()); + trimAdjustments(dp, text.length()), text.toString(), nextIsSpace); /* } */ } catch (IFException e) { handleIFException(e); @@ -1243,6 +1244,11 @@ public class IFRenderer extends AbstractPathOrientedRenderer { } } + void drawText(int x, int y, int letterSpacing, int wordSpacing, int[][] dx, String text, boolean nextIsSpace) + throws IFException { + painter.drawText(startx, starty, tls, tws, dx, text, nextIsSpace); + } + /** * Trim adjustments array dp to be no greater length than * text length, and where trailing all-zero entries are removed. diff --git a/fop-core/src/main/java/org/apache/fop/render/intermediate/IFSerializer.java b/fop-core/src/main/java/org/apache/fop/render/intermediate/IFSerializer.java index 054f0f5cc..dd8a946c2 100644 --- a/fop-core/src/main/java/org/apache/fop/render/intermediate/IFSerializer.java +++ b/fop-core/src/main/java/org/apache/fop/render/intermediate/IFSerializer.java @@ -669,12 +669,21 @@ implements IFConstants, IFPainter, IFDocumentNavigationHandler { /** {@inheritDoc} */ public void drawText(int x, int y, int letterSpacing, int wordSpacing, - int[][] dp, String text) throws IFException { + int[][] dp, String text) throws IFException { + drawText(x, y, letterSpacing, wordSpacing, dp, text, false); + } + + /** {@inheritDoc} */ + public void drawText(int x, int y, int letterSpacing, int wordSpacing, + int[][] dp, String text, boolean nextIsSpace) throws IFException { try { addID(); AttributesImpl atts = new AttributesImpl(); addAttribute(atts, "x", Integer.toString(x)); addAttribute(atts, "y", Integer.toString(y)); + if (nextIsSpace) { + addAttribute(atts, "next-is-space", "true"); + } if (letterSpacing != 0) { addAttribute(atts, "letter-spacing", Integer.toString(letterSpacing)); } diff --git a/fop-core/src/main/java/org/apache/fop/render/pdf/PDFPainter.java b/fop-core/src/main/java/org/apache/fop/render/pdf/PDFPainter.java index de8b42aec..1ab1a8a9e 100644 --- a/fop-core/src/main/java/org/apache/fop/render/pdf/PDFPainter.java +++ b/fop-core/src/main/java/org/apache/fop/render/pdf/PDFPainter.java @@ -441,6 +441,14 @@ public class PDFPainter extends AbstractIFPainter { } } + public void drawText(int x, int y, int letterSpacing, int wordSpacing, int[][] dp, String text, boolean nextIsSpace) + throws IFException { + if (accessEnabled && nextIsSpace) { + text += ' '; + } + drawText(x, y, letterSpacing, wordSpacing, dp, text); + } + private void drawTextWithDX(int x, int y, String text, FontTriplet triplet, int letterSpacing, int wordSpacing, int[] dx) throws IFException { //TODO Ignored: state.getFontVariant() diff --git a/fop-core/src/test/java/org/apache/fop/layoutmgr/RetrieveTableMarkerLayoutManagerMakerTestCase.java b/fop-core/src/test/java/org/apache/fop/layoutmgr/RetrieveTableMarkerLayoutManagerMakerTestCase.java index 6a37de33c..b0d0181e3 100644 --- a/fop-core/src/test/java/org/apache/fop/layoutmgr/RetrieveTableMarkerLayoutManagerMakerTestCase.java +++ b/fop-core/src/test/java/org/apache/fop/layoutmgr/RetrieveTableMarkerLayoutManagerMakerTestCase.java @@ -44,11 +44,11 @@ public class RetrieveTableMarkerLayoutManagerMakerTestCase { RetrieveTableMarker rtm = mock(RetrieveTableMarker.class); // real RTMLMM, not mock List l = new ArrayList(); - LayoutManagerMapping lmm = new LayoutManagerMapping(); + LayoutManagerMapping lmm = new LayoutManagerMapping(null); RetrieveTableMarkerLayoutManagerMaker rtmlmm = lmm.new RetrieveTableMarkerLayoutManagerMaker(); // test the case rtm has no child nodes when(rtm.getChildNodes()).thenReturn(null); - rtmlmm.make(rtm, l); + rtmlmm.make(rtm, l, null); assertTrue(l.size() == 1); assertTrue(l.get(0) instanceof RetrieveTableMarkerLayoutManager); } diff --git a/fop-core/src/test/java/org/apache/fop/render/intermediate/IFRendererTestCase.java b/fop-core/src/test/java/org/apache/fop/render/intermediate/IFRendererTestCase.java new file mode 100644 index 000000000..20c26b97b --- /dev/null +++ b/fop-core/src/test/java/org/apache/fop/render/intermediate/IFRendererTestCase.java @@ -0,0 +1,86 @@ +/* + * 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.intermediate; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.sax.SAXResult; +import javax.xml.transform.stream.StreamSource; + +import org.junit.Assert; +import org.junit.Test; + +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.area.inline.WordArea; + +public class IFRendererTestCase { + private List wordAreas = new ArrayList(); + + private void foToOutput(InputStream fo) throws FOPException, TransformerException { + FopFactoryBuilder fopFactoryBuilder = new FopFactoryBuilder(new File(".").toURI()); + fopFactoryBuilder.setAccessibility(true); + FopFactory fopFactory = fopFactoryBuilder.build(); + FOUserAgent userAgent = fopFactory.newFOUserAgent(); + IFRenderer ifRenderer = new IFRenderer(userAgent) { + protected void renderWord(WordArea word) { + wordAreas.add(word); + super.renderWord(word); + } + }; + userAgent.setRendererOverride(ifRenderer); + Fop fop = fopFactory.newFop("application/pdf", userAgent, new ByteArrayOutputStream()); + Transformer transformer = TransformerFactory.newInstance().newTransformer(); + Source src = new StreamSource(fo); + Result res = new SAXResult(fop.getDefaultHandler()); + transformer.transform(src, res); + } + + @Test + public void testWordSpace() throws FOPException, TransformerException { + String fo = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " test test\n" + + " \n" + + " \n" + + ""; + foToOutput(new ByteArrayInputStream(fo.getBytes())); + Assert.assertTrue(wordAreas.get(0).isNextIsSpace()); + Assert.assertFalse(wordAreas.get(1).isNextIsSpace()); + } +} -- 2.39.5