aboutsummaryrefslogtreecommitdiffstats
path: root/src/java/org/apache/fop/render/intermediate
diff options
context:
space:
mode:
authorPeter Hancock <phancock@apache.org>2012-06-29 11:22:42 +0000
committerPeter Hancock <phancock@apache.org>2012-06-29 11:22:42 +0000
commit3e31e071ea47f37ef7f8749b324dfdfe76745d18 (patch)
tree7d3b646c521349634592b62556a8832ec082cc9c /src/java/org/apache/fop/render/intermediate
parentae8a5035235e1262e412e1eacd0eb3adfaef83ef (diff)
parent015538e0f11f031e3d7bd05db8c29e2a40365678 (diff)
downloadxmlgraphics-fop-3e31e071ea47f37ef7f8749b324dfdfe76745d18.tar.gz
xmlgraphics-fop-3e31e071ea47f37ef7f8749b324dfdfe76745d18.zip
Merged trunk@1354651
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_RoundedCorners@1355321 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/java/org/apache/fop/render/intermediate')
-rw-r--r--src/java/org/apache/fop/render/intermediate/AbstractIFDocumentHandler.java14
-rw-r--r--src/java/org/apache/fop/render/intermediate/AbstractIFPainter.java59
-rw-r--r--src/java/org/apache/fop/render/intermediate/BorderPainter.java254
-rw-r--r--src/java/org/apache/fop/render/intermediate/EventProducingFilter.java54
-rw-r--r--src/java/org/apache/fop/render/intermediate/IFConstants.java4
-rw-r--r--src/java/org/apache/fop/render/intermediate/IFContext.java54
-rw-r--r--src/java/org/apache/fop/render/intermediate/IFDocumentHandler.java16
-rw-r--r--src/java/org/apache/fop/render/intermediate/IFGraphicContext.java15
-rw-r--r--src/java/org/apache/fop/render/intermediate/IFPainter.java18
-rw-r--r--src/java/org/apache/fop/render/intermediate/IFParser.java180
-rw-r--r--src/java/org/apache/fop/render/intermediate/IFRenderer.java279
-rw-r--r--src/java/org/apache/fop/render/intermediate/IFSerializer.java176
-rw-r--r--src/java/org/apache/fop/render/intermediate/IFSerializerMaker.java3
-rw-r--r--src/java/org/apache/fop/render/intermediate/IFState.java4
-rw-r--r--src/java/org/apache/fop/render/intermediate/IFStructureTreeBuilder.java239
-rw-r--r--src/java/org/apache/fop/render/intermediate/IFUtil.java195
-rw-r--r--src/java/org/apache/fop/render/intermediate/extensions/AbstractAction.java14
-rw-r--r--src/java/org/apache/fop/render/intermediate/extensions/DocumentNavigationHandler.java26
-rw-r--r--src/java/org/apache/fop/render/intermediate/extensions/GoToXYAction.java10
-rw-r--r--src/java/org/apache/fop/render/intermediate/util/IFConcatenator.java11
-rw-r--r--src/java/org/apache/fop/render/intermediate/util/IFDocumentHandlerProxy.java15
21 files changed, 1244 insertions, 396 deletions
diff --git a/src/java/org/apache/fop/render/intermediate/AbstractIFDocumentHandler.java b/src/java/org/apache/fop/render/intermediate/AbstractIFDocumentHandler.java
index b156b6c3a..2b90e4a7b 100644
--- a/src/java/org/apache/fop/render/intermediate/AbstractIFDocumentHandler.java
+++ b/src/java/org/apache/fop/render/intermediate/AbstractIFDocumentHandler.java
@@ -19,6 +19,10 @@
package org.apache.fop.render.intermediate;
+import java.util.Locale;
+
+import org.apache.fop.accessibility.DummyStructureTreeEventHandler;
+import org.apache.fop.accessibility.StructureTreeEventHandler;
import org.apache.fop.apps.FOUserAgent;
/**
@@ -53,6 +57,11 @@ public abstract class AbstractIFDocumentHandler implements IFDocumentHandler {
}
/** {@inheritDoc} */
+ public StructureTreeEventHandler getStructureTreeEventHandler() {
+ return DummyStructureTreeEventHandler.INSTANCE;
+ }
+
+ /** {@inheritDoc} */
public IFDocumentNavigationHandler getDocumentNavigationHandler() {
return null; //By default, this is not supported
}
@@ -66,6 +75,10 @@ public abstract class AbstractIFDocumentHandler implements IFDocumentHandler {
}
/** {@inheritDoc} */
+ public void setDocumentLocale(Locale locale) {
+ }
+
+ /** {@inheritDoc} */
public void startDocumentHeader() throws IFException {
//nop
}
@@ -104,5 +117,4 @@ public abstract class AbstractIFDocumentHandler implements IFDocumentHandler {
public void endPageTrailer() throws IFException {
//nop
}
-
}
diff --git a/src/java/org/apache/fop/render/intermediate/AbstractIFPainter.java b/src/java/org/apache/fop/render/intermediate/AbstractIFPainter.java
index ca907eb0d..9651cf446 100644
--- a/src/java/org/apache/fop/render/intermediate/AbstractIFPainter.java
+++ b/src/java/org/apache/fop/render/intermediate/AbstractIFPainter.java
@@ -46,6 +46,7 @@ import org.apache.xmlgraphics.image.loader.util.ImageUtil;
import org.apache.fop.ResourceEventProducer;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.FopFactory;
+import org.apache.fop.fo.Constants;
import org.apache.fop.render.ImageHandler;
import org.apache.fop.render.ImageHandlerRegistry;
import org.apache.fop.render.ImageHandlerUtil;
@@ -314,34 +315,60 @@ public abstract class AbstractIFPainter implements IFPainter {
}
/** {@inheritDoc} */
- public void drawBorderRect(Rectangle rect, BorderProps before, BorderProps after,
- BorderProps start, BorderProps end, Color innerBackgroundColor) throws IFException {
- if (before != null) {
+ public void drawBorderRect(Rectangle rect, BorderProps top, BorderProps bottom,
+ BorderProps left, BorderProps right, Color innerBackgroundColor) throws IFException {
+ if (top != null) {
Rectangle b = new Rectangle(
rect.x, rect.y,
- rect.width, before.width);
- fillRect(b, before.color);
+ rect.width, top.width);
+ fillRect(b, top.color);
}
- if (end != null) {
+ if (right != null) {
Rectangle b = new Rectangle(
- rect.x + rect.width - end.width, rect.y,
- end.width, rect.height);
- fillRect(b, end.color);
+ rect.x + rect.width - right.width, rect.y,
+ right.width, rect.height);
+ fillRect(b, right.color);
}
- if (after != null) {
+ if (bottom != null) {
Rectangle b = new Rectangle(
- rect.x, rect.y + rect.height - after.width,
- rect.width, after.width);
- fillRect(b, after.color);
+ rect.x, rect.y + rect.height - bottom.width,
+ rect.width, bottom.width);
+ fillRect(b, bottom.color);
}
- if (start != null) {
+ if (left != null) {
Rectangle b = new Rectangle(
rect.x, rect.y,
- start.width, rect.height);
- fillRect(b, start.color);
+ left.width, rect.height);
+ fillRect(b, left.color);
}
}
+ /**
+ * Indicates whether the given border segments (if present) have only solid borders, i.e.
+ * could be painted in a simplified fashion keeping the output file smaller.
+ * @param top the border segment on the top edge
+ * @param bottom the border segment on the bottom edge
+ * @param left the border segment on the left edge
+ * @param right the border segment on the right edge
+ * @return true if any border segment has a non-solid border style
+ */
+ protected boolean hasOnlySolidBorders(BorderProps top, BorderProps bottom,
+ BorderProps left, BorderProps right) {
+ if (top != null && top.style != Constants.EN_SOLID) {
+ return false;
+ }
+ if (bottom != null && bottom.style != Constants.EN_SOLID) {
+ return false;
+ }
+ if (left != null && left.style != Constants.EN_SOLID) {
+ return false;
+ }
+ if (right != null && right.style != Constants.EN_SOLID) {
+ return false;
+ }
+ return true;
+ }
+
/** {@inheritDoc} */
public void drawLine(Point start, Point end, int width, Color color, RuleStyle style)
throws IFException {
diff --git a/src/java/org/apache/fop/render/intermediate/BorderPainter.java b/src/java/org/apache/fop/render/intermediate/BorderPainter.java
index 5cf50ecbb..0ff5c2036 100644
--- a/src/java/org/apache/fop/render/intermediate/BorderPainter.java
+++ b/src/java/org/apache/fop/render/intermediate/BorderPainter.java
@@ -36,36 +36,36 @@ public abstract class BorderPainter {
public static final String ROUNDED_CORNERS = "fop.round-corners";
/** TODO Use a class to model border instead of an array
- * convention index of before, end, after and start borders */
- protected static final int BEFORE = 0, END = 1, AFTER = 2, START = 3;
+ * convention index of top, bottom, right and left borders */
+ protected static final int TOP = 0, RIGHT = 1, BOTTOM = 2, LEFT = 3;
/** TODO Use a class to model border corners instead of an array
- convention index of before_start, before_end, after_end and after_start border corners*/
- protected static final int BEFORE_START = 0, BEFORE_END = 1, AFTER_END = 2, AFTER_START = 3;
+ convention index of top-left, top-right, bottom-right and bottom-left border corners*/
+ protected static final int TOP_LEFT = 0, TOP_RIGHT = 1, BOTTOM_RIGHT = 2, BOTTOM_LEFT = 3;
/**
* Draws borders.
* @param borderRect the border rectangle
- * @param bpsBefore the border specification on the before side
- * @param bpsAfter the border specification on the after side
- * @param bpsStart the border specification on the start side
- * @param bpsEnd the border specification on the end side
+ * @param bpsTop the border specification on the top side
+ * @param bpsBottom the border specification on the bottom side
+ * @param bpsLeft the border specification on the left side
+ * @param bpsRight the border specification on the end side
* @param innerBackgroundColor the inner background color
* @throws IFException if an error occurs while drawing the borders
*/
public void drawBorders(Rectangle borderRect, // CSOK: MethodLength
- BorderProps bpsBefore, BorderProps bpsAfter,
- BorderProps bpsStart, BorderProps bpsEnd, Color innerBackgroundColor)
+ BorderProps bpsTop, BorderProps bpsBottom,
+ BorderProps bpsLeft, BorderProps bpsRight, Color innerBackgroundColor)
throws IFException {
try {
if (isRoundedCornersSupported()) {
- drawRoundedBorders(borderRect, bpsBefore, bpsAfter,
- bpsStart, bpsEnd);
+ drawRoundedBorders(borderRect, bpsTop, bpsBottom,
+ bpsLeft, bpsRight);
} else {
- drawRectangularBorders(borderRect, bpsBefore, bpsAfter,
- bpsStart, bpsEnd);
+ drawRectangularBorders(borderRect, bpsTop, bpsBottom,
+ bpsLeft, bpsRight);
}
} catch (IOException ioe) {
@@ -80,61 +80,59 @@ public abstract class BorderPainter {
/**
* TODO merge with drawRoundedBorders()?
* @param borderRect the border rectangle
- * @param bpsBefore the border specification on the before side
- * @param bpsAfter the border specification on the after side
- * @param bpsStart the border specification on the start side
- * @param bpsEnd the border specification on the end side
+ * @param bpsTop the border specification on the top side
+ * @param bpsBottom the border specification on the bottom side
+ * @param bpsLeft the border specification on the left side
+ * @param bpsRight the border specification on the end side
* @throws IOException
*/
protected void drawRectangularBorders(Rectangle borderRect,
- BorderProps bpsBefore, BorderProps bpsAfter,
- BorderProps bpsStart, BorderProps bpsEnd) throws IOException {
+ BorderProps bpsTop, BorderProps bpsBottom,
+ BorderProps bpsLeft, BorderProps bpsRight) throws IOException {
+
+ bpsTop = sanitizeBorderProps(bpsTop);
+ bpsBottom = sanitizeBorderProps(bpsBottom);
+ bpsLeft = sanitizeBorderProps(bpsLeft);
+ bpsRight = sanitizeBorderProps(bpsRight);
- bpsBefore = sanitizeBorderProps(bpsBefore);
- bpsAfter = sanitizeBorderProps(bpsAfter);
- bpsStart = sanitizeBorderProps(bpsStart);
- bpsEnd = sanitizeBorderProps(bpsEnd);
int startx = borderRect.x;
int starty = borderRect.y;
int width = borderRect.width;
int height = borderRect.height;
boolean[] b = new boolean[] {
- (bpsBefore != null), (bpsEnd != null),
- (bpsAfter != null), (bpsStart != null)};
+ (bpsTop != null), (bpsRight != null),
+ (bpsBottom != null), (bpsLeft != null)};
if (!b[0] && !b[1] && !b[2] && !b[3]) {
return;
}
int[] bw = new int[] {
- (b[BEFORE] ? bpsBefore.width : 0),
- (b[END] ? bpsEnd.width : 0),
- (b[AFTER] ? bpsAfter.width : 0),
- (b[3] ? bpsStart.width : 0)};
+ (b[0] ? bpsTop.width : 0),
+ (b[1] ? bpsRight.width : 0),
+ (b[2] ? bpsBottom.width : 0),
+ (b[3] ? bpsLeft.width : 0)};
int[] clipw = new int[] {
- BorderProps.getClippedWidth(bpsBefore),
- BorderProps.getClippedWidth(bpsEnd),
- BorderProps.getClippedWidth(bpsAfter),
- BorderProps.getClippedWidth(bpsStart)};
- starty += clipw[BEFORE];
- height -= clipw[BEFORE];
- height -= clipw[AFTER];
- startx += clipw[START];
- width -= clipw[START];
- width -= clipw[END];
+ BorderProps.getClippedWidth(bpsTop),
+ BorderProps.getClippedWidth(bpsRight),
+ BorderProps.getClippedWidth(bpsBottom),
+ BorderProps.getClippedWidth(bpsLeft)};
+ starty += clipw[0];
+ height -= clipw[0];
+ height -= clipw[2];
+ startx += clipw[3];
+ width -= clipw[3];
+ width -= clipw[1];
boolean[] slant = new boolean[] {
- (b[START] && b[BEFORE]),
- (b[BEFORE] && b[END]),
- (b[END] && b[AFTER]),
- (b[AFTER] && b[START])};
- if (bpsBefore != null) {
+ (b[3] && b[0]), (b[0] && b[1]), (b[1] && b[2]), (b[2] && b[3])};
+ if (bpsTop != null) {
int sx1 = startx;
- int sx2 = (slant[BEFORE_START] ? sx1 + bw[START] - clipw[START] : sx1);
+ int sx2 = (slant[TOP_LEFT] ? sx1 + bw[LEFT] - clipw[LEFT] : sx1);
int ex1 = startx + width;
- int ex2 = (slant[BEFORE_END] ? ex1 - bw[END] + clipw[END] : ex1);
- int outery = starty - clipw[BEFORE];
- int clipy = outery + clipw[BEFORE];
- int innery = outery + bw[BEFORE];
+ int ex2 = (slant[TOP_RIGHT] ? ex1 - bw[RIGHT] + clipw[RIGHT] : ex1);
+ int outery = starty - clipw[TOP];
+ int clipy = outery + clipw[TOP];
+ int innery = outery + bw[TOP];
saveGraphicsState();
moveTo(sx1, clipy);
@@ -142,12 +140,12 @@ public abstract class BorderPainter {
int sx1a = sx1;
int ex1a = ex1;
- if (bpsBefore.mode == BorderProps.COLLAPSE_OUTER) {
- if (bpsStart != null && bpsStart.mode == BorderProps.COLLAPSE_OUTER) {
- sx1a -= clipw[START];
+ if (bpsTop.mode == BorderProps.COLLAPSE_OUTER) {
+ if (bpsLeft != null && bpsLeft.mode == BorderProps.COLLAPSE_OUTER) {
+ sx1a -= clipw[3];
}
- if (bpsEnd != null && bpsEnd.mode == BorderProps.COLLAPSE_OUTER) {
- ex1a += clipw[END];
+ if (bpsRight != null && bpsRight.mode == BorderProps.COLLAPSE_OUTER) {
+ ex1a += clipw[1];
}
lineTo(sx1a, outery);
lineTo(ex1a, outery);
@@ -158,28 +156,28 @@ public abstract class BorderPainter {
closePath();
clip();
drawBorderLine(sx1a, outery, ex1a, innery, true, true,
- bpsBefore.style, bpsBefore.color);
+ bpsTop.style, bpsTop.color);
restoreGraphicsState();
}
- if (bpsEnd != null) {
+ if (bpsRight != null) {
int sy1 = starty;
- int sy2 = (slant[BEFORE_END] ? sy1 + bw[BEFORE] - clipw[BEFORE] : sy1);
+ int sy2 = (slant[TOP_RIGHT] ? sy1 + bw[TOP] - clipw[TOP] : sy1);
int ey1 = starty + height;
- int ey2 = (slant[AFTER_END] ? ey1 - bw[AFTER] + clipw[AFTER] : ey1);
- int outerx = startx + width + clipw[END];
- int clipx = outerx - clipw[END];
- int innerx = outerx - bw[END];
+ int ey2 = (slant[BOTTOM_RIGHT] ? ey1 - bw[BOTTOM] + clipw[BOTTOM] : ey1);
+ int outerx = startx + width + clipw[RIGHT];
+ int clipx = outerx - clipw[RIGHT];
+ int innerx = outerx - bw[RIGHT];
saveGraphicsState();
moveTo(clipx, sy1);
int sy1a = sy1;
int ey1a = ey1;
- if (bpsEnd.mode == BorderProps.COLLAPSE_OUTER) {
- if (bpsBefore != null && bpsBefore.mode == BorderProps.COLLAPSE_OUTER) {
- sy1a -= clipw[BEFORE];
+ if (bpsRight.mode == BorderProps.COLLAPSE_OUTER) {
+ if (bpsTop != null && bpsTop.mode == BorderProps.COLLAPSE_OUTER) {
+ sy1a -= clipw[TOP];
}
- if (bpsAfter != null && bpsAfter.mode == BorderProps.COLLAPSE_OUTER) {
- ey1a += clipw[AFTER];
+ if (bpsBottom != null && bpsBottom.mode == BorderProps.COLLAPSE_OUTER) {
+ ey1a += clipw[BOTTOM];
}
lineTo(outerx, sy1a);
lineTo(outerx, ey1a);
@@ -189,28 +187,29 @@ public abstract class BorderPainter {
lineTo(innerx, sy2);
closePath();
clip();
- drawBorderLine(innerx, sy1a, outerx, ey1a, false, false, bpsEnd.style, bpsEnd.color);
+ drawBorderLine(innerx, sy1a, outerx, ey1a, false, false,
+ bpsRight.style, bpsRight.color);
restoreGraphicsState();
}
- if (bpsAfter != null) {
+ if (bpsBottom != null) {
int sx1 = startx;
- int sx2 = (slant[AFTER_START] ? sx1 + bw[START] - clipw[START] : sx1);
+ int sx2 = (slant[BOTTOM_LEFT] ? sx1 + bw[LEFT] - clipw[LEFT] : sx1);
int ex1 = startx + width;
- int ex2 = (slant[AFTER_END] ? ex1 - bw[END] + clipw[END] : ex1);
- int outery = starty + height + clipw[AFTER];
- int clipy = outery - clipw[AFTER];
- int innery = outery - bw[AFTER];
+ int ex2 = (slant[BOTTOM_RIGHT] ? ex1 - bw[RIGHT] + clipw[RIGHT] : ex1);
+ int outery = starty + height + clipw[BOTTOM];
+ int clipy = outery - clipw[BOTTOM];
+ int innery = outery - bw[BOTTOM];
saveGraphicsState();
moveTo(ex1, clipy);
int sx1a = sx1;
int ex1a = ex1;
- if (bpsAfter.mode == BorderProps.COLLAPSE_OUTER) {
- if (bpsStart != null && bpsStart.mode == BorderProps.COLLAPSE_OUTER) {
- sx1a -= clipw[START];
+ if (bpsBottom.mode == BorderProps.COLLAPSE_OUTER) {
+ if (bpsLeft != null && bpsLeft.mode == BorderProps.COLLAPSE_OUTER) {
+ sx1a -= clipw[LEFT];
}
- if (bpsEnd != null && bpsEnd.mode == BorderProps.COLLAPSE_OUTER) {
- ex1a += clipw[END];
+ if (bpsRight != null && bpsRight.mode == BorderProps.COLLAPSE_OUTER) {
+ ex1a += clipw[RIGHT];
}
lineTo(ex1a, outery);
lineTo(sx1a, outery);
@@ -220,17 +219,18 @@ public abstract class BorderPainter {
lineTo(ex2, innery);
closePath();
clip();
- drawBorderLine(sx1a, innery, ex1a, outery, true, false, bpsAfter.style, bpsAfter.color);
+ drawBorderLine(sx1a, innery, ex1a, outery, true, false,
+ bpsBottom.style, bpsBottom.color);
restoreGraphicsState();
}
- if (bpsStart != null) {
+ if (bpsLeft != null) {
int sy1 = starty;
- int sy2 = (slant[BEFORE_START] ? sy1 + bw[BEFORE] - clipw[BEFORE] : sy1);
+ int sy2 = (slant[TOP_LEFT] ? sy1 + bw[TOP] - clipw[TOP] : sy1);
int ey1 = sy1 + height;
- int ey2 = (slant[AFTER_START] ? ey1 - bw[AFTER] + clipw[AFTER] : ey1);
- int outerx = startx - clipw[START];
- int clipx = outerx + clipw[START];
- int innerx = outerx + bw[START];
+ int ey2 = (slant[BOTTOM_LEFT] ? ey1 - bw[BOTTOM] + clipw[BOTTOM] : ey1);
+ int outerx = startx - clipw[LEFT];
+ int clipx = outerx + clipw[LEFT];
+ int innerx = outerx + bw[LEFT];
saveGraphicsState();
@@ -238,12 +238,12 @@ public abstract class BorderPainter {
int sy1a = sy1;
int ey1a = ey1;
- if (bpsStart.mode == BorderProps.COLLAPSE_OUTER) {
- if (bpsBefore != null && bpsBefore.mode == BorderProps.COLLAPSE_OUTER) {
- sy1a -= clipw[BEFORE];
+ if (bpsLeft.mode == BorderProps.COLLAPSE_OUTER) {
+ if (bpsTop != null && bpsTop.mode == BorderProps.COLLAPSE_OUTER) {
+ sy1a -= clipw[TOP];
}
- if (bpsAfter != null && bpsAfter.mode == BorderProps.COLLAPSE_OUTER) {
- ey1a += clipw[AFTER];
+ if (bpsBottom != null && bpsBottom.mode == BorderProps.COLLAPSE_OUTER) {
+ ey1a += clipw[BOTTOM];
}
lineTo(outerx, ey1a);
lineTo(outerx, sy1a);
@@ -253,7 +253,7 @@ public abstract class BorderPainter {
lineTo(innerx, ey2);
closePath();
clip();
- drawBorderLine(outerx, sy1a, innerx, ey1a, false, true, bpsStart.style, bpsStart.color);
+ drawBorderLine(outerx, sy1a, innerx, ey1a, false, true, bpsLeft.style, bpsLeft.color);
restoreGraphicsState();
}
}
@@ -278,14 +278,14 @@ public abstract class BorderPainter {
boolean[] b = new boolean[] {
(bpsBefore != null), (bpsEnd != null),
(bpsAfter != null), (bpsStart != null)};
- if (!b[BEFORE] && !b[END] && !b[AFTER] && !b[START]) {
+ if (!b[TOP] && !b[RIGHT] && !b[BOTTOM] && !b[LEFT]) {
return;
}
int[] bw = new int[] {
- (b[BEFORE] ? bpsBefore.width : 0),
- (b[END] ? bpsEnd.width : 0),
- (b[AFTER] ? bpsAfter.width : 0),
- (b[START] ? bpsStart.width : 0)};
+ (b[TOP] ? bpsBefore.width : 0),
+ (b[RIGHT] ? bpsEnd.width : 0),
+ (b[BOTTOM] ? bpsAfter.width : 0),
+ (b[LEFT] ? bpsStart.width : 0)};
int[] clipw = new int[] {
BorderProps.getClippedWidth(bpsBefore),
@@ -293,26 +293,26 @@ public abstract class BorderPainter {
BorderProps.getClippedWidth(bpsAfter),
BorderProps.getClippedWidth(bpsStart)};
- final int startx = borderRect.x + clipw[START];
- final int starty = borderRect.y + clipw[BEFORE];
- final int width = borderRect.width - clipw[START] - clipw[END];
- final int height = borderRect.height - clipw[BEFORE] - clipw[AFTER];
+ final int startx = borderRect.x + clipw[LEFT];
+ final int starty = borderRect.y + clipw[TOP];
+ final int width = borderRect.width - clipw[LEFT] - clipw[RIGHT];
+ final int height = borderRect.height - clipw[TOP] - clipw[BOTTOM];
boolean[] slant = new boolean[] {
- (b[START] && b[BEFORE]), (b[BEFORE] && b[END]),
- (b[END] && b[AFTER]), (b[START] && b[AFTER])};
+ (b[LEFT] && b[TOP]), (b[TOP] && b[RIGHT]),
+ (b[RIGHT] && b[BOTTOM]), (b[LEFT] && b[BOTTOM])};
//Determine scale factor if any adjacent elliptic corners overlap
double esf = cornerScaleFactor(width, height, bpsBefore, bpsAfter, bpsStart, bpsEnd);
if (bpsBefore != null) {
//Let x increase in the START->END direction
- final int sx2 = (slant[BEFORE_START] ? bw[START] - clipw[START] : 0);
+ final int sx2 = (slant[TOP_LEFT] ? bw[LEFT] - clipw[LEFT] : 0);
final int ex1 = width;
- final int ex2 = (slant[BEFORE_END] ? ex1 - bw[END] + clipw[END] : ex1);
- final int outery = -clipw[BEFORE];
- final int innery = outery + bw[BEFORE];
- final int clipy = outery + clipw[BEFORE];
+ final int ex2 = (slant[TOP_RIGHT] ? ex1 - bw[RIGHT] + clipw[RIGHT] : ex1);
+ final int outery = -clipw[TOP];
+ final int innery = outery + bw[TOP];
+ final int clipy = outery + clipw[TOP];
final int ellipseSBW = bpsStart == null ? 0 : (int)(esf * bpsStart.getRadiusStart());
final int ellipseSBH = (int)(esf * bpsBefore.getRadiusStart());
final int ellipseSBX = ellipseSBW;
@@ -325,7 +325,7 @@ public abstract class BorderPainter {
saveGraphicsState();
translateCoordinates(startx, starty);
drawBorderSegment( sx2, ex1, ex2, outery, innery,
- clipw[START], clipw[END],
+ clipw[LEFT], clipw[RIGHT],
ellipseSBX, ellipseSBY, ellipseSBW, ellipseSBH,
ellipseBEX, ellipseBEY, ellipseBEW, ellipseBEH,
bpsBefore, bpsStart, bpsEnd
@@ -335,12 +335,12 @@ public abstract class BorderPainter {
if (bpsStart != null) {
//Let x increase in the AFTER->BEFORE direction
- final int sx2 = (slant[AFTER_START] ? bw[AFTER] - clipw[AFTER] : 0);
+ final int sx2 = (slant[BOTTOM_LEFT] ? bw[BOTTOM] - clipw[BOTTOM] : 0);
final int ex1 = height;
- final int ex2 = (slant[BEFORE_START] ? ex1 - bw[BEFORE] + clipw[BEFORE] : ex1);
- final int outery = -clipw[START];
- final int innery = outery + bw[START];
- final int clipy = outery + clipw[START];
+ final int ex2 = (slant[TOP_LEFT] ? ex1 - bw[TOP] + clipw[TOP] : ex1);
+ final int outery = -clipw[LEFT];
+ final int innery = outery + bw[LEFT];
+ final int clipy = outery + clipw[LEFT];
final int ellipseSBW = bpsAfter == null ? 0 : (int)(esf * bpsAfter.getRadiusStart());
final int ellipseSBH = (int)(esf * bpsStart.getRadiusEnd());
final int ellipseSBX = ellipseSBW;
@@ -354,7 +354,7 @@ public abstract class BorderPainter {
translateCoordinates(startx, starty + height);
rotateCoordinates(Math.PI * 3d / 2d);
drawBorderSegment( sx2, ex1, ex2, outery, innery,
- clipw[AFTER], clipw[BEFORE],
+ clipw[BOTTOM], clipw[TOP],
ellipseSBX, ellipseSBY, ellipseSBW, ellipseSBH,
ellipseBEX, ellipseBEY, ellipseBEW, ellipseBEH,
bpsStart, bpsAfter, bpsBefore
@@ -366,12 +366,12 @@ public abstract class BorderPainter {
if (bpsAfter != null) {
//Let x increase in the START->END direction
- final int sx2 = (slant[AFTER_START] ? bw[START] - clipw[START] : 0);
+ final int sx2 = (slant[BOTTOM_LEFT] ? bw[LEFT] - clipw[LEFT] : 0);
final int ex1 = width;
- final int ex2 = (slant[AFTER_END] ? ex1 - bw[END] + clipw[END] : ex1);
- final int outery = -clipw[AFTER];
- final int innery = outery + bw[AFTER];
- final int clipy = outery + clipw[AFTER];
+ final int ex2 = (slant[BOTTOM_RIGHT] ? ex1 - bw[RIGHT] + clipw[RIGHT] : ex1);
+ final int outery = -clipw[BOTTOM];
+ final int innery = outery + bw[BOTTOM];
+ final int clipy = outery + clipw[BOTTOM];
final int ellipseSBW = bpsStart == null ? 0 : (int)(esf * bpsStart.getRadiusEnd());
final int ellipseSBH = (int)(esf * bpsAfter.getRadiusStart());
final int ellipseSBX = ellipseSBW;
@@ -385,7 +385,7 @@ public abstract class BorderPainter {
translateCoordinates(startx, starty + height);
scaleCoordinates(1, -1);
drawBorderSegment( sx2, ex1, ex2, outery, innery,
- clipw[START], clipw[END],
+ clipw[LEFT], clipw[RIGHT],
ellipseSBX, ellipseSBY, ellipseSBW, ellipseSBH,
ellipseBEX, ellipseBEY, ellipseBEW, ellipseBEH,
bpsAfter, bpsStart, bpsEnd
@@ -395,12 +395,12 @@ public abstract class BorderPainter {
if (bpsEnd != null) {
//Let x increase in the BEFORE-> AFTER direction
- final int sx2 = (slant[BEFORE_END] ? bw[BEFORE] - clipw[BEFORE] : 0);
+ final int sx2 = (slant[TOP_RIGHT] ? bw[TOP] - clipw[TOP] : 0);
final int ex1 = height;
- final int ex2 = (slant[AFTER_END] ? ex1 - bw[AFTER] + clipw[AFTER] : ex1);
- final int outery = -clipw[END];
- final int innery = outery + bw[END];
- final int clipy = outery + clipw[END];
+ final int ex2 = (slant[BOTTOM_RIGHT] ? ex1 - bw[BOTTOM] + clipw[BOTTOM] : ex1);
+ final int outery = -clipw[RIGHT];
+ final int innery = outery + bw[RIGHT];
+ final int clipy = outery + clipw[RIGHT];
final int ellipseSBW = bpsBefore == null ? 0 : (int)(esf * bpsBefore.getRadiusEnd());
final int ellipseSBH = (int)(esf * bpsEnd.getRadiusStart());
final int ellipseSBX = ellipseSBW;
@@ -414,7 +414,7 @@ public abstract class BorderPainter {
translateCoordinates(startx + width, starty);
rotateCoordinates(Math.PI / 2d);
drawBorderSegment( sx2, ex1, ex2, outery, innery,
- clipw[BEFORE], clipw[AFTER],
+ clipw[TOP], clipw[BOTTOM],
ellipseSBX, ellipseSBY, ellipseSBW, ellipseSBH,
ellipseBEX, ellipseBEY, ellipseBEW, ellipseBEH,
bpsEnd, bpsBefore, bpsAfter
diff --git a/src/java/org/apache/fop/render/intermediate/EventProducingFilter.java b/src/java/org/apache/fop/render/intermediate/EventProducingFilter.java
new file mode 100644
index 000000000..36f518d9a
--- /dev/null
+++ b/src/java/org/apache/fop/render/intermediate/EventProducingFilter.java
@@ -0,0 +1,54 @@
+/*
+ * 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 org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.render.RendererEventProducer;
+import org.apache.fop.render.intermediate.util.IFDocumentHandlerProxy;
+
+/**
+ * A filter that uses the Event Notification System to broadcast IF events.
+ *
+ */
+public class EventProducingFilter extends IFDocumentHandlerProxy {
+
+ private int pageNumberEnded;
+
+ private FOUserAgent userAgent;
+
+ /**
+ * Constructor
+ * @param ifDocumentHandler the IFDocumentHandler to filter
+ * @param userAgent the FOUerAgent
+ */
+ public EventProducingFilter(IFDocumentHandler ifDocumentHandler, FOUserAgent userAgent) {
+ super(ifDocumentHandler);
+ this.userAgent = userAgent;
+ }
+
+ @Override
+ public void endPage() throws IFException {
+ super.endPage();
+ pageNumberEnded++;
+ RendererEventProducer.Provider.get(userAgent.getEventBroadcaster())
+ .endPage(this, pageNumberEnded);
+ }
+
+}
diff --git a/src/java/org/apache/fop/render/intermediate/IFConstants.java b/src/java/org/apache/fop/render/intermediate/IFConstants.java
index 34fe2bd2c..c7bf13e31 100644
--- a/src/java/org/apache/fop/render/intermediate/IFConstants.java
+++ b/src/java/org/apache/fop/render/intermediate/IFConstants.java
@@ -39,6 +39,8 @@ public interface IFConstants extends XMLConstants {
String EL_HEADER = "header";
/** element name trailer */
String EL_TRAILER = "trailer";
+ /** element name locale */
+ String EL_LOCALE = "locale";
/** element name page-sequence */
String EL_PAGE_SEQUENCE = "page-sequence";
/** element name page */
@@ -67,6 +69,8 @@ public interface IFConstants extends XMLConstants {
String EL_FONT = "font";
/** element name text */
String EL_TEXT = "text";
+ /** element name id */
+ String EL_ID = "id";
/** Parent element of the logical structure tree. */
String EL_STRUCTURE_TREE = "structure-tree";
}
diff --git a/src/java/org/apache/fop/render/intermediate/IFContext.java b/src/java/org/apache/fop/render/intermediate/IFContext.java
index 804b353c1..681b996e4 100644
--- a/src/java/org/apache/fop/render/intermediate/IFContext.java
+++ b/src/java/org/apache/fop/render/intermediate/IFContext.java
@@ -25,6 +25,7 @@ import java.util.Map;
import org.apache.xmlgraphics.util.QName;
+import org.apache.fop.accessibility.StructureTreeElement;
import org.apache.fop.apps.FOUserAgent;
/**
@@ -46,7 +47,9 @@ public class IFContext {
private Locale language;
- private String structurePointer;
+ private StructureTreeElement structureTreeElement;
+
+ private String id = "";
/**
* Main constructor.
@@ -130,29 +133,50 @@ public class IFContext {
}
/**
- * Sets the structure pointer for the following painted marks. This method is used when
- * accessibility features are enabled.
- * @param ptr the structure pointer
+ * Sets the structure tree element to which the subsequently painted marks
+ * will correspond. This method is used when accessibility features are
+ * enabled.
+ *
+ * @param structureTreeElement the structure tree element
+ */
+ public void setStructureTreeElement(StructureTreeElement structureTreeElement) {
+ this.structureTreeElement = structureTreeElement;
+ }
+
+ /**
+ * Resets the current structure tree element.
+ * @see #setStructureTreeElement(StructureTreeElement)
+ */
+ public void resetStructureTreeElement() {
+ setStructureTreeElement(null);
+ }
+
+ /**
+ * Returns the current structure tree element.
+ * @return the structure tree element (or null if no element is active)
+ * @see #setStructureTreeElement(StructureTreeElement)
*/
- public void setStructurePointer(String ptr) {
- this.structurePointer = ptr;
+ public StructureTreeElement getStructureTreeElement() {
+ return this.structureTreeElement;
}
/**
- * Resets the current structure pointer.
- * @see #setStructurePointer(String)
+ * Sets the ID of the object enclosing the content that will follow.
+ *
+ * @param id the ID of the nearest ancestor object for which the id property was set
*/
- public void resetStructurePointer() {
- setStructurePointer(null);
+ void setID(String id) {
+ assert id != null;
+ this.id = id;
}
/**
- * Returns the current structure pointer.
- * @return the structure pointer (or null if no pointer is active)
- * @see #setStructurePointer(String)
+ * Returns the ID of the object enclosing the current content.
+ *
+ * @return the ID of the nearest ancestor object for which the id property was set
*/
- public String getStructurePointer() {
- return this.structurePointer;
+ String getID() {
+ return id;
}
}
diff --git a/src/java/org/apache/fop/render/intermediate/IFDocumentHandler.java b/src/java/org/apache/fop/render/intermediate/IFDocumentHandler.java
index af1451fe3..6cb8f2795 100644
--- a/src/java/org/apache/fop/render/intermediate/IFDocumentHandler.java
+++ b/src/java/org/apache/fop/render/intermediate/IFDocumentHandler.java
@@ -20,9 +20,11 @@
package org.apache.fop.render.intermediate;
import java.awt.Dimension;
+import java.util.Locale;
import javax.xml.transform.Result;
+import org.apache.fop.accessibility.StructureTreeEventHandler;
import org.apache.fop.fonts.FontInfo;
/**
@@ -32,6 +34,7 @@ import org.apache.fop.fonts.FontInfo;
* <p>
* <pre>
* startDocument()
+ * [setDocumentLocale()]
* startDocumentHeader()
* [handleExtension()]*
* endDocumentHeader()
@@ -118,6 +121,11 @@ public interface IFDocumentHandler {
IFDocumentHandlerConfigurator getConfigurator();
/**
+ * @return the structure tree builder
+ */
+ StructureTreeEventHandler getStructureTreeEventHandler();
+
+ /**
* Returns a document navigation handler if this feature is supported.
* @return the document navigation handler or null if not supported
*/
@@ -152,6 +160,11 @@ public interface IFDocumentHandler {
void endDocument() throws IFException;
/**
+ * @param locale Locale of the document.
+ */
+ void setDocumentLocale(Locale locale);
+
+ /**
* Indicates the start of the document header. This method is called right after the
* {@link #startDocument()} method. Extensions sent to this painter between
* {@link #startDocumentHeader()} and {@link #endDocumentHeader()} apply to the document as
@@ -261,7 +274,4 @@ public interface IFDocumentHandler {
* @throws IFException if an error occurs while handling this event
*/
void handleExtensionObject(Object extension) throws IFException;
-
- //TODO Prototype the following:
- //ContentHandler handleExtension() throws Exception
}
diff --git a/src/java/org/apache/fop/render/intermediate/IFGraphicContext.java b/src/java/org/apache/fop/render/intermediate/IFGraphicContext.java
index 6e431e513..8c3f998a9 100644
--- a/src/java/org/apache/fop/render/intermediate/IFGraphicContext.java
+++ b/src/java/org/apache/fop/render/intermediate/IFGraphicContext.java
@@ -22,7 +22,7 @@ package org.apache.fop.render.intermediate;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
-import java.util.List;
+import java.util.ArrayList;
import org.apache.xmlgraphics.java2d.GraphicContext;
@@ -33,7 +33,7 @@ public class IFGraphicContext extends GraphicContext {
private static final AffineTransform[] EMPTY_TRANSFORM_ARRAY = new AffineTransform[0];
- private List groupList = new java.util.ArrayList();
+ private ArrayList groupList = new ArrayList();
/**
* Default constructor.
@@ -48,17 +48,20 @@ public class IFGraphicContext extends GraphicContext {
*/
protected IFGraphicContext(IFGraphicContext graphicContext) {
super(graphicContext);
- //We don't clone groupDepth!
+ // N.B. do not perform deep copy on groupList; doing so causes
+ // a junit regression... have not investigated cause... [GA]
+ // groupList = (ArrayList) graphicContext.groupList.clone();
}
- /** {@inheritDoc} */
+ /**
+ * {@inheritDoc}
+ */
public Object clone() {
- return new IFGraphicContext(this);
+ return new IFGraphicContext ( this );
}
/** @param group a group */
public void pushGroup(Group group) {
- //this.groupDepth++;
this.groupList.add(group);
for (int i = 0, c = group.getTransforms().length; i < c; i++) {
transform(group.getTransforms()[i]);
diff --git a/src/java/org/apache/fop/render/intermediate/IFPainter.java b/src/java/org/apache/fop/render/intermediate/IFPainter.java
index 8d92d1ca9..5d2beb65c 100644
--- a/src/java/org/apache/fop/render/intermediate/IFPainter.java
+++ b/src/java/org/apache/fop/render/intermediate/IFPainter.java
@@ -151,12 +151,14 @@ public interface IFPainter {
* @param y Y-coordinate of the starting point of the text
* @param letterSpacing additional spacing between characters (may be 0)
* @param wordSpacing additional spacing between words (may be 0)
- * @param dx an array of adjustment values for each character in X-direction (may be null)
+ * @param dp an array of 4-tuples, expressing [X,Y] placment
+ * adjustments and [X,Y] advancement adjustments, in that order (may be null); if
+ * not null, then adjustments.length must be the same as text.length()
* @param text the text
* @throws IFException if an error occurs while handling this event
*/
void drawText(int x, int y, int letterSpacing, int wordSpacing,
- int[] dx, String text) throws IFException;
+ int[][] dp, String text) throws IFException;
/**
* Restricts the current clipping region with the given rectangle.
@@ -206,16 +208,16 @@ public interface IFPainter {
* Draws a border rectangle. The border segments are specified through {@link BorderProps}
* instances.
* @param rect the rectangle's coordinates and extent
- * @param before the border segment on the before-side (top)
- * @param after the border segment on the after-side (bottom)
- * @param start the border segment on the start-side (left)
- * @param end the border segment on the end-side (right)
+ * @param top the border segment on the top edge
+ * @param bottom the border segment on the bottom edge
+ * @param left the border segment on the left edge
+ * @param right the border segment on the right edge
* @param innerBackgroundColor the color of the inner background
* @throws IFException if an error occurs while handling this event
*/
void drawBorderRect(Rectangle rect,
- BorderProps before, BorderProps after,
- BorderProps start, BorderProps end, Color innerBackgroundColor) throws IFException;
+ BorderProps top, BorderProps bottom,
+ BorderProps left, BorderProps right, Color innerBackgroundColor) throws IFException;
/**
* Draws a line. NOTE: Currently, only horizontal lines are implemented!
diff --git a/src/java/org/apache/fop/render/intermediate/IFParser.java b/src/java/org/apache/fop/render/intermediate/IFParser.java
index 0f143018d..293487ac2 100644
--- a/src/java/org/apache/fop/render/intermediate/IFParser.java
+++ b/src/java/org/apache/fop/render/intermediate/IFParser.java
@@ -24,6 +24,8 @@ import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
+import java.util.HashMap;
+import java.util.Locale;
import java.util.Map;
import java.util.Set;
@@ -47,11 +49,13 @@ import org.apache.commons.logging.LogFactory;
import org.apache.xmlgraphics.util.QName;
import org.apache.fop.accessibility.AccessibilityEventProducer;
-import org.apache.fop.accessibility.StructureTreeBuilder;
+import org.apache.fop.accessibility.StructureTreeElement;
+import org.apache.fop.accessibility.StructureTreeEventHandler;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.fo.ElementMapping;
import org.apache.fop.fo.ElementMappingRegistry;
import org.apache.fop.fo.expr.PropertyException;
+import org.apache.fop.fo.extensions.InternalElementMapping;
import org.apache.fop.render.intermediate.extensions.DocumentNavigationExtensionConstants;
import org.apache.fop.render.intermediate.extensions.DocumentNavigationHandler;
import org.apache.fop.traits.BorderProps;
@@ -61,7 +65,7 @@ import org.apache.fop.util.ContentHandlerFactory;
import org.apache.fop.util.ContentHandlerFactoryRegistry;
import org.apache.fop.util.DOMBuilderContentHandlerFactory;
import org.apache.fop.util.DefaultErrorListener;
-import org.apache.fop.util.DelegatingContentHandler;
+import org.apache.fop.util.LanguageTags;
import org.apache.fop.util.XMLUtil;
/**
@@ -71,12 +75,12 @@ import org.apache.fop.util.XMLUtil;
public class IFParser implements IFConstants {
/** Logger instance */
- protected static Log log = LogFactory.getLog(IFParser.class);
+ protected static final Log log = LogFactory.getLog(IFParser.class);
private static SAXTransformerFactory tFactory
= (SAXTransformerFactory)SAXTransformerFactory.newInstance();
- private static Set handledNamespaces = new java.util.HashSet();
+ private static Set<String> handledNamespaces = new java.util.HashSet<String>();
static {
handledNamespaces.add(XMLNS_NAMESPACE_URI);
@@ -132,7 +136,7 @@ public class IFParser implements IFConstants {
private static class Handler extends DefaultHandler {
- private Map elementHandlers = new java.util.HashMap();
+ private Map<String, ElementHandler> elementHandlers = new HashMap<String, ElementHandler>();
private IFDocumentHandler documentHandler;
private IFPainter painter;
@@ -152,24 +156,65 @@ public class IFParser implements IFConstants {
private ContentHandler navParser;
- private StructureTreeBuilder structureTreeBuilder;
-
- private ContentHandler structureTreeBuilderWrapper;
+ private StructureTreeHandler structureTreeHandler;
private Attributes pageSequenceAttributes;
- private final class StructureTreeBuilderWrapper extends DelegatingContentHandler {
+ private Map<String, StructureTreeElement> structureTreeElements
+ = new HashMap<String, StructureTreeElement>();
- private StructureTreeBuilderWrapper()
- throws SAXException {
- super(structureTreeBuilder.getHandlerForNextPageSequence());
+ private final class StructureTreeHandler extends DefaultHandler {
+
+ private final Locale pageSequenceLanguage;
+
+ private final StructureTreeEventHandler structureTreeEventHandler;
+
+ private StructureTreeHandler(StructureTreeEventHandler structureTreeEventHandler,
+ Locale pageSequenceLanguage) throws SAXException {
+ this.pageSequenceLanguage = pageSequenceLanguage;
+ this.structureTreeEventHandler = structureTreeEventHandler;
+ }
+
+ void startStructureTree(String type) {
+ structureTreeEventHandler.startPageSequence(pageSequenceLanguage, type);
}
public void endDocument() throws SAXException {
- super.endDocument();
startIFElement(EL_PAGE_SEQUENCE, pageSequenceAttributes);
pageSequenceAttributes = null;
}
+
+ @Override
+ public void startElement(String uri, String localName, String qName,
+ Attributes attributes) throws SAXException {
+ if (!"structure-tree".equals(localName)) {
+ if (localName.equals("marked-content")) {
+ localName = "#PCDATA";
+ }
+ String structID = attributes.getValue(InternalElementMapping.URI,
+ InternalElementMapping.STRUCT_ID);
+ if (structID == null) {
+ structureTreeEventHandler.startNode(localName, attributes);
+ } else if (localName.equals("external-graphic")
+ || localName.equals("instream-foreign-object")) {
+ StructureTreeElement structureTreeElement
+ = structureTreeEventHandler.startImageNode(localName, attributes);
+ structureTreeElements.put(structID, structureTreeElement);
+ } else {
+ StructureTreeElement structureTreeElement = structureTreeEventHandler
+ .startReferencedNode(localName, attributes);
+ structureTreeElements.put(structID, structureTreeElement);
+ }
+ }
+ }
+
+ @Override
+ public void endElement(String uri, String localName, String arqNameg2)
+ throws SAXException {
+ if (!"structure-tree".equals(localName)) {
+ structureTreeEventHandler.endNode(localName);
+ }
+ }
}
public Handler(IFDocumentHandler documentHandler, FOUserAgent userAgent,
@@ -179,6 +224,7 @@ public class IFParser implements IFConstants {
this.elementMappingRegistry = elementMappingRegistry;
elementHandlers.put(EL_DOCUMENT, new DocumentHandler());
elementHandlers.put(EL_HEADER, new DocumentHeaderHandler());
+ elementHandlers.put(EL_LOCALE, new LocaleHandler());
elementHandlers.put(EL_TRAILER, new DocumentTrailerHandler());
elementHandlers.put(EL_PAGE_SEQUENCE, new PageSequenceHandler());
elementHandlers.put(EL_PAGE, new PageHandler());
@@ -188,6 +234,7 @@ public class IFParser implements IFConstants {
//Page content
elementHandlers.put(EL_VIEWPORT, new ViewportHandler());
elementHandlers.put(EL_GROUP, new GroupHandler());
+ elementHandlers.put(EL_ID, new IDHandler());
elementHandlers.put(EL_FONT, new FontHandler());
elementHandlers.put(EL_TEXT, new TextHandler());
elementHandlers.put(EL_CLIP_RECT, new ClipRectHandler());
@@ -195,14 +242,9 @@ public class IFParser implements IFConstants {
elementHandlers.put(EL_LINE, new LineHandler());
elementHandlers.put(EL_BORDER_RECT, new BorderRectHandler());
elementHandlers.put(EL_IMAGE, new ImageHandler());
-
- if (userAgent.isAccessibilityEnabled()) {
- structureTreeBuilder = new StructureTreeBuilder(tFactory);
- userAgent.setStructureTree(structureTreeBuilder.getStructureTree());
- }
}
- private void establishForeignAttributes(Map foreignAttributes) {
+ private void establishForeignAttributes(Map<QName, String> foreignAttributes) {
documentHandler.getContext().setForeignAttributes(foreignAttributes);
}
@@ -210,14 +252,6 @@ public class IFParser implements IFConstants {
documentHandler.getContext().resetForeignAttributes();
}
- private void establishStructurePointer(String ptr) {
- documentHandler.getContext().setStructurePointer(ptr);
- }
-
- private void resetStructurePointer() {
- documentHandler.getContext().resetStructurePointer();
- }
-
/** {@inheritDoc} */
public void startElement(String uri, String localName, String qName, Attributes attributes)
throws SAXException {
@@ -229,10 +263,15 @@ public class IFParser implements IFConstants {
if (NAMESPACE.equals(uri)) {
if (localName.equals(EL_PAGE_SEQUENCE) && userAgent.isAccessibilityEnabled()) {
pageSequenceAttributes = new AttributesImpl(attributes);
- structureTreeBuilderWrapper = new StructureTreeBuilderWrapper();
+ Locale language = getLanguage(attributes);
+ structureTreeHandler = new StructureTreeHandler(
+ userAgent.getStructureTreeEventHandler(), language);
+
} else if (localName.equals(EL_STRUCTURE_TREE)) {
if (userAgent.isAccessibilityEnabled()) {
- delegate = structureTreeBuilderWrapper;
+ String type = attributes.getValue("type");
+ structureTreeHandler.startStructureTree(type);
+ delegate = structureTreeHandler;
} else {
/* Delegate to a handler that does nothing */
delegate = new DefaultHandler();
@@ -258,7 +297,8 @@ public class IFParser implements IFConstants {
} else if (DocumentNavigationExtensionConstants.NAMESPACE.equals(uri)) {
if (this.navParser == null) {
this.navParser = new DocumentNavigationHandler(
- this.documentHandler.getDocumentNavigationHandler());
+ this.documentHandler.getDocumentNavigationHandler(),
+ structureTreeElements);
}
delegate = this.navParser;
delegateDepth++;
@@ -297,10 +337,15 @@ public class IFParser implements IFConstants {
}
}
+ private static Locale getLanguage(Attributes attributes) {
+ String xmllang = attributes.getValue(XML_NAMESPACE, "lang");
+ return (xmllang == null) ? null : LanguageTags.toLocale(xmllang);
+ }
+
private boolean startIFElement(String localName, Attributes attributes)
throws SAXException {
lastAttributes = new AttributesImpl(attributes);
- ElementHandler elementHandler = (ElementHandler)elementHandlers.get(localName);
+ ElementHandler elementHandler = elementHandlers.get(localName);
content.setLength(0);
ignoreCharacters = true;
if (elementHandler != null) {
@@ -346,7 +391,7 @@ public class IFParser implements IFConstants {
}
} else {
if (NAMESPACE.equals(uri)) {
- ElementHandler elementHandler = (ElementHandler)elementHandlers.get(localName);
+ ElementHandler elementHandler = elementHandlers.get(localName);
if (elementHandler != null) {
try {
elementHandler.endElement();
@@ -366,7 +411,7 @@ public class IFParser implements IFConstants {
// ============== Element handlers for the intermediate format =============
- private static interface ElementHandler {
+ private interface ElementHandler {
void startElement(Attributes attributes) throws IFException, SAXException;
void endElement() throws IFException;
boolean ignoreCharacters();
@@ -411,6 +456,12 @@ public class IFParser implements IFConstants {
}
+ private class LocaleHandler extends AbstractElementHandler {
+ public void startElement(Attributes attributes) throws IFException {
+ documentHandler.setDocumentLocale(getLanguage(attributes));
+ }
+ }
+
private class DocumentTrailerHandler extends AbstractElementHandler {
public void startElement(Attributes attributes) throws IFException {
@@ -427,12 +478,11 @@ public class IFParser implements IFConstants {
public void startElement(Attributes attributes) throws IFException {
String id = attributes.getValue("id");
- String xmllang = attributes.getValue(XML_NAMESPACE, "lang");
- if (xmllang != null) {
- documentHandler.getContext().setLanguage(
- XMLUtil.convertRFC3066ToLocale(xmllang));
+ Locale language = getLanguage(attributes);
+ if (language != null) {
+ documentHandler.getContext().setLanguage(language);
}
- Map foreignAttributes = getForeignAttributes(lastAttributes);
+ Map<QName, String> foreignAttributes = getForeignAttributes(lastAttributes);
establishForeignAttributes(foreignAttributes);
documentHandler.startPageSequence(id);
resetForeignAttributes();
@@ -453,7 +503,7 @@ public class IFParser implements IFConstants {
String pageMasterName = attributes.getValue("page-master-name");
int width = Integer.parseInt(attributes.getValue("width"));
int height = Integer.parseInt(attributes.getValue("height"));
- Map foreignAttributes = getForeignAttributes(lastAttributes);
+ Map<QName, String> foreignAttributes = getForeignAttributes(lastAttributes);
establishForeignAttributes(foreignAttributes);
documentHandler.startPage(index, name, pageMasterName,
new Dimension(width, height));
@@ -486,6 +536,7 @@ public class IFParser implements IFConstants {
public void endElement() throws IFException {
painter = null;
+ documentHandler.getContext().setID("");
documentHandler.endPageContent();
}
@@ -536,6 +587,16 @@ public class IFParser implements IFConstants {
}
+ private class IDHandler extends AbstractElementHandler {
+
+ @Override
+ public void startElement(Attributes attributes) throws IFException, SAXException {
+ String id = attributes.getValue("name");
+ documentHandler.getContext().setID(id);
+ }
+
+ }
+
private class FontHandler extends AbstractElementHandler {
public void startElement(Attributes attributes) throws IFException {
@@ -565,9 +626,15 @@ public class IFParser implements IFConstants {
s = lastAttributes.getValue("word-spacing");
int wordSpacing = (s != null ? Integer.parseInt(s) : 0);
int[] dx = XMLUtil.getAttributeAsIntArray(lastAttributes, "dx");
- setStructurePointer(lastAttributes);
- painter.drawText(x, y, letterSpacing, wordSpacing, dx, content.toString());
- resetStructurePointer();
+ int[][] dp = XMLUtil.getAttributeAsPositionAdjustments(lastAttributes, "dp");
+ // if only DX present, then convert DX to DP; otherwise use only DP,
+ // effectively ignoring DX
+ if ( ( dp == null ) && ( dx != null ) ) {
+ dp = IFUtil.convertDXToDP ( dx );
+ }
+ establishStructureTreeElement(lastAttributes);
+ painter.drawText(x, y, letterSpacing, wordSpacing, dp, content.toString());
+ resetStructureTreeElement();
}
public boolean ignoreCharacters() {
@@ -658,7 +725,7 @@ public class IFParser implements IFConstants {
}
- private static final String[] SIDES = new String[] {"before", "after", "start", "end"};
+ private static final String[] SIDES = new String[] {"top", "bottom", "left", "right"};
private class BorderRectHandler extends AbstractElementHandler {
@@ -699,9 +766,9 @@ public class IFParser implements IFConstants {
int y = Integer.parseInt(lastAttributes.getValue("y"));
int width = Integer.parseInt(lastAttributes.getValue("width"));
int height = Integer.parseInt(lastAttributes.getValue("height"));
- Map foreignAttributes = getForeignAttributes(lastAttributes);
+ Map<QName, String> foreignAttributes = getForeignAttributes(lastAttributes);
establishForeignAttributes(foreignAttributes);
- setStructurePointer(lastAttributes);
+ establishStructureTreeElement(lastAttributes);
if (foreignObject != null) {
painter.drawImage(foreignObject,
new Rectangle(x, y, width, height));
@@ -715,7 +782,7 @@ public class IFParser implements IFConstants {
painter.drawImage(uri, new Rectangle(x, y, width, height));
}
resetForeignAttributes();
- resetStructurePointer();
+ resetStructureTreeElement();
inForeignObject = false;
}
@@ -751,8 +818,8 @@ public class IFParser implements IFConstants {
}
}
- private static Map getForeignAttributes(Attributes atts) {
- Map foreignAttributes = null;
+ private static Map<QName, String> getForeignAttributes(Attributes atts) {
+ Map<QName, String> foreignAttributes = null;
for (int i = 0, c = atts.getLength(); i < c; i++) {
String ns = atts.getURI(i);
if (ns.length() > 0) {
@@ -760,7 +827,7 @@ public class IFParser implements IFConstants {
continue;
}
if (foreignAttributes == null) {
- foreignAttributes = new java.util.HashMap();
+ foreignAttributes = new java.util.HashMap<QName, String>();
}
QName qname = new QName(ns, atts.getQName(i));
foreignAttributes.put(qname, atts.getValue(i));
@@ -769,13 +836,20 @@ public class IFParser implements IFConstants {
return foreignAttributes;
}
- private void setStructurePointer(Attributes attributes) {
- String ptr = attributes.getValue("ptr");
- if (ptr != null && ptr.length() > 0) {
- establishStructurePointer(ptr);
+ private void establishStructureTreeElement(Attributes attributes) {
+ String structRef = attributes.getValue(InternalElementMapping.URI,
+ InternalElementMapping.STRUCT_REF);
+ if (structRef != null && structRef.length() > 0) {
+ assert structureTreeElements.containsKey(structRef);
+ StructureTreeElement structureTreeElement = structureTreeElements.get(structRef);
+ documentHandler.getContext().setStructureTreeElement(structureTreeElement);
}
}
+ private void resetStructureTreeElement() {
+ documentHandler.getContext().resetStructureTreeElement();
+ }
+
/** {@inheritDoc} */
public void characters(char[] ch, int start, int length) throws SAXException {
if (delegate != null) {
diff --git a/src/java/org/apache/fop/render/intermediate/IFRenderer.java b/src/java/org/apache/fop/render/intermediate/IFRenderer.java
index 1d20da519..45b0c3a93 100644
--- a/src/java/org/apache/fop/render/intermediate/IFRenderer.java
+++ b/src/java/org/apache/fop/render/intermediate/IFRenderer.java
@@ -37,7 +37,6 @@ import java.util.Stack;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
-
import org.xml.sax.SAXException;
import org.apache.batik.parser.AWTTransformProducer;
@@ -51,7 +50,9 @@ import org.apache.xmlgraphics.xmp.schemas.XMPBasicAdapter;
import org.apache.xmlgraphics.xmp.schemas.XMPBasicSchema;
import org.apache.fop.Version;
+import org.apache.fop.accessibility.StructureTreeElement;
import org.apache.fop.apps.FOPException;
+import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.MimeConstants;
import org.apache.fop.area.Area;
import org.apache.fop.area.AreaTreeObject;
@@ -71,10 +72,10 @@ import org.apache.fop.area.inline.ForeignObject;
import org.apache.fop.area.inline.Image;
import org.apache.fop.area.inline.InlineArea;
import org.apache.fop.area.inline.InlineParent;
+import org.apache.fop.area.inline.InlineViewport;
import org.apache.fop.area.inline.Leader;
import org.apache.fop.area.inline.SpaceArea;
import org.apache.fop.area.inline.TextArea;
-import org.apache.fop.area.inline.Viewport;
import org.apache.fop.area.inline.WordArea;
import org.apache.fop.datatypes.URISpecification;
import org.apache.fop.fo.extensions.ExtensionAttachment;
@@ -110,7 +111,7 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
//if optimizations can be done to avoid int->float->int conversions.
/** logging instance */
- protected static Log log = LogFactory.getLog(IFRenderer.class);
+ protected static final Log log = LogFactory.getLog(IFRenderer.class);
/** XML MIME type */
public static final String IF_MIME_TYPE = MimeConstants.MIME_FOP_IF;
@@ -154,10 +155,15 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
private TextUtil textUtil = new TextUtil();
+ private Stack<String> ids = new Stack<String>();
+
/**
* Main constructor
+ *
+ * @param userAgent the user agent that contains configuration details. This cannot be null.
*/
- public IFRenderer() {
+ public IFRenderer(FOUserAgent userAgent) {
+ super(userAgent);
}
/** {@inheritDoc} */
@@ -226,7 +232,11 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
*/
protected IFDocumentHandler createDefaultDocumentHandler() {
IFSerializer serializer = new IFSerializer();
- serializer.setContext(new IFContext(getUserAgent()));
+ FOUserAgent userAgent = getUserAgent();
+ serializer.setContext(new IFContext(userAgent));
+ if (userAgent.isAccessibilityEnabled()) {
+ userAgent.setStructureTreeEventHandler(serializer.getStructureTreeEventHandler());
+ }
return serializer;
}
@@ -293,6 +303,11 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
log.debug("Rendering finished.");
}
+ @Override
+ public void setDocumentLocale(Locale locale) {
+ documentHandler.setDocumentLocale(locale);
+ }
+
/** {@inheritDoc} */
public void processOffDocumentItem(OffDocumentItem odi) {
if (odi instanceof DestinationData) {
@@ -473,7 +488,8 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
if (hasDocumentNavigation() && id != null) {
int extraMarginBefore = 5000; // millipoints
int ipp = currentIPPosition;
- int bpp = currentBPPosition + inlineArea.getOffset() - extraMarginBefore;
+ int bpp = currentBPPosition
+ + inlineArea.getBlockProgressionOffset() - extraMarginBefore;
saveAbsolutePosition(id, ipp, bpp);
}
}
@@ -618,12 +634,12 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
documentHandler.getContext().resetForeignAttributes();
}
- private void establishStructurePointer(String ptr) {
- documentHandler.getContext().setStructurePointer(ptr);
+ private void establishStructureTreeElement(StructureTreeElement structureTreeElement) {
+ documentHandler.getContext().setStructureTreeElement(structureTreeElement);
}
private void resetStructurePointer() {
- documentHandler.getContext().resetStructurePointer();
+ documentHandler.getContext().resetStructureTreeElement();
}
/** {@inheritDoc} */
@@ -788,18 +804,11 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
contentRectTransform.translate(borderPaddingStart, borderPaddingBefore);
concatenateTransformationMatrixMpt(contentRectTransform, false);
- //Clipping
- Rectangle clipRect = null;
- if (bv.getClip()) {
- clipRect = new Rectangle(0, 0, dim.width, dim.height);
- //clipRect(0f, 0f, width, height);
- }
-
//saveGraphicsState();
//Set up coordinate system for content rectangle
AffineTransform contentTransform = ctm.toAffineTransform();
//concatenateTransformationMatrixMpt(contentTransform);
- startViewport(contentTransform, clipRect);
+ startViewport(contentTransform, bv.getClipRectangle());
currentIPPosition = 0;
currentBPPosition = 0;
@@ -831,13 +840,7 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
//Now adjust for border/padding
currentBPPosition += borderPaddingBefore;
- Rectangle2D clippingRect = null;
- if (bv.getClip()) {
- clippingRect = new Rectangle(currentIPPosition, currentBPPosition,
- bv.getIPD(), bv.getBPD());
- }
-
- startVParea(ctm, clippingRect);
+ startVParea(ctm, bv.getClipRectangle());
currentIPPosition = 0;
currentBPPosition = 0;
renderBlocks(bv, children);
@@ -852,30 +855,26 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
}
/** {@inheritDoc} */
- public void renderViewport(Viewport viewport) {
- String ptr = (String) viewport.getTrait(Trait.PTR);
- establishStructurePointer(ptr);
+ public void renderInlineViewport(InlineViewport viewport) {
+ StructureTreeElement structElem
+ = (StructureTreeElement) viewport.getTrait(Trait.STRUCTURE_TREE_ELEMENT);
+ establishStructureTreeElement(structElem);
+ pushdID(viewport);
Dimension dim = new Dimension(viewport.getIPD(), viewport.getBPD());
viewportDimensionStack.push(dim);
- super.renderViewport(viewport);
+ super.renderInlineViewport(viewport);
viewportDimensionStack.pop();
resetStructurePointer();
+ popID(viewport);
}
/** {@inheritDoc} */
- protected void startVParea(CTM ctm, Rectangle2D clippingRect) {
+ protected void startVParea(CTM ctm, Rectangle clippingRect) {
if (log.isTraceEnabled()) {
log.trace("startVParea() ctm=" + ctm + ", clippingRect=" + clippingRect);
}
AffineTransform at = new AffineTransform(ctm.toArray());
- Rectangle clipRect = null;
- if (clippingRect != null) {
- clipRect = new Rectangle(
- (int)clippingRect.getMinX() - currentIPPosition,
- (int)clippingRect.getMinY() - currentBPPosition,
- (int)clippingRect.getWidth(), (int)clippingRect.getHeight());
- }
- startViewport(at, clipRect);
+ startViewport(at, clippingRect);
if (log.isTraceEnabled()) {
log.trace("startVPArea: " + at + " --> " + graphicContext.getTransform());
}
@@ -909,7 +908,9 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
/** {@inheritDoc} */
protected void renderInlineArea(InlineArea inlineArea) {
saveInlinePosIfTargetable(inlineArea);
+ pushdID(inlineArea);
super.renderInlineArea(inlineArea);
+ popID(inlineArea);
}
/** {@inheritDoc} */
@@ -917,10 +918,9 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
// stuff we only need if a link must be created:
Rectangle ipRect = null;
AbstractAction action = null;
- String ptr = (String) ip.getTrait(Trait.PTR); // used for accessibility
// make sure the rect is determined *before* calling super!
int ipp = currentIPPosition;
- int bpp = currentBPPosition + ip.getOffset();
+ int bpp = currentBPPosition + ip.getBlockProgressionOffset();
ipRect = new Rectangle(ipp, bpp, ip.getIPD(), ip.getBPD());
AffineTransform transform = graphicContext.getTransform();
ipRect = transform.createTransformedShape(ipRect).getBounds();
@@ -961,7 +961,9 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
// warn if link trait found but not allowed, else create link
if (linkTraitFound) {
- action.setStructurePointer(ptr); // used for accessibility
+ StructureTreeElement structElem
+ = (StructureTreeElement) ip.getTrait(Trait.STRUCTURE_TREE_ELEMENT);
+ action.setStructureTreeElement(structElem);
Link link = new Link(action, ipRect);
this.deferredLinks.add(link);
}
@@ -973,7 +975,25 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
log.trace("renderBlock() " + block);
}
saveBlockPosIfTargetable(block);
+ pushdID(block);
super.renderBlock(block);
+ popID(block);
+ }
+
+ private void pushdID(Area area) {
+ String prodID = (String) area.getTrait(Trait.PROD_ID);
+ if (prodID != null) {
+ ids.push(prodID);
+ documentHandler.getContext().setID(prodID);
+ }
+ }
+
+ private void popID(Area area) {
+ String prodID = (String) area.getTrait(Trait.PROD_ID);
+ if (prodID != null) {
+ ids.pop();
+ documentHandler.getContext().setID(ids.empty() ? "" : ids.peek());
+ }
}
private Typeface getTypeface(String fontName) {
@@ -996,8 +1016,9 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
String fontName = getInternalFontNameForArea(text);
int size = ((Integer) text.getTrait(Trait.FONT_SIZE)).intValue();
- String ptr = (String)text.getTrait(Trait.PTR); // used for accessibility
- establishStructurePointer(ptr);
+ StructureTreeElement structElem
+ = (StructureTreeElement) text.getTrait(Trait.STRUCTURE_TREE_ELEMENT);
+ establishStructureTreeElement(structElem);
// This assumes that *all* CIDFonts use a /ToUnicode mapping
Typeface tf = getTypeface(fontName);
@@ -1011,7 +1032,7 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
}
int rx = currentIPPosition + text.getBorderAndPaddingWidthStart();
- int bl = currentBPPosition + text.getOffset() + text.getBaselineOffset();
+ int bl = currentBPPosition + text.getBlockProgressionOffset() + text.getBaselineOffset();
textUtil.flush();
textUtil.setStartPosition(rx, bl);
textUtil.setSpacing(text.getTextLetterSpaceAdjust(), text.getTextWordSpaceAdjust());
@@ -1027,7 +1048,12 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
Font font = getFontFromArea(word.getParentArea());
String s = word.getWord();
- renderText(s, word.getLetterAdjustArray(),
+ int[][] dp = word.getGlyphPositionAdjustments();
+ if ( dp == null ) {
+ dp = IFUtil.convertDXToDP ( word.getLetterAdjustArray() );
+ }
+
+ renderText(s, dp, word.isReversed(),
font, (AbstractTextArea)word.getParentArea());
super.renderWord(word);
@@ -1039,7 +1065,7 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
String s = space.getSpace();
AbstractTextArea textArea = (AbstractTextArea)space.getParentArea();
- renderText(s, null, font, textArea);
+ renderText(s, null, false, font, textArea);
if (textUtil.combined && space.isAdjustable()) {
//Used for justified text, for example
@@ -1052,24 +1078,32 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
super.renderSpace(space);
}
+ private void renderText(String s,
+ int[][] dp, boolean reversed,
+ Font font, AbstractTextArea parentArea) {
+ if ( ( dp == null ) || IFUtil.isDPOnlyDX ( dp ) ) {
+ int[] dx = IFUtil.convertDPToDX ( dp );
+ renderTextWithAdjustments ( s, dx, reversed, font, parentArea );
+ } else {
+ renderTextWithAdjustments ( s, dp, reversed, font, parentArea );
+ }
+ }
+
/**
- * Does low-level rendering of text.
+ * Does low-level rendering of text using DX only position adjustments.
* @param s text to render
- * @param letterAdjust an array of widths for letter adjustment (may be null)
+ * @param dx an array of widths for letter adjustment (may be null)
+ * @param reversed if true then text has been reversed (from logical order)
* @param font to font in use
* @param parentArea the parent text area to retrieve certain traits from
*/
- protected void renderText(String s,
- int[] letterAdjust,
- Font font, AbstractTextArea parentArea) {
+ private void renderTextWithAdjustments(String s,
+ int[] dx, boolean reversed,
+ Font font, AbstractTextArea parentArea) {
int l = s.length();
if (l == 0) {
return;
}
-
- if (letterAdjust != null) {
- textUtil.adjust(letterAdjust[0]);
- }
for (int i = 0; i < l; i++) {
char ch = s.charAt(i);
textUtil.addChar(ch);
@@ -1078,46 +1112,84 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
int tls = (i < l - 1 ? parentArea.getTextLetterSpaceAdjust() : 0);
glyphAdjust += tls;
}
- if (letterAdjust != null && i < l - 1) {
- glyphAdjust += letterAdjust[i + 1];
+ if (dx != null && i < l) {
+ glyphAdjust += dx[i];
}
-
textUtil.adjust(glyphAdjust);
}
}
+ /**
+ * Does low-level rendering of text using generalized position adjustments.
+ * @param s text to render
+ * @param dp an array of 4-tuples, expressing [X,Y] placment
+ * adjustments and [X,Y] advancement adjustments, in that order (may be null)
+ * @param reversed if true then text has been reversed (from logical order)
+ * @param font to font in use
+ * @param parentArea the parent text area to retrieve certain traits from
+ */
+ private void renderTextWithAdjustments(String s,
+ int[][] dp, boolean reversed,
+ Font font, AbstractTextArea parentArea) {
+ assert !textUtil.combined;
+ for ( int i = 0, n = s.length(); i < n; i++ ) {
+ textUtil.addChar ( s.charAt ( i ) );
+ if ( dp != null ) {
+ textUtil.adjust ( dp[i] );
+ }
+ }
+ }
+
private class TextUtil {
private static final int INITIAL_BUFFER_SIZE = 16;
- private int[] dx = new int[INITIAL_BUFFER_SIZE];
- private int lastDXPos = 0;
+ private int[][] dp = new int[INITIAL_BUFFER_SIZE][4];
+ // private int lastDPPos = 0; // TBD - not yet used
private final StringBuffer text = new StringBuffer();
- private int startx, starty;
- private int tls, tws;
+ private int startx;
+ private int starty;
+ private int tls;
+ private int tws;
private final boolean combined = false;
void addChar(char ch) {
text.append(ch);
}
- void adjust(int adjust) {
- if (adjust != 0) {
+ void adjust(int dx) {
+ adjust ( new int[] {
+ dx, // xPlaAdjust
+ 0, // yPlaAdjust
+ dx, // xAdvAdjust
+ 0 // yAdvAdjust
+ } );
+ }
+
+ void adjust(int[] pa) {
+ if ( !IFUtil.isPAIdentity ( pa ) ) {
int idx = text.length();
- if (idx > dx.length - 1) {
- int newSize = Math.max(dx.length, idx + 1) + INITIAL_BUFFER_SIZE;
- int[] newDX = new int[newSize];
- System.arraycopy(dx, 0, newDX, 0, dx.length);
- dx = newDX;
+ if (idx > dp.length - 1) {
+ int newSize = Math.max(dp.length, idx + 1) + INITIAL_BUFFER_SIZE;
+ int[][] newDP = new int[newSize][];
+ // reuse prior PA[0]...PA[dp.length-1]
+ System.arraycopy(dp, 0, newDP, 0, dp.length);
+ // populate new PA[dp.length]...PA[newDP.length-1]
+ for ( int i = dp.length, n = newDP.length; i < n; i++ ) {
+ newDP[i] = new int[4];
+ }
+ dp = newDP;
}
- dx[idx] += adjust;
- lastDXPos = idx;
+ IFUtil.adjustPA ( dp[idx - 1], pa );
+ // lastDPPos = idx;
}
}
void reset() {
if (text.length() > 0) {
text.setLength(0);
- Arrays.fill(dx, 0);
- lastDXPos = 0;
+ for ( int i = 0, n = dp.length; i < n; i++ ) {
+ Arrays.fill(dp[i], 0);
+ }
+ // lastDPPos = 0;
}
}
@@ -1134,16 +1206,12 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
void flush() {
if (text.length() > 0) {
try {
- int[] effDX = null;
- if (lastDXPos > 0) {
- int size = lastDXPos + 1;
- effDX = new int[size];
- System.arraycopy(dx, 0, effDX, 0, size);
- }
if (combined) {
- painter.drawText(startx, starty, 0, 0, effDX, text.toString());
+ painter.drawText(startx, starty, 0, 0,
+ trimAdjustments ( dp, text.length() ), text.toString());
} else {
- painter.drawText(startx, starty, tls, tws, effDX, text.toString());
+ painter.drawText(startx, starty, tls, tws,
+ trimAdjustments ( dp, text.length() ), text.toString());
}
} catch (IFException e) {
handleIFException(e);
@@ -1151,6 +1219,38 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
reset();
}
}
+
+ /**
+ * Trim adjustments array <code>dp</code> to be no greater length than
+ * text length, and where trailing all-zero entries are removed.
+ * @param dp a position adjustments array (or null)
+ * @param textLength the length of the associated text
+ * @return either the original value of <code>dp</code> or a copy
+ * of its first N significant adjustment entries, such that N is
+ * no greater than text length, and the last entry has a non-zero
+ * adjustment.
+ */
+ private int[][] trimAdjustments ( int[][] dp, int textLength ) {
+ if ( dp != null ) {
+ int tl = textLength;
+ int pl = dp.length;
+ int i = ( tl < pl ) ? tl : pl;
+ while ( i > 0 ) {
+ int[] pa = dp [ i - 1 ];
+ if ( !IFUtil.isPAIdentity ( pa ) ) {
+ break;
+ } else {
+ i--;
+ }
+ }
+ if ( i == 0 ) {
+ dp = null;
+ } else if ( i < pl ) {
+ dp = IFUtil.copyDP ( dp, 0, i );
+ }
+ }
+ return dp;
+ }
}
/** {@inheritDoc} */
@@ -1200,7 +1300,7 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
int style = area.getRuleStyle();
int ruleThickness = area.getRuleThickness();
int startx = currentIPPosition + area.getBorderAndPaddingWidthStart();
- int starty = currentBPPosition + area.getOffset() + (ruleThickness / 2);
+ int starty = currentBPPosition + area.getBlockProgressionOffset() + (ruleThickness / 2);
int endx = currentIPPosition
+ area.getBorderAndPaddingWidthStart()
+ area.getIPD();
@@ -1268,12 +1368,21 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
float startx, float starty,
float width, float height,
BorderProps bpsBefore, BorderProps bpsAfter,
- BorderProps bpsStart, BorderProps bpsEnd, Color innerBackgroundColor) {
- //TODO lose scale?
+ BorderProps bpsStart, BorderProps bpsEnd, int level, Color innerBackgroundColor) {
Rectangle rect = toMillipointRectangle(startx, starty, width, height);
try {
- painter.drawBorderRect(rect, bpsBefore, bpsAfter, bpsStart, bpsEnd,
- innerBackgroundColor);
+ BorderProps bpsTop = bpsBefore;
+ BorderProps bpsBottom = bpsAfter;
+ BorderProps bpsLeft;
+ BorderProps bpsRight;
+ if ( ( level == -1 ) || ( ( level & 1 ) == 0 ) ) {
+ bpsLeft = bpsStart;
+ bpsRight = bpsEnd;
+ } else {
+ bpsLeft = bpsEnd;
+ bpsRight = bpsStart;
+ }
+ painter.drawBorderRect(rect, bpsTop, bpsBottom, bpsLeft, bpsRight, innerBackgroundColor);
} catch (IFException ife) {
handleIFException(ife);
}
diff --git a/src/java/org/apache/fop/render/intermediate/IFSerializer.java b/src/java/org/apache/fop/render/intermediate/IFSerializer.java
index 4af90faed..4c6781706 100644
--- a/src/java/org/apache/fop/render/intermediate/IFSerializer.java
+++ b/src/java/org/apache/fop/render/intermediate/IFSerializer.java
@@ -31,19 +31,18 @@ import java.util.Locale;
import java.util.Map;
import org.w3c.dom.Document;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
import org.apache.xmlgraphics.util.QName;
import org.apache.xmlgraphics.util.XMLizable;
-import org.apache.fop.accessibility.StructureTree;
+import org.apache.fop.accessibility.StructureTreeEventHandler;
+import org.apache.fop.fo.extensions.InternalElementMapping;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.render.PrintRendererConfigurator;
import org.apache.fop.render.RenderingContext;
+import org.apache.fop.render.intermediate.IFStructureTreeBuilder.IFStructureTreeElement;
import org.apache.fop.render.intermediate.extensions.AbstractAction;
import org.apache.fop.render.intermediate.extensions.Bookmark;
import org.apache.fop.render.intermediate.extensions.BookmarkTree;
@@ -54,28 +53,38 @@ import org.apache.fop.traits.BorderProps;
import org.apache.fop.traits.RuleStyle;
import org.apache.fop.util.ColorUtil;
import org.apache.fop.util.DOM2SAX;
+import org.apache.fop.util.LanguageTags;
import org.apache.fop.util.XMLConstants;
import org.apache.fop.util.XMLUtil;
+
/**
* IFPainter implementation that serializes the intermediate format to XML.
*/
public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
implements IFConstants, IFPainter, IFDocumentNavigationHandler {
+ /**
+ * Intermediate Format (IF) version, used to express an @version attribute
+ * in the root element of the IF document, the initial value of which
+ * is set to '2.0' to signify that something preceded it (but didn't
+ * happen to be marked as such), and that this version is not necessarily
+ * backwards compatible with the unmarked (<2.0) version.
+ */
+ public static final String VERSION = "2.0";
+
private IFDocumentHandler mimicHandler;
private int pageSequenceIndex; // used for accessibility
/** Holds the intermediate format state */
private IFState state;
- /**
- * Default constructor.
- */
- public IFSerializer() {
- }
+ private String currentID = "";
+
+ private IFStructureTreeBuilder structureTreeBuilder;
/** {@inheritDoc} */
+ @Override
protected String getMainNamespace() {
return NAMESPACE;
}
@@ -102,6 +111,7 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
}
/** {@inheritDoc} */
+ @Override
public IFDocumentNavigationHandler getDocumentNavigationHandler() {
return this;
}
@@ -146,7 +156,16 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
}
}
+ @Override
+ public StructureTreeEventHandler getStructureTreeEventHandler() {
+ if (structureTreeBuilder == null) {
+ structureTreeBuilder = new IFStructureTreeBuilder();
+ }
+ return structureTreeBuilder;
+ }
+
/** {@inheritDoc} */
+ @Override
public void startDocument() throws IFException {
super.startDocument();
try {
@@ -155,13 +174,31 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
handler.startPrefixMapping(XLINK_PREFIX, XLINK_NAMESPACE);
handler.startPrefixMapping(DocumentNavigationExtensionConstants.PREFIX,
DocumentNavigationExtensionConstants.NAMESPACE);
- handler.startElement(EL_DOCUMENT);
+ handler.startPrefixMapping(InternalElementMapping.STANDARD_PREFIX,
+ InternalElementMapping.URI);
+ AttributesImpl atts = new AttributesImpl();
+ addAttribute(atts, "version", VERSION);
+ handler.startElement(EL_DOCUMENT, atts);
} catch (SAXException e) {
throw new IFException("SAX error in startDocument()", e);
}
}
+ @Override
+ public void setDocumentLocale(Locale locale) {
+ AttributesImpl atts = new AttributesImpl();
+ atts.addAttribute(XML_NAMESPACE, "lang", "xml:lang", XMLUtil.CDATA,
+ LanguageTags.toLanguageTag(locale));
+ try {
+ handler.startElement(EL_LOCALE, atts);
+ handler.endElement(EL_LOCALE);
+ } catch (SAXException e) {
+ throw new RuntimeException("Unable to create the " + EL_LOCALE + " element.", e);
+ }
+ }
+
/** {@inheritDoc} */
+ @Override
public void startDocumentHeader() throws IFException {
try {
handler.startElement(EL_HEADER);
@@ -171,6 +208,7 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
}
/** {@inheritDoc} */
+ @Override
public void endDocumentHeader() throws IFException {
try {
handler.endElement(EL_HEADER);
@@ -180,6 +218,7 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
}
/** {@inheritDoc} */
+ @Override
public void startDocumentTrailer() throws IFException {
try {
handler.startElement(EL_TRAILER);
@@ -189,6 +228,7 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
}
/** {@inheritDoc} */
+ @Override
public void endDocumentTrailer() throws IFException {
try {
handler.endElement(EL_TRAILER);
@@ -218,20 +258,14 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
Locale lang = getContext().getLanguage();
if (lang != null) {
atts.addAttribute(XML_NAMESPACE, "lang", "xml:lang", XMLUtil.CDATA,
- XMLUtil.toRFC3066(lang));
+ LanguageTags.toLanguageTag(lang));
}
XMLUtil.addAttribute(atts, XMLConstants.XML_SPACE, "preserve");
addForeignAttributes(atts);
handler.startElement(EL_PAGE_SEQUENCE, atts);
if (this.getUserAgent().isAccessibilityEnabled()) {
- StructureTree structureTree = getUserAgent().getStructureTree();
- handler.startElement(EL_STRUCTURE_TREE); // add structure tree
- NodeList nodes = structureTree.getPageSequence(pageSequenceIndex++);
- for (int i = 0, n = nodes.getLength(); i < n; i++) {
- Node node = nodes.item(i);
- new DOM2SAX(handler).writeFragment(node);
- }
- handler.endElement(EL_STRUCTURE_TREE);
+ assert (structureTreeBuilder != null);
+ structureTreeBuilder.replayEventsForPageSequence(handler, pageSequenceIndex++);
}
} catch (SAXException e) {
throw new IFException("SAX error in startPageSequence()", e);
@@ -241,6 +275,7 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
/** {@inheritDoc} */
public void endPageSequence() throws IFException {
try {
+
handler.endElement(EL_PAGE_SEQUENCE);
} catch (SAXException e) {
throw new IFException("SAX error in endPageSequence()", e);
@@ -265,6 +300,7 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
}
/** {@inheritDoc} */
+ @Override
public void startPageHeader() throws IFException {
try {
handler.startElement(EL_PAGE_HEADER);
@@ -274,6 +310,7 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
}
/** {@inheritDoc} */
+ @Override
public void endPageHeader() throws IFException {
try {
handler.endElement(EL_PAGE_HEADER);
@@ -297,6 +334,7 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
public void endPageContent() throws IFException {
try {
this.state = null;
+ currentID = "";
handler.endElement(EL_PAGE_CONTENT);
} catch (SAXException e) {
throw new IFException("SAX error in endPageContent()", e);
@@ -304,6 +342,7 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
}
/** {@inheritDoc} */
+ @Override
public void startPageTrailer() throws IFException {
try {
handler.startElement(EL_PAGE_TRAILER);
@@ -313,6 +352,7 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
}
/** {@inheritDoc} */
+ @Override
public void endPageTrailer() throws IFException {
try {
commitNavigation();
@@ -406,6 +446,7 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
/** {@inheritDoc} */
public void drawImage(String uri, Rectangle rect) throws IFException {
try {
+ addID();
AttributesImpl atts = new AttributesImpl();
addAttribute(atts, XLINK_HREF, uri);
addAttribute(atts, "x", Integer.toString(rect.x));
@@ -413,7 +454,7 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
addAttribute(atts, "width", Integer.toString(rect.width));
addAttribute(atts, "height", Integer.toString(rect.height));
addForeignAttributes(atts);
- addStructurePointerAttribute(atts);
+ addStructureReference(atts);
handler.element(EL_IMAGE, atts);
} catch (SAXException e) {
throw new IFException("SAX error in startGroup()", e);
@@ -434,13 +475,14 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
/** {@inheritDoc} */
public void drawImage(Document doc, Rectangle rect) throws IFException {
try {
+ addID();
AttributesImpl atts = new AttributesImpl();
addAttribute(atts, "x", Integer.toString(rect.x));
addAttribute(atts, "y", Integer.toString(rect.y));
addAttribute(atts, "width", Integer.toString(rect.width));
addAttribute(atts, "height", Integer.toString(rect.height));
addForeignAttributes(atts);
- addStructurePointerAttribute(atts);
+ addStructureReference(atts);
handler.startElement(EL_IMAGE, atts);
new DOM2SAX(handler).writeDocument(doc, true);
handler.endElement(EL_IMAGE);
@@ -550,9 +592,9 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
}
/** {@inheritDoc} */
- public void drawBorderRect(Rectangle rect, BorderProps before, BorderProps after,
- BorderProps start, BorderProps end, Color innerBackgroundColor) throws IFException {
- if (before == null && after == null && start == null && end == null) {
+ public void drawBorderRect(Rectangle rect, BorderProps top, BorderProps bottom,
+ BorderProps left, BorderProps right, Color innerBackgroundColor) throws IFException {
+ if (top == null && bottom == null && left == null && right == null) {
return;
}
try {
@@ -561,17 +603,17 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
addAttribute(atts, "y", Integer.toString(rect.y));
addAttribute(atts, "width", Integer.toString(rect.width));
addAttribute(atts, "height", Integer.toString(rect.height));
- if (before != null) {
- addAttribute(atts, "before", before.toString());
+ if (top != null) {
+ addAttribute(atts, "top", top.toString());
}
- if (after != null) {
- addAttribute(atts, "after", after.toString());
+ if (bottom != null) {
+ addAttribute(atts, "bottom", bottom.toString());
}
- if (start != null) {
- addAttribute(atts, "start", start.toString());
+ if (left != null) {
+ addAttribute(atts, "left", left.toString());
}
- if (end != null) {
- addAttribute(atts, "end", end.toString());
+ if (right != null) {
+ addAttribute(atts, "right", right.toString());
}
if (innerBackgroundColor != null) {
@@ -589,6 +631,7 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
public void drawLine(Point start, Point end, int width, Color color, RuleStyle style)
throws IFException {
try {
+ addID();
AttributesImpl atts = new AttributesImpl();
addAttribute(atts, "x1", Integer.toString(start.x));
addAttribute(atts, "y1", Integer.toString(start.y));
@@ -605,8 +648,9 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
/** {@inheritDoc} */
public void drawText(int x, int y, int letterSpacing, int wordSpacing,
- int[] dx, String text) throws IFException {
+ int[][] dp, String text) throws IFException {
try {
+ addID();
AttributesImpl atts = new AttributesImpl();
addAttribute(atts, "x", Integer.toString(x));
addAttribute(atts, "y", Integer.toString(y));
@@ -616,10 +660,19 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
if (wordSpacing != 0) {
addAttribute(atts, "word-spacing", Integer.toString(wordSpacing));
}
- if (dx != null) {
- addAttribute(atts, "dx", IFUtil.toString(dx));
+ if (dp != null) {
+ if ( IFUtil.isDPIdentity(dp) ) {
+ // don't add dx or dp attribute
+ } else if ( IFUtil.isDPOnlyDX(dp) ) {
+ // add dx attribute only
+ int[] dx = IFUtil.convertDPToDX(dp);
+ addAttribute(atts, "dx", IFUtil.toString(dx));
+ } else {
+ // add dp attribute only
+ addAttribute(atts, "dp", XMLUtil.encodePositionAdjustments(dp));
+ }
}
- addStructurePointerAttribute(atts);
+ addStructureReference(atts);
handler.startElement(EL_TEXT, atts);
char[] chars = text.toCharArray();
handler.characters(chars, 0, chars.length);
@@ -671,7 +724,8 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
}
}
if (color != null) {
- changed = !color.equals(state.getTextColor());
+ changed = !org.apache.xmlgraphics.java2d.color.ColorUtil.isSameColor(
+ color, state.getTextColor());
if (changed) {
state.setTextColor(color);
addAttribute(atts, "color", toString(color));
@@ -718,14 +772,32 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
XMLUtil.addAttribute(atts, localName, value);
}
- private void addStructurePointerAttribute(AttributesImpl atts) {
- String ptr = getContext().getStructurePointer();
- if (ptr != null) {
- addAttribute(atts, "ptr", ptr);
+ private void addStructureReference(AttributesImpl atts) {
+ IFStructureTreeElement structureTreeElement
+ = (IFStructureTreeElement) getContext().getStructureTreeElement();
+ if (structureTreeElement != null) {
+ addStructRefAttribute(atts, structureTreeElement.getId());
}
}
- // ---=== IFDocumentNavigationHandler ===---
+ private void addStructRefAttribute(AttributesImpl atts, String id) {
+ atts.addAttribute(InternalElementMapping.URI,
+ InternalElementMapping.STRUCT_REF,
+ InternalElementMapping.STANDARD_PREFIX + ":" + InternalElementMapping.STRUCT_REF,
+ XMLConstants.CDATA,
+ id);
+ }
+
+ private void addID() throws SAXException {
+ String id = getContext().getID();
+ if (!currentID.equals(id)) {
+ AttributesImpl atts = new AttributesImpl();
+ addAttribute(atts, "name", id);
+ handler.startElement(EL_ID, atts);
+ handler.endElement(EL_ID);
+ currentID = id;
+ }
+ }
private Map incompleteActions = new java.util.HashMap();
private List completeActions = new java.util.LinkedList();
@@ -763,7 +835,9 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
Iterator iter = tree.getBookmarks().iterator();
while (iter.hasNext()) {
Bookmark b = (Bookmark)iter.next();
- serializeBookmark(b);
+ if (b.getAction() != null) {
+ serializeBookmark(b);
+ }
}
handler.endElement(DocumentNavigationExtensionConstants.BOOKMARK_TREE);
} catch (SAXException e) {
@@ -783,10 +857,11 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
Iterator iter = bookmark.getChildBookmarks().iterator();
while (iter.hasNext()) {
Bookmark b = (Bookmark)iter.next();
- serializeBookmark(b);
+ if (b.getAction() != null) {
+ serializeBookmark(b);
+ }
}
handler.endElement(DocumentNavigationExtensionConstants.BOOKMARK);
-
}
/** {@inheritDoc} */
@@ -797,7 +872,8 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
atts.addAttribute(null, "rect", "rect",
XMLConstants.CDATA, IFUtil.toString(link.getTargetRect()));
if (getUserAgent().isAccessibilityEnabled()) {
- addAttribute(atts, "ptr", link.getAction().getStructurePointer());
+ addStructRefAttribute(atts,
+ ((IFStructureTreeElement) link.getAction().getStructureTreeElement()).getId());
}
try {
handler.startElement(DocumentNavigationExtensionConstants.LINK, atts);
@@ -843,12 +919,8 @@ public class IFSerializer extends AbstractXMLWritingIFDocumentHandler
}
/** {@inheritDoc} */
- public boolean isBackgroundRequired(BorderProps bpsBefore, BorderProps bpsAfter,
- BorderProps bpsStart, BorderProps bpsEnd) {
+ public boolean isBackgroundRequired(BorderProps bpsTop, BorderProps bpsBottom,
+ BorderProps bpsLeft, BorderProps bpsRight) {
return true;
}
-
-
-
-
}
diff --git a/src/java/org/apache/fop/render/intermediate/IFSerializerMaker.java b/src/java/org/apache/fop/render/intermediate/IFSerializerMaker.java
index 699fd0549..c0060ab8e 100644
--- a/src/java/org/apache/fop/render/intermediate/IFSerializerMaker.java
+++ b/src/java/org/apache/fop/render/intermediate/IFSerializerMaker.java
@@ -31,6 +31,9 @@ public class IFSerializerMaker extends AbstractIFDocumentHandlerMaker {
public IFDocumentHandler makeIFDocumentHandler(FOUserAgent ua) {
IFSerializer handler = new IFSerializer();
handler.setContext(new IFContext(ua));
+ if (ua.isAccessibilityEnabled()) {
+ ua.setStructureTreeEventHandler(handler.getStructureTreeEventHandler());
+ }
return handler;
}
diff --git a/src/java/org/apache/fop/render/intermediate/IFState.java b/src/java/org/apache/fop/render/intermediate/IFState.java
index c13382192..4d8325d3e 100644
--- a/src/java/org/apache/fop/render/intermediate/IFState.java
+++ b/src/java/org/apache/fop/render/intermediate/IFState.java
@@ -21,6 +21,8 @@ package org.apache.fop.render.intermediate;
import java.awt.Color;
+import org.apache.xmlgraphics.java2d.color.ColorUtil;
+
/** a state class for intermediate format data */
public final class IFState {
@@ -184,7 +186,7 @@ public final class IFState {
* @param color the new text color
*/
public void setTextColor(Color color) {
- if (!color.equals(this.textColor)) {
+ if (!ColorUtil.isSameColor(color, this.textColor)) {
this.fontChanged = true;
}
this.textColor = color;
diff --git a/src/java/org/apache/fop/render/intermediate/IFStructureTreeBuilder.java b/src/java/org/apache/fop/render/intermediate/IFStructureTreeBuilder.java
new file mode 100644
index 000000000..9ba9afd81
--- /dev/null
+++ b/src/java/org/apache/fop/render/intermediate/IFStructureTreeBuilder.java
@@ -0,0 +1,239 @@
+/*
+ * 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.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+import org.xml.sax.helpers.DefaultHandler;
+
+import org.apache.fop.accessibility.StructureTree2SAXEventAdapter;
+import org.apache.fop.accessibility.StructureTreeElement;
+import org.apache.fop.accessibility.StructureTreeEventHandler;
+import org.apache.fop.fo.extensions.InternalElementMapping;
+import org.apache.fop.util.XMLUtil;
+
+/**
+ * Saves structure tree events as SAX events in order to replay them when it's
+ * time to stream the structure tree to the output.
+ */
+final class IFStructureTreeBuilder implements StructureTreeEventHandler {
+
+ static final class IFStructureTreeElement implements StructureTreeElement {
+
+ private final String id;
+
+ IFStructureTreeElement() {
+ this.id = null;
+ }
+
+ IFStructureTreeElement(String id) {
+ this.id = id;
+ }
+
+ public String getId() {
+ return id;
+ }
+ }
+
+ /** A SAX handler that records events to replay them later. */
+ static class SAXEventRecorder extends DefaultHandler {
+
+ private final List<SAXEventRecorder.Event> events = new ArrayList<SAXEventRecorder.Event>();
+
+ private abstract static class Event {
+ abstract void replay(ContentHandler handler) throws SAXException;
+ }
+
+ private abstract static class Element extends SAXEventRecorder.Event {
+
+ protected final String uri;
+ protected final String localName;
+ protected final String qName;
+
+ private Element(String uri, String localName, String qName) {
+ this.uri = uri;
+ this.localName = localName;
+ this.qName = qName;
+ }
+ }
+
+ private static final class StartElement extends SAXEventRecorder.Element {
+
+ private final Attributes attributes;
+
+ private StartElement(String uri, String localName, String qName,
+ Attributes attributes) {
+ super(uri, localName, qName);
+ this.attributes = attributes;
+ }
+
+ @Override
+ void replay(ContentHandler handler) throws SAXException {
+ handler.startElement(uri, localName, qName, attributes);
+ }
+ }
+
+ private static final class EndElement extends SAXEventRecorder.Element {
+
+ private EndElement(String uri, String localName, String qName) {
+ super(uri, localName, qName);
+ }
+
+ @Override
+ void replay(ContentHandler handler) throws SAXException {
+ handler.endElement(uri, localName, qName);
+ }
+ }
+
+ private static final class StartPrefixMapping extends SAXEventRecorder.Event {
+
+ private final String prefix;
+ private final String uri;
+
+ private StartPrefixMapping(String prefix, String uri) {
+ this.prefix = prefix;
+ this.uri = uri;
+ }
+
+ @Override
+ void replay(ContentHandler handler) throws SAXException {
+ handler.startPrefixMapping(prefix, uri);
+ }
+ }
+
+ private static final class EndPrefixMapping extends SAXEventRecorder.Event {
+
+ private final String prefix;
+
+ private EndPrefixMapping(String prefix) {
+ this.prefix = prefix;
+ }
+
+ @Override
+ void replay(ContentHandler handler) throws SAXException {
+ handler.endPrefixMapping(prefix);
+ }
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String qName,
+ Attributes attributes) throws SAXException {
+ events.add(new StartElement(uri, localName, qName, attributes));
+ }
+
+ @Override
+ public void endElement(String uri, String localName, String qName) throws SAXException {
+ events.add(new EndElement(uri, localName, qName));
+ }
+
+ @Override
+ public void startPrefixMapping(String prefix, String uri) throws SAXException {
+ events.add(new StartPrefixMapping(prefix, uri));
+ }
+
+ @Override
+ public void endPrefixMapping(String prefix) throws SAXException {
+ events.add(new EndPrefixMapping(prefix));
+ }
+
+ /**
+ * Replays the recorded events.
+ *
+ * @param handler {@code ContentHandler} to replay events on
+ */
+ public void replay(ContentHandler handler) throws SAXException {
+ for (SAXEventRecorder.Event e : events) {
+ e.replay(handler);
+ }
+ }
+ }
+
+ private StructureTreeEventHandler delegate;
+
+ private final List<SAXEventRecorder> pageSequenceEventRecorders
+ = new ArrayList<SAXEventRecorder>();
+
+ private int idCounter;
+
+ /**
+ * Replay SAX events for a page sequence.
+ * @param handler The handler that receives SAX events
+ * @param pageSequenceIndex The index of the page sequence
+ * @throws SAXException
+ */
+ public void replayEventsForPageSequence(ContentHandler handler,
+ int pageSequenceIndex) throws SAXException {
+ pageSequenceEventRecorders.get(pageSequenceIndex).replay(handler);
+ }
+
+ public void startPageSequence(Locale locale, String role) {
+ SAXEventRecorder eventRecorder = new SAXEventRecorder();
+ pageSequenceEventRecorders.add(eventRecorder);
+ delegate = StructureTree2SAXEventAdapter.newInstance(eventRecorder);
+ delegate.startPageSequence(locale, role);
+ }
+
+ public void endPageSequence() {
+ delegate.endPageSequence();
+ }
+
+ public StructureTreeElement startNode(String name, Attributes attributes) {
+ delegate.startNode(name, attributes);
+ return new IFStructureTreeElement();
+ }
+
+ public void endNode(String name) {
+ delegate.endNode(name);
+ }
+
+ public StructureTreeElement startImageNode(String name, Attributes attributes) {
+ String id = getNextID();
+ AttributesImpl atts = addIDAttribute(attributes, id);
+ delegate.startImageNode(name, atts);
+ return new IFStructureTreeElement(id);
+ }
+
+ public StructureTreeElement startReferencedNode(String name, Attributes attributes) {
+ String id = getNextID();
+ AttributesImpl atts = addIDAttribute(attributes, id);
+ delegate.startReferencedNode(name, atts);
+ return new IFStructureTreeElement(id);
+ }
+
+ private String getNextID() {
+ return Integer.toHexString(idCounter++);
+ }
+
+ private AttributesImpl addIDAttribute(Attributes attributes, String id) {
+ AttributesImpl atts = new AttributesImpl(attributes);
+ atts.addAttribute(InternalElementMapping.URI,
+ InternalElementMapping.STRUCT_ID,
+ InternalElementMapping.STANDARD_PREFIX + ":" + InternalElementMapping.STRUCT_ID,
+ XMLUtil.CDATA,
+ id);
+ return atts;
+ }
+}
diff --git a/src/java/org/apache/fop/render/intermediate/IFUtil.java b/src/java/org/apache/fop/render/intermediate/IFUtil.java
index 1867b0294..c4f681936 100644
--- a/src/java/org/apache/fop/render/intermediate/IFUtil.java
+++ b/src/java/org/apache/fop/render/intermediate/IFUtil.java
@@ -22,10 +22,10 @@ package org.apache.fop.render.intermediate;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
+import org.apache.xmlgraphics.util.DoubleFormatUtil;
+
import org.apache.fop.apps.FOPException;
-import org.apache.fop.apps.FopFactory;
import org.apache.fop.fonts.FontInfo;
-import org.apache.fop.util.DecimalFormatCache;
/**
* Utility functions for the intermediate format.
@@ -41,7 +41,9 @@ public final class IFUtil {
//See http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.2.3
value = 0.0;
}
- return DecimalFormatCache.getDecimalFormat(6).format(value);
+ StringBuffer buf = new StringBuffer();
+ DoubleFormatUtil.formatDouble(value, 6, 6, buf);
+ return buf.toString();
}
/**
@@ -145,8 +147,8 @@ public final class IFUtil {
/**
* Sets up the fonts on a document handler. If the document handler provides a configurator
- * object the configuration from the {@link FopFactory} will be used. Otherwise,
- * a default font configuration will be set up.
+ * object the configuration from the {@link org.apache.fop.apps.FopFactory} will be used.
+ * Otherwise, a default font configuration will be set up.
* @param documentHandler the document handler
* @param fontInfo the font info object (may be null)
* @throws FOPException if an error occurs while setting up the fonts
@@ -173,8 +175,8 @@ public final class IFUtil {
/**
* Sets up the fonts on a document handler. If the document handler provides a configurator
- * object the configuration from the {@link FopFactory} will be used. Otherwise,
- * a default font configuration will be set up.
+ * object the configuration from the {@link org.apache.fop.apps.FopFactory} will be used.
+ * Otherwise, a default font configuration will be set up.
* @param documentHandler the document handler
* @throws FOPException if an error occurs while setting up the fonts
*/
@@ -199,4 +201,183 @@ public final class IFUtil {
return documentHandler.getMimeType();
}
+ /**
+ * Convert the general gpos 'dp' adjustments to the older 'dx' adjustments.
+ * This utility method is used to provide backward compatibility in implementations
+ * of IFPainter that have not yet been upgraded to the general position adjustments format.
+ * @param dp an array of 4-tuples, expressing [X,Y] placment
+ * adjustments and [X,Y] advancement adjustments, in that order (may be null)
+ * @param count if <code>dp</code> is not null, then a count of dp values to convert
+ * @return if <code>dp</code> is not null, then an array of adjustments to the current
+ * x position prior to rendering individual glyphs; otherwise, null
+ */
+ public static int[] convertDPToDX ( int[][] dp, int count ) {
+ int[] dx;
+ if ( dp != null ) {
+ dx = new int [ count ];
+ for ( int i = 0, n = count; i < n; i++ ) {
+ dx [ i ] = dp [ i ] [ 0 ]; // xPlaAdjust[i]
+ }
+ } else {
+ dx = null;
+ }
+ return dx;
+ }
+
+ /**
+ * Convert the general gpos 'dp' adjustments to the older 'dx' adjustments.
+ * This utility method is used to provide backward compatibility in implementations
+ * of IFPainter that have not yet been upgraded to the general position adjustments format.
+ * @param dp an array of 4-tuples, expressing [X,Y] placment
+ * adjustments and [X,Y] advancement adjustments, in that order (may be null)
+ * @return if <code>dp</code> is not null, then an array of adjustments to the current
+ * x position prior to rendering individual glyphs; otherwise, null
+ */
+ public static int[] convertDPToDX ( int[][] dp ) {
+ return convertDPToDX ( dp, ( dp != null ) ? dp.length : 0 );
+ }
+
+ /**
+ * Convert the general gpos 'dp' adjustments to the older 'dx' adjustments.
+ * This utility method is used to provide backward compatibility in implementations
+ * of IFPainter that have not yet been upgraded to the general position adjustments format.
+ * @param dx an array of adjustments to the current x position prior to rendering
+ * individual glyphs or null
+ * @param count if <code>dx</code> is not null, then a count of dx values to convert
+ * @return if <code>dx</code> is not null, then an array of 4-tuples, expressing [X,Y]
+ * placment adjustments and [X,Y] advancement adjustments, in that order; otherwise, null
+ */
+ public static int[][] convertDXToDP ( int[] dx, int count ) {
+ int[][] dp;
+ if ( dx != null ) {
+ dp = new int [ count ] [ 4 ];
+ for ( int i = 0, n = count; i < n; i++ ) {
+ int[] pa = dp [ i ];
+ int d = dx [ i ];
+ pa [ 0 ] = d; // xPlaAdjust[i]
+ pa [ 2 ] = d; // xAdvAdjust[i]
+ }
+ } else {
+ dp = null;
+ }
+ return dp;
+ }
+
+ /**
+ * Convert the general gpos 'dp' adjustments to the older 'dx' adjustments.
+ * This utility method is used to provide backward compatibility in implementations
+ * of IFPainter that have not yet been upgraded to the general position adjustments format.
+ * @param dx an array of adjustments to the current x position prior to rendering
+ * individual glyphs or null
+ * @return if <code>dx</code> is not null, then an array of 4-tuples, expressing [X,Y]
+ * placment adjustments and [X,Y] advancement adjustments, in that order; otherwise, null
+ */
+ public static int[][] convertDXToDP ( int[] dx ) {
+ return convertDXToDP ( dx, ( dx != null ) ? dx.length : 0 );
+ }
+
+ /**
+ * Determine if position adjustment is the identity adjustment, i.e., no non-zero adjustment.
+ * @param pa a 4-tuple, expressing [X,Y] placment and [X,Y] advance adjuustments (may be null)
+ * @return true if <code>dp</code> is null or contains no non-zero adjustment
+ */
+ public static boolean isPAIdentity ( int[] pa ) {
+ if ( pa == null ) {
+ return true;
+ } else {
+ for ( int k = 0; k < 4; k++ ) {
+ if ( pa[k] != 0 ) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+ /**
+ * Determine if position adjustments is the identity adjustment, i.e., no non-zero adjustment.
+ * @param dp an array of 4-tuples, expressing [X,Y] placment
+ * adjustments and [X,Y] advancement adjustments, in that order (may be null)
+ * @return true if <code>dp</code> is null or contains no non-zero adjustment
+ */
+ public static boolean isDPIdentity ( int[][] dp ) {
+ if ( dp == null ) {
+ return true;
+ } else {
+ for ( int i = 0, n = dp.length; i < n; i++ ) {
+ if ( !isPAIdentity ( dp[i] ) ) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+ /**
+ * Determine if position adjustments comprises only DX adjustments as encoded by
+ * {@link #convertDPToDX}. Note that if given a set of all all zero position
+ * adjustments, both this method and {@link #isDPIdentity} will return true;
+ * however, this method may return true when {@link #isDPIdentity} returns false.
+ * @param dp an array of 4-tuples, expressing [X,Y] placment
+ * adjustments and [X,Y] advancement adjustments, in that order (may be null)
+ * @return true if <code>dp</code> is not null and contains only xPlaAdjust
+ * and xAdvAdjust values consistent with the output of {@link #convertDPToDX}.
+ */
+ public static boolean isDPOnlyDX ( int[][] dp ) {
+ if ( dp == null ) {
+ return false;
+ } else {
+ for ( int i = 0, n = dp.length; i < n; i++ ) {
+ int[] pa = dp[i];
+ if ( pa[0] != pa[2] ) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+ /**
+ * Adjust a position adjustments array. If both <code>paDst</code> and <code>paSrc</code> are
+ * non-null, then <code>paSrc[i]</code> is added to <code>paDst[i]</code>.
+ * @param paDst a 4-tuple, expressing [X,Y] placment
+ * and [X,Y] advance adjuustments (may be null)
+ * @param paSrc a 4-tuple, expressing [X,Y] placment
+ * and [X,Y] advance adjuustments (may be null)
+ */
+ public static void adjustPA ( int[] paDst, int[] paSrc ) {
+ if ( ( paDst != null ) && ( paSrc != null ) ) {
+ assert paDst.length == 4;
+ assert paSrc.length == 4;
+ for ( int i = 0; i < 4; i++ ) {
+ paDst[i] += paSrc[i];
+ }
+ }
+ }
+
+ /**
+ * Copy entries from position adjustments.
+ * @param dp an array of 4-tuples, expressing [X,Y] placment
+ * adjustments and [X,Y] advancement adjustments, in that order
+ * @param offset starting offset from which to copy
+ * @param count number of entries to copy
+ * @return a deep copy of the count position adjustment entries start at
+ * offset
+ */
+ public static int[][] copyDP ( int[][] dp, int offset, int count ) {
+ if ( ( dp == null ) || ( offset > dp.length ) || ( ( offset + count ) > dp.length ) ) {
+ throw new IllegalArgumentException();
+ } else {
+ int[][] dpNew = new int [ count ] [ 4 ];
+ for ( int i = 0, n = count; i < n; i++ ) {
+ int[] paDst = dpNew [ i ];
+ int[] paSrc = dp [ i + offset ];
+ for ( int k = 0; k < 4; k++ ) {
+ paDst [ k ] = paSrc [ k ];
+ }
+ }
+ return dpNew;
+ }
+ }
+
}
diff --git a/src/java/org/apache/fop/render/intermediate/extensions/AbstractAction.java b/src/java/org/apache/fop/render/intermediate/extensions/AbstractAction.java
index 340b2e068..a2595d320 100644
--- a/src/java/org/apache/fop/render/intermediate/extensions/AbstractAction.java
+++ b/src/java/org/apache/fop/render/intermediate/extensions/AbstractAction.java
@@ -21,13 +21,15 @@ package org.apache.fop.render.intermediate.extensions;
import org.apache.xmlgraphics.util.XMLizable;
+import org.apache.fop.accessibility.StructureTreeElement;
+
/**
* Abstract base class for document actions, like "go-to" actions with absolute page coordinates.
*/
public abstract class AbstractAction implements XMLizable {
private String id;
- private String structurePointer;
+ private StructureTreeElement structureTreeElement;
/**
* Sets an ID to make the action referencable.
@@ -47,18 +49,18 @@ public abstract class AbstractAction implements XMLizable {
/**
* Sets the structure element corresponding to this action.
- * @param structurePointer a reference to the structure element
+ * @param structureTreeElement a reference to the structure element
*/
- public void setStructurePointer(String structurePointer) {
- this.structurePointer = structurePointer;
+ public void setStructureTreeElement(StructureTreeElement structureTreeElement) {
+ this.structureTreeElement = structureTreeElement;
}
/**
* Returns the structure element corresponding to this action.
* @return the reference to the structure element
*/
- public String getStructurePointer() {
- return structurePointer;
+ public StructureTreeElement getStructureTreeElement() {
+ return structureTreeElement;
}
/**
diff --git a/src/java/org/apache/fop/render/intermediate/extensions/DocumentNavigationHandler.java b/src/java/org/apache/fop/render/intermediate/extensions/DocumentNavigationHandler.java
index 5ca480f4a..c174a74a9 100644
--- a/src/java/org/apache/fop/render/intermediate/extensions/DocumentNavigationHandler.java
+++ b/src/java/org/apache/fop/render/intermediate/extensions/DocumentNavigationHandler.java
@@ -21,6 +21,7 @@ package org.apache.fop.render.intermediate.extensions;
import java.awt.Point;
import java.awt.Rectangle;
+import java.util.Map;
import java.util.Stack;
import org.xml.sax.Attributes;
@@ -30,6 +31,8 @@ import org.xml.sax.helpers.DefaultHandler;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.fop.accessibility.StructureTreeElement;
+import org.apache.fop.fo.extensions.InternalElementMapping;
import org.apache.fop.render.intermediate.IFDocumentNavigationHandler;
import org.apache.fop.render.intermediate.IFException;
import org.apache.fop.util.XMLUtil;
@@ -41,21 +44,27 @@ public class DocumentNavigationHandler extends DefaultHandler
implements DocumentNavigationExtensionConstants {
/** Logger instance */
- protected static Log log = LogFactory.getLog(DocumentNavigationHandler.class);
+ protected static final Log log = LogFactory.getLog(DocumentNavigationHandler.class);
private StringBuffer content = new StringBuffer();
private Stack objectStack = new Stack();
private IFDocumentNavigationHandler navHandler;
- private String structurePointer;
+ private StructureTreeElement structureTreeElement;
+
+ private Map<String, StructureTreeElement> structureTreeElements;
/**
* Main constructor.
* @param navHandler the navigation handler that will receive the events
+ * @param structureTreeElements the elements representing the structure of the document
*/
- public DocumentNavigationHandler(IFDocumentNavigationHandler navHandler) {
+ public DocumentNavigationHandler(IFDocumentNavigationHandler navHandler,
+ Map<String, StructureTreeElement> structureTreeElements) {
this.navHandler = navHandler;
+ assert structureTreeElements != null;
+ this.structureTreeElements = structureTreeElements;
}
/** {@inheritDoc} */
@@ -98,7 +107,8 @@ public class DocumentNavigationHandler extends DefaultHandler
throw new SAXException(localName + " must be the root element!");
}
Rectangle targetRect = XMLUtil.getAttributeAsRectangle(attributes, "rect");
- structurePointer = attributes.getValue("ptr");
+ structureTreeElement = structureTreeElements.get(attributes.getValue(
+ InternalElementMapping.URI, InternalElementMapping.STRUCT_REF));
Link link = new Link(null, targetRect);
objectStack.push(link);
} else if (GOTO_XY.getLocalName().equals(localName)) {
@@ -121,8 +131,8 @@ public class DocumentNavigationHandler extends DefaultHandler
}
action = new GoToXYAction(id, pageIndex, location);
}
- if (structurePointer != null) {
- action.setStructurePointer(structurePointer);
+ if (structureTreeElement != null) {
+ action.setStructureTreeElement(structureTreeElement);
}
objectStack.push(action);
} else if (GOTO_URI.getLocalName().equals(localName)) {
@@ -134,8 +144,8 @@ public class DocumentNavigationHandler extends DefaultHandler
if (id != null) {
action.setID(id);
}
- if (structurePointer != null) {
- action.setStructurePointer(structurePointer);
+ if (structureTreeElement != null) {
+ action.setStructureTreeElement(structureTreeElement);
}
objectStack.push(action);
} else {
diff --git a/src/java/org/apache/fop/render/intermediate/extensions/GoToXYAction.java b/src/java/org/apache/fop/render/intermediate/extensions/GoToXYAction.java
index a2b4f31b6..4bd548c73 100644
--- a/src/java/org/apache/fop/render/intermediate/extensions/GoToXYAction.java
+++ b/src/java/org/apache/fop/render/intermediate/extensions/GoToXYAction.java
@@ -74,7 +74,7 @@ public class GoToXYAction extends AbstractAction implements DocumentNavigationEx
* <p>
* This function will always return a valid value for safety. Use
* {@link #isComplete()} to check if the link is actually complete.
- *
+ *
* @return the page index (0-based)
*/
public int getPageIndex() {
@@ -90,7 +90,7 @@ public class GoToXYAction extends AbstractAction implements DocumentNavigationEx
* <p>
* This function will always return a valid value for safety. Use
* {@link #isComplete()} to check if the link is actually complete.
- *
+ *
* @return the target location (coordinates in millipoints)
*/
public Point getTargetLocation() {
@@ -112,7 +112,7 @@ public class GoToXYAction extends AbstractAction implements DocumentNavigationEx
private boolean isCompleteExceptTargetLocation() {
return (getPageIndex() >= 0);
}
-
+
/** {@inheritDoc} */
public boolean isComplete() {
return this.isCompleteExceptTargetLocation() && (this.targetLocation != null);
@@ -147,9 +147,9 @@ public class GoToXYAction extends AbstractAction implements DocumentNavigationEx
atts.addAttribute(null, "id", "id", XMLUtil.CDATA, getID());
atts.addAttribute(null, "page-index", "page-index",
XMLUtil.CDATA, Integer.toString(pageIndex));
- atts.addAttribute(null, "x", "x", XMLUtil.CDATA,
+ atts.addAttribute(null, "x", "x", XMLUtil.CDATA,
Integer.toString(reportedTargetLocation.x));
- atts.addAttribute(null, "y", "y", XMLUtil.CDATA,
+ atts.addAttribute(null, "y", "y", XMLUtil.CDATA,
Integer.toString(reportedTargetLocation.y));
} else {
atts.addAttribute(null, "idref", "idref", XMLUtil.CDATA, getID());
diff --git a/src/java/org/apache/fop/render/intermediate/util/IFConcatenator.java b/src/java/org/apache/fop/render/intermediate/util/IFConcatenator.java
index 4b0a3fe68..71ee7a0b0 100644
--- a/src/java/org/apache/fop/render/intermediate/util/IFConcatenator.java
+++ b/src/java/org/apache/fop/render/intermediate/util/IFConcatenator.java
@@ -19,7 +19,6 @@
package org.apache.fop.render.intermediate.util;
-
import java.awt.Dimension;
import javax.xml.transform.Source;
@@ -39,12 +38,17 @@ import org.apache.fop.render.intermediate.IFParser;
* <p>
* Note: This class will filter/ignore any document navigation events. Support for this may be
* added later.
+ * <p>
+ * Note: document-level extensions will only be transferred from the first document passed in.
+ * If you need to merge extensions from all the concatenated documents, you may have to merge
+ * these manually on the XML level, for example using XSLT.
*/
public class IFConcatenator {
private IFDocumentHandler targetHandler;
private int nextPageIndex = 0;
+ private boolean inFirstDocument = true;
/**
* Creates a new IF concatenator.
@@ -163,14 +167,17 @@ public class IFConcatenator {
/** {@inheritDoc} */
public void endDocument() throws IFException {
//ignore
+ inFirstDocument = false;
}
/** {@inheritDoc} */
public void handleExtensionObject(Object extension) throws IFException {
- if (inPageSequence) {
+ if (inPageSequence || inFirstDocument) {
//Only pass through when inside page-sequence
+ //or for the first document (for document-level extensions).
super.handleExtensionObject(extension);
}
+ //Note:Extensions from non-first documents are ignored!
}
/** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/render/intermediate/util/IFDocumentHandlerProxy.java b/src/java/org/apache/fop/render/intermediate/util/IFDocumentHandlerProxy.java
index 3d89e812e..dde744180 100644
--- a/src/java/org/apache/fop/render/intermediate/util/IFDocumentHandlerProxy.java
+++ b/src/java/org/apache/fop/render/intermediate/util/IFDocumentHandlerProxy.java
@@ -20,9 +20,11 @@
package org.apache.fop.render.intermediate.util;
import java.awt.Dimension;
+import java.util.Locale;
import javax.xml.transform.Result;
+import org.apache.fop.accessibility.StructureTreeEventHandler;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.render.intermediate.IFContext;
import org.apache.fop.render.intermediate.IFDocumentHandler;
@@ -94,6 +96,11 @@ public class IFDocumentHandlerProxy implements IFDocumentHandler {
}
/** {@inheritDoc} */
+ public StructureTreeEventHandler getStructureTreeEventHandler() {
+ return this.delegate.getStructureTreeEventHandler();
+ }
+
+ /** {@inheritDoc} */
public void setResult(Result result) throws IFException {
this.delegate.setResult(result);
}
@@ -104,6 +111,12 @@ public class IFDocumentHandlerProxy implements IFDocumentHandler {
}
/** {@inheritDoc} */
+ public void setDocumentLocale(Locale locale) {
+ this.delegate.setDocumentLocale(locale);
+
+ }
+
+ /** {@inheritDoc} */
public void startDocumentHeader() throws IFException {
this.delegate.startDocumentHeader();
}
@@ -184,4 +197,4 @@ public class IFDocumentHandlerProxy implements IFDocumentHandler {
this.delegate.handleExtensionObject(extension);
}
-} \ No newline at end of file
+}