aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/java/org/apache/fop/accessibility/fo/PDFUAWarningTestCase.java61
-rw-r--r--test/java/org/apache/fop/fo/complete_document.fo4
-rw-r--r--test/java/org/apache/fop/pdf/PDFUATestCase.java84
-rw-r--r--test/java/org/apache/fop/pdf/PDFVTTestCase.java61
-rw-r--r--test/java/org/apache/fop/render/afp/AFPParser.java235
-rw-r--r--test/java/org/apache/fop/render/afp/AFPTrueTypeTestCase.java181
-rw-r--r--test/java/org/apache/fop/render/ps/ImageHandlingTestCase.java33
-rw-r--r--test/java/org/apache/fop/render/ps/PSPainterTestCase.java74
-rw-r--r--test/layoutengine/standard-testcases/basic_link_to_last_page.xml80
-rw-r--r--test/layoutengine/standard-testcases/page-sequence-force-page-count-end-on-even.xml77
-rw-r--r--test/layoutengine/standard-testcases/region-body_column-count_span_5.xml48
11 files changed, 932 insertions, 6 deletions
diff --git a/test/java/org/apache/fop/accessibility/fo/PDFUAWarningTestCase.java b/test/java/org/apache/fop/accessibility/fo/PDFUAWarningTestCase.java
new file mode 100644
index 000000000..3940ada7e
--- /dev/null
+++ b/test/java/org/apache/fop/accessibility/fo/PDFUAWarningTestCase.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.accessibility.fo;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import org.xml.sax.helpers.AttributesImpl;
+
+import org.apache.fop.pdf.PDFDocument;
+import org.apache.fop.pdf.PDFFactory;
+import org.apache.fop.pdf.PDFParentTree;
+import org.apache.fop.pdf.PDFStructElem;
+import org.apache.fop.pdf.PDFUAMode;
+import org.apache.fop.render.pdf.PDFStructureTreeBuilder;
+
+public class PDFUAWarningTestCase {
+
+ PDFFactory pdfFactory;
+
+ @Test
+ public void nestedTableWarningTestCase() throws IOException {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ PDFStructElem emptyElem = new PDFStructElem();
+ PDFStructElem block = PDFStructureTreeBuilder.createStructureElement("block", emptyElem,
+ new AttributesImpl(), pdfFactory, null);
+ PDFStructureTreeBuilder.createStructureElement("table", block, new AttributesImpl(), pdfFactory, null);
+ block.output(bos);
+ Assert.assertEquals("Div", block.getStructureType().toString());
+ }
+
+ @Before
+ public void setUp() {
+ PDFParentTree tree = new PDFParentTree();
+ PDFDocument doc = new PDFDocument("");
+ doc.makeStructTreeRoot(tree);
+ doc.getProfile().setPDFUAMode(PDFUAMode.PDFUA_1);
+ pdfFactory = new PDFFactory(doc);
+ }
+}
diff --git a/test/java/org/apache/fop/fo/complete_document.fo b/test/java/org/apache/fop/fo/complete_document.fo
index 5a34e9e9a..b103744ae 100644
--- a/test/java/org/apache/fop/fo/complete_document.fo
+++ b/test/java/org/apache/fop/fo/complete_document.fo
@@ -38,7 +38,7 @@
</fo:static-content>
<fo:flow flow-name="xsl-region-body">
<fo:block id="4">This is a link to the <fo:wrapper id="5" color="blue"><fo:basic-link id="6"
- internal-destination="second-start">next page-sequence</fo:basic-link></fo:wrapper>
+ internal-destination="second-start" fox:alt-text="">next page-sequence</fo:basic-link></fo:wrapper>
(which starts on page <fo:page-number-citation id="7" ref-id="second-start"/> and ends on
page <fo:page-number-citation-last id="8" ref-id="second-end"/>).</fo:block>
<fo:block id="9" font-family="sans-serif" font-weight="bold" space-before="1em"
@@ -46,7 +46,7 @@
<fo:block id="11">This block of text contains a footnote<fo:footnote id="12"><fo:inline id="13"
baseline-shift="super" font-size="70%">1</fo:inline><fo:footnote-body id="14"><fo:block
id="15">A footnote with a link to the <fo:wrapper id="16" color="blue"><fo:basic-link
- id="17" external-destination="http://xmlgraphics.apache.org/fop/">FOP
+ id="17" external-destination="http://xmlgraphics.apache.org/fop/" fox:alt-text="">FOP
website</fo:basic-link></fo:wrapper></fo:block></fo:footnote-body></fo:footnote>
call.</fo:block>
<fo:table id="18" space-before="1em" width="100%" table-layout="fixed">
diff --git a/test/java/org/apache/fop/pdf/PDFUATestCase.java b/test/java/org/apache/fop/pdf/PDFUATestCase.java
new file mode 100644
index 000000000..e6d7404a2
--- /dev/null
+++ b/test/java/org/apache/fop/pdf/PDFUATestCase.java
@@ -0,0 +1,84 @@
+/*
+ * 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.pdf;
+
+import java.awt.geom.Rectangle2D;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.apache.xmlgraphics.util.QName;
+import org.apache.xmlgraphics.xmp.Metadata;
+
+import org.apache.fop.render.pdf.PDFContentGenerator;
+
+public class PDFUATestCase {
+ @Test
+ public void testXMP() throws IOException {
+ PDFDocument doc = new PDFDocument("");
+ doc.getProfile().setPDFUAMode(PDFUAMode.PDFUA_1);
+ Metadata metadata = PDFMetadata.createXMPFromPDFDocument(doc);
+ StringBuilder sb = new StringBuilder();
+ Iterator i = metadata.iterator();
+ while (i.hasNext()) {
+ QName k = (QName) i.next();
+ sb.append(k + ": " + metadata.getProperty(k).getValue() + "\n");
+ }
+ String s = sb.toString();
+ Assert.assertTrue(s, s.contains("pdfuaid:part: 1"));
+ }
+
+ @Test
+ public void testPDF() throws IOException {
+ PDFDocument doc = new PDFDocument("");
+ doc.getRoot().makeTagged();
+ doc.getRoot().setStructTreeRoot(new PDFStructTreeRoot(null));
+ doc.getInfo().setTitle("title");
+ doc.getProfile().setPDFUAMode(PDFUAMode.PDFUA_1);
+ PDFResources resources = new PDFResources(doc);
+ doc.addObject(resources);
+ PDFResourceContext context = new PDFResourceContext(resources);
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ PDFContentGenerator gen = new PDFContentGenerator(doc, out, context);
+ Rectangle2D.Float f = new Rectangle2D.Float();
+ PDFPage page = new PDFPage(resources, 0, f, f, f, f);
+ doc.addImage(context, new BitmapImage("", 1, 1, new byte[0], null));
+ doc.registerObject(page);
+ gen.flushPDFDoc();
+ doc.outputTrailer(out);
+
+ Collection<StringBuilder> objs = PDFLinearizationTestCase.readObjs(
+ new ByteArrayInputStream(out.toByteArray())).values();
+ Assert.assertTrue(getObj(objs, "/Type /Catalog").contains("/ViewerPreferences << /DisplayDocTitle true >>"));
+ }
+
+ private String getObj(Collection<StringBuilder> objs, String x) {
+ for (StringBuilder s : objs) {
+ if (s.toString().contains(x)) {
+ return s.toString();
+ }
+ }
+ return null;
+ }
+}
diff --git a/test/java/org/apache/fop/pdf/PDFVTTestCase.java b/test/java/org/apache/fop/pdf/PDFVTTestCase.java
index e3dcf2cf6..a2c1a010c 100644
--- a/test/java/org/apache/fop/pdf/PDFVTTestCase.java
+++ b/test/java/org/apache/fop/pdf/PDFVTTestCase.java
@@ -24,6 +24,7 @@ import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
@@ -34,6 +35,7 @@ import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXResult;
+import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.junit.Assert;
@@ -48,6 +50,12 @@ import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.Fop;
import org.apache.fop.apps.FopFactory;
import org.apache.fop.apps.MimeConstants;
+import org.apache.fop.render.intermediate.IFContext;
+import org.apache.fop.render.intermediate.IFDocumentHandler;
+import org.apache.fop.render.intermediate.IFException;
+import org.apache.fop.render.intermediate.IFParser;
+import org.apache.fop.render.intermediate.IFSerializer;
+import org.apache.fop.render.intermediate.IFUtil;
import org.apache.fop.render.pdf.PDFContentGenerator;
public class PDFVTTestCase {
@@ -100,18 +108,63 @@ public class PDFVTTestCase {
}
@Test
- public void textFO() throws IOException, SAXException, TransformerException {
+ public void textFO() throws IOException, SAXException, TransformerException, IFException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
- FopFactory fopFactory = FopFactory.newInstance(new File(".").toURI(),
- new FileInputStream("test/java/org/apache/fop/pdf/PDFVT.xconf"));
+ foToOutput(out, MimeConstants.MIME_PDF);
+ checkPDF(out);
+ }
+
+ @Test
+ public void textIF() throws IOException, SAXException, TransformerException, IFException {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ foToOutput(out, MimeConstants.MIME_FOP_IF);
+ iFToPDF(new ByteArrayInputStream(out.toByteArray()));
+ }
+
+
+ private void foToOutput(ByteArrayOutputStream out, String mimeFopIf)
+ throws IOException, SAXException, TransformerException {
+ FopFactory fopFactory = getFopFactory();
FOUserAgent userAgent = fopFactory.newFOUserAgent();
- Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, userAgent, out);
+ if (mimeFopIf.equals(MimeConstants.MIME_FOP_IF)) {
+ IFSerializer serializer = new IFSerializer(new IFContext(userAgent));
+ IFDocumentHandler targetHandler
+ = userAgent.getRendererFactory().createDocumentHandler(userAgent, MimeConstants.MIME_PDF);
+ serializer.mimicDocumentHandler(targetHandler);
+ userAgent.setDocumentHandlerOverride(serializer);
+ }
+
+ Fop fop = fopFactory.newFop(mimeFopIf, userAgent, out);
Transformer transformer = TransformerFactory.newInstance().newTransformer();
Source src = new StreamSource(new FileInputStream("test/java/org/apache/fop/pdf/PDFVT.fo"));
Result res = new SAXResult(fop.getDefaultHandler());
transformer.transform(src, res);
+ }
+
+ private FopFactory getFopFactory() throws IOException, SAXException {
+ return FopFactory.newInstance(new File(".").toURI(),
+ new FileInputStream("test/java/org/apache/fop/pdf/PDFVT.xconf"));
+ }
+
+ private void iFToPDF(InputStream is) throws IOException, SAXException, TransformerException, IFException {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+ FOUserAgent userAgent = getFopFactory().newFOUserAgent();
+ Transformer transformer = TransformerFactory.newInstance().newTransformer();
+ Source src = new StreamSource(is);
+ IFDocumentHandler documentHandler
+ = userAgent.getRendererFactory().createDocumentHandler(userAgent, MimeConstants.MIME_PDF);
+ documentHandler.setResult(new StreamResult(out));
+ IFUtil.setupFonts(documentHandler);
+ IFParser parser = new IFParser();
+ Result res = new SAXResult(parser.getContentHandler(documentHandler, userAgent));
+ transformer.transform(src, res);
+
+ checkPDF(out);
+ }
+ private void checkPDF(ByteArrayOutputStream out) throws IOException {
Map<String, StringBuilder> objs =
PDFLinearizationTestCase.readObjs(new ByteArrayInputStream(out.toByteArray()));
String dpart = getObj(objs.values(), "/DParts");
diff --git a/test/java/org/apache/fop/render/afp/AFPParser.java b/test/java/org/apache/fop/render/afp/AFPParser.java
new file mode 100644
index 000000000..9f0f92322
--- /dev/null
+++ b/test/java/org/apache/fop/render/afp/AFPParser.java
@@ -0,0 +1,235 @@
+/*
+ * 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.afp;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.fop.afp.AFPConstants;
+import org.apache.fop.afp.ptoca.PtocaBuilder;
+
+import junit.framework.Assert;
+
+public class AFPParser {
+ private boolean readText;
+ public AFPParser(boolean readText) {
+ this.readText = readText;
+ }
+
+ public void read(InputStream bis, StringBuilder sb) throws IOException {
+ while (bis.available() > 0) {
+ readField(bis, sb);
+ }
+ }
+
+ private void readField(InputStream bis, StringBuilder sb) throws IOException {
+ bis.read();
+ int len = getLength(bis.read(), bis.read());
+ byte[] field = new byte[len - 2];
+ bis.read(field);
+ InputStream fieldStream = new ByteArrayInputStream(field);
+ fieldStream.read();
+ byte type = (byte) fieldStream.read();
+ byte category = (byte) fieldStream.read();
+ fieldStream.skip(3);
+ String typeStr = TYPE_MAP.get(type & 0xFF);
+ String catStr = CATEGORY_MAP.get(category & 0xFF);
+ if (typeStr != null && catStr != null) {
+ sb.append(typeStr + " " + catStr);
+ if (typeStr.equals("BEGIN") || typeStr.equals("END")) {
+ byte[] name = new byte[8];
+ fieldStream.read(name);
+ sb.append(" " + new String(name, AFPConstants.EBCIDIC_ENCODING));
+ fieldStream.skip(2);
+ readTriplet(fieldStream, sb);
+ } else if (typeStr.equals("MAP")) {
+ fieldStream.skip(2);
+ readTriplet(fieldStream, sb);
+ } else if (typeStr.equals("DESCRIPTOR") && catStr.equals("OBJECT_AREA")) {
+ readTriplet(fieldStream, sb);
+ } else if (typeStr.equals("DATA") && catStr.equals("PRESENTATION_TEXT") && readText) {
+ readData(fieldStream, sb);
+ }
+ sb.append("\n");
+ }
+ }
+
+ private void readData(InputStream bis, StringBuilder sb) throws IOException {
+ Assert.assertEquals(bis.read(), 0x2B);
+ Assert.assertEquals(bis.read(), 0xD3);
+ while (bis.available() > 0) {
+ int len = bis.read();
+ int functionType = bis.read();
+
+ sb.append(" " + PTOCA_MAP.get(functionType));
+
+ if ("TRN".equals(PTOCA_MAP.get(functionType))) {
+ byte[] data = new byte[len - 2];
+ bis.read(data);
+ sb.append(" " + new String(data, "UTF-16BE"));
+ } else {
+ bis.skip(len - 2);
+ }
+ }
+ }
+
+ private void readTriplet(InputStream des, StringBuilder sb) throws IOException {
+ if (des.available() > 0) {
+ sb.append(" Triplets: ");
+ }
+ while (des.available() > 0) {
+ int len2 = des.read();
+ int id = des.read();
+ int b = id & 0xFF;
+ if (TRIPLET_MAP.containsKey(b)) {
+ sb.append(TRIPLET_MAP.get(b) + ",");
+ } else {
+ sb.append(String.format("0x%02X,", b));
+ }
+ des.skip(len2 - 2);
+ }
+ }
+
+ private int getLength(int a, int b) {
+ return (a * 256) + b;
+ }
+
+ private static final Map<Integer, String> TYPE_MAP = new HashMap<Integer, String>();
+ private static final Map<Integer, String> CATEGORY_MAP = new HashMap<Integer, String>();
+ private static final Map<Integer, String> TRIPLET_MAP = new HashMap<Integer, String>();
+ private static final Map<Integer, String> PTOCA_MAP = new HashMap<Integer, String>();
+ static {
+ PTOCA_MAP.put(0xC2 | PtocaBuilder.CHAIN_BIT, "SIA");
+ PTOCA_MAP.put(0xC4 | PtocaBuilder.CHAIN_BIT, "SVI");
+ PTOCA_MAP.put(0xC6 | PtocaBuilder.CHAIN_BIT, "AMI");
+ PTOCA_MAP.put(0xC8 | PtocaBuilder.CHAIN_BIT, "RMI");
+ PTOCA_MAP.put(0xD2 | PtocaBuilder.CHAIN_BIT, "AMB");
+ PTOCA_MAP.put(0xDA | PtocaBuilder.CHAIN_BIT, "TRN");
+ PTOCA_MAP.put(0xE4 | PtocaBuilder.CHAIN_BIT, "DIR");
+ PTOCA_MAP.put(0xE6 | PtocaBuilder.CHAIN_BIT, "DBR");
+ PTOCA_MAP.put(0x80 | PtocaBuilder.CHAIN_BIT, "SEC");
+ PTOCA_MAP.put(0xF0 | PtocaBuilder.CHAIN_BIT, "SCFL");
+ PTOCA_MAP.put(0xF6 | PtocaBuilder.CHAIN_BIT, "STO");
+ PTOCA_MAP.put(0xF8 | PtocaBuilder.CHAIN_BIT, "NOP");
+
+ TYPE_MAP.put(0xA0, "ATTRIBUTE");
+ TYPE_MAP.put(0xA2, "COPY_COUNT");
+ TYPE_MAP.put(0xA6, "DESCRIPTOR");
+ TYPE_MAP.put(0xA7, "CONTROL");
+ TYPE_MAP.put(0xA8, "BEGIN");
+ TYPE_MAP.put(0xA9, "END");
+ TYPE_MAP.put(0xAB, "MAP");
+ TYPE_MAP.put(0xAC, "POSITION");
+ TYPE_MAP.put(0xAD, "PROCESS");
+ TYPE_MAP.put(0xAF, "INCLUDE");
+ TYPE_MAP.put(0xB0, "TABLE");
+ TYPE_MAP.put(0xB1, "MIGRATION");
+ TYPE_MAP.put(0xB2, "VARIABLE");
+ TYPE_MAP.put(0xB4, "LINK");
+ TYPE_MAP.put(0xEE, "DATA");
+
+ CATEGORY_MAP.put(0x5F, "PAGE_SEGMENT");
+ CATEGORY_MAP.put(0x6B, "OBJECT_AREA");
+ CATEGORY_MAP.put(0x77, "COLOR_ATTRIBUTE_TABLE");
+ CATEGORY_MAP.put(0x7B, "IM_IMAGE");
+ CATEGORY_MAP.put(0x88, "MEDIUM");
+ CATEGORY_MAP.put(0x8A, "CODED_FONT");
+ CATEGORY_MAP.put(0x90, "PROCESS_ELEMENT");
+ CATEGORY_MAP.put(0x92, "OBJECT_CONTAINER");
+ CATEGORY_MAP.put(0x9B, "PRESENTATION_TEXT");
+ CATEGORY_MAP.put(0xA7, "INDEX");
+ CATEGORY_MAP.put(0xA8, "DOCUMENT");
+ CATEGORY_MAP.put(0xAD, "PAGE_GROUP");
+ CATEGORY_MAP.put(0xAF, "PAGE");
+ CATEGORY_MAP.put(0xBB, "GRAPHICS");
+ CATEGORY_MAP.put(0xC3, "DATA_RESOURCE");
+ CATEGORY_MAP.put(0xC4, "DOCUMENT_ENVIRONMENT_GROUP");
+ CATEGORY_MAP.put(0xC6, "RESOURCE_GROUP");
+ CATEGORY_MAP.put(0xC7, "OBJECT_ENVIRONMENT_GROUP");
+ CATEGORY_MAP.put(0xC9, "ACTIVE_ENVIRONMENT_GROUP");
+ CATEGORY_MAP.put(0xCC, "MEDIUM_MAP");
+ CATEGORY_MAP.put(0xCD, "FORM_MAP");
+ CATEGORY_MAP.put(0xCE, "NAME_RESOURCE");
+ CATEGORY_MAP.put(0xD8, "PAGE_OVERLAY");
+ CATEGORY_MAP.put(0xD9, "RESOURCE_ENVIROMENT_GROUP");
+ CATEGORY_MAP.put(0xDF, "OVERLAY");
+ CATEGORY_MAP.put(0xEA, "DATA_SUPRESSION");
+ CATEGORY_MAP.put(0xEB, "BARCODE");
+ CATEGORY_MAP.put(0xEE, "NO_OPERATION");
+ CATEGORY_MAP.put(0xFB, "IMAGE");
+
+ TRIPLET_MAP.put(0x02, "FULLY_QUALIFIED_NAME");
+ TRIPLET_MAP.put(0x04, "MAPPING_OPTION");
+ TRIPLET_MAP.put(0x10, "OBJECT_CLASSIFICATION");
+ TRIPLET_MAP.put(0x18, "MODCA_INTERCHANGE_SET");
+ TRIPLET_MAP.put(0x1F, "FONT_DESCRIPTOR_SPECIFICATION");
+ TRIPLET_MAP.put(0x21, "OBJECT_FUNCTION_SET_SPECIFICATION");
+ TRIPLET_MAP.put(0x22, "EXTENDED_RESOURCE_LOCAL_IDENTIFIER");
+ TRIPLET_MAP.put(0x24, "RESOURCE_LOCAL_IDENTIFIER");
+ TRIPLET_MAP.put(0x25, "RESOURCE_SECTION_NUMBER");
+ TRIPLET_MAP.put(0x26, "CHARACTER_ROTATION");
+ TRIPLET_MAP.put(0x2D, "OBJECT_BYTE_OFFSET");
+ TRIPLET_MAP.put(0x36, "ATTRIBUTE_VALUE");
+ TRIPLET_MAP.put(0x43, "DESCRIPTOR_POSITION");
+ TRIPLET_MAP.put(0x45, "MEDIA_EJECT_CONTROL");
+ TRIPLET_MAP.put(0x46, "PAGE_OVERLAY_CONDITIONAL_PROCESSING");
+ TRIPLET_MAP.put(0x47, "RESOURCE_USAGE_ATTRIBUTE");
+ TRIPLET_MAP.put(0x4B, "MEASUREMENT_UNITS");
+ TRIPLET_MAP.put(0x4C, "OBJECT_AREA_SIZE");
+ TRIPLET_MAP.put(0x4D, "AREA_DEFINITION");
+ TRIPLET_MAP.put(0x4E, "COLOR_SPECIFICATION");
+ TRIPLET_MAP.put(0x50, "ENCODING_SCHEME_ID");
+ TRIPLET_MAP.put(0x56, "MEDIUM_MAP_PAGE_NUMBER");
+ TRIPLET_MAP.put(0x57, "OBJECT_BYTE_EXTENT");
+ TRIPLET_MAP.put(0x58, "OBJECT_STRUCTURED_FIELD_OFFSET");
+ TRIPLET_MAP.put(0x59, "OBJECT_STRUCTURED_FIELD_EXTENT");
+ TRIPLET_MAP.put(0x5A, "OBJECT_OFFSET");
+ TRIPLET_MAP.put(0x5D, "FONT_HORIZONTAL_SCALE_FACTOR");
+ TRIPLET_MAP.put(0x5E, "OBJECT_COUNT");
+ TRIPLET_MAP.put(0x62, "OBJECT_DATE_AND_TIMESTAMP");
+ TRIPLET_MAP.put(0x65, "COMMENT");
+ TRIPLET_MAP.put(0x68, "MEDIUM_ORIENTATION");
+ TRIPLET_MAP.put(0x6C, "RESOURCE_OBJECT_INCLUDE");
+ TRIPLET_MAP.put(0x70, "PRESENTATION_SPACE_RESET_MIXING");
+ TRIPLET_MAP.put(0x71, "PRESENTATION_SPACE_MIXING_RULE");
+ TRIPLET_MAP.put(0x72, "UNIVERSAL_DATE_AND_TIMESTAMP");
+ TRIPLET_MAP.put(0x74, "TONER_SAVER");
+ TRIPLET_MAP.put(0x75, "COLOR_FIDELITY");
+ TRIPLET_MAP.put(0x78, "FONT_FIDELITY");
+ TRIPLET_MAP.put(0x80, "ATTRIBUTE_QUALIFIER");
+ TRIPLET_MAP.put(0x81, "PAGE_POSITION_INFORMATION");
+ TRIPLET_MAP.put(0x82, "PARAMETER_VALUE");
+ TRIPLET_MAP.put(0x83, "PRESENTATION_CONTROL");
+ TRIPLET_MAP.put(0x84, "FONT_RESOLUTION_AND_METRIC_TECHNOLOGY");
+ TRIPLET_MAP.put(0x85, "FINISHING_OPERATION");
+ TRIPLET_MAP.put(0x86, "TEXT_FIDELITY");
+ TRIPLET_MAP.put(0x87, "MEDIA_FIDELITY");
+ TRIPLET_MAP.put(0x88, "FINISHING_FIDELITY");
+ TRIPLET_MAP.put(0x8B, "DATA_OBJECT_FONT_DESCRIPTOR");
+ TRIPLET_MAP.put(0x8C, "LOCALE_SELECTOR");
+ TRIPLET_MAP.put(0x8E, "UP3I_FINISHING_OPERATION");
+ TRIPLET_MAP.put(0x91, "COLOR_MANAGEMENT_RESOURCE_DESCRIPTOR");
+ TRIPLET_MAP.put(0x95, "RENDERING_INTENT");
+ TRIPLET_MAP.put(0x96, "CMR_TAG_FIDELITY");
+ TRIPLET_MAP.put(0x97, "DEVICE_APPEARANCE");
+ }
+}
diff --git a/test/java/org/apache/fop/render/afp/AFPTrueTypeTestCase.java b/test/java/org/apache/fop/render/afp/AFPTrueTypeTestCase.java
new file mode 100644
index 000000000..6e6bbfe94
--- /dev/null
+++ b/test/java/org/apache/fop/render/afp/AFPTrueTypeTestCase.java
@@ -0,0 +1,181 @@
+/*
+ * 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.afp;
+
+import java.awt.Color;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.sax.SAXResult;
+import javax.xml.transform.stream.StreamSource;
+
+import org.junit.Test;
+
+import org.xml.sax.SAXException;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.apache.fop.afp.AFPPaintingState;
+import org.apache.fop.afp.AFPResourceManager;
+import org.apache.fop.afp.DataStream;
+import org.apache.fop.afp.Factory;
+import org.apache.fop.afp.fonts.FopCharacterSet;
+import org.apache.fop.afp.modca.PageObject;
+import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.apps.Fop;
+import org.apache.fop.apps.FopConfParser;
+import org.apache.fop.apps.FopFactory;
+import org.apache.fop.apps.FopFactoryBuilder;
+import org.apache.fop.fonts.EmbeddingMode;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.fonts.FontTriplet;
+import org.apache.fop.fonts.MultiByteFont;
+import org.apache.fop.render.intermediate.IFException;
+
+import junit.framework.Assert;
+
+public class AFPTrueTypeTestCase {
+ @Test
+ public void testAFPTrueType() throws IOException, SAXException, TransformerException {
+ String fopxconf = "<fop version=\"1.0\">\n"
+ + " <renderers>\n"
+ + " <renderer mime=\"application/x-afp\">\n"
+ + " <fonts>\n"
+ + " <font name=\"Univers\" embed-url=\"test/resources/fonts/ttf/DejaVuLGCSerif.ttf\">\n"
+ + " <font-triplet name=\"Univers\" style=\"normal\" weight=\"normal\"/>\n"
+ + " <font-triplet name=\"any\" style=\"normal\" weight=\"normal\"/>\n"
+ + " </font>\n"
+ + " </fonts>\n"
+ + " </renderer>\n"
+ + " </renderers>\n"
+ + "</fop>";
+ String fo = "<fo:root xmlns:fo=\"http://www.w3.org/1999/XSL/Format\">\n"
+ + " <fo:layout-master-set>\n"
+ + " <fo:simple-page-master master-name=\"simple\">\n"
+ + " <fo:region-body />\n"
+ + " </fo:simple-page-master>\n"
+ + " </fo:layout-master-set>\n"
+ + " <fo:page-sequence master-reference=\"simple\">\n"
+ + " <fo:flow flow-name=\"xsl-region-body\">\n"
+ + " <fo:block font-family=\"Univers\">Univers</fo:block>\n"
+ + " </fo:flow>\n"
+ + " </fo:page-sequence>\n"
+ + "</fo:root>";
+
+ FopFactoryBuilder confBuilder = new FopConfParser(
+ new ByteArrayInputStream(fopxconf.getBytes()), new File(".").toURI()).getFopFactoryBuilder();
+ FopFactory fopFactory = confBuilder.build();
+ FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ Fop fop = fopFactory.newFop("application/x-afp", foUserAgent, bos);
+ TransformerFactory factory = TransformerFactory.newInstance();
+ Transformer transformer = factory.newTransformer();
+ Source src = new StreamSource(new ByteArrayInputStream(fo.getBytes()));
+ Result res = new SAXResult(fop.getDefaultHandler());
+ transformer.transform(src, res);
+ bos.close();
+
+ StringBuilder sb = new StringBuilder();
+ InputStream bis = new ByteArrayInputStream(bos.toByteArray());
+ new AFPParser(false).read(bis, sb);
+
+ String format = "BEGIN RESOURCE_GROUP RG000001\n"
+ + "BEGIN NAME_RESOURCE RES00001 Triplets: OBJECT_FUNCTION_SET_SPECIFICATION"
+ + ",OBJECT_CLASSIFICATION,0x01,FULLY_QUALIFIED_NAME,\n"
+ + "BEGIN OBJECT_CONTAINER OC000001 Triplets: 0x41,0x00,0x00,\n";
+ for (int i = 0; i < 29; i++) {
+ format += "DATA OBJECT_CONTAINER\n";
+ }
+ format += "END OBJECT_CONTAINER OC000001\n"
+ + "END NAME_RESOURCE RES00001\n"
+ + "END RESOURCE_GROUP RG000001\n"
+ + "BEGIN DOCUMENT DOC00001\n"
+ + "BEGIN PAGE_GROUP PGP00001\n"
+ + "BEGIN PAGE PGN00001\n"
+ + "BEGIN ACTIVE_ENVIRONMENT_GROUP AEG00001\n"
+ + "MAP DATA_RESOURCE Triplets: 0x01,FULLY_QUALIFIED_NAME,FULLY_QUALIFIED_NAME"
+ + ",OBJECT_CLASSIFICATION,DATA_OBJECT_FONT_DESCRIPTOR,\n"
+ + "DESCRIPTOR PAGE\n"
+ + "MIGRATION PRESENTATION_TEXT\n"
+ + "END ACTIVE_ENVIRONMENT_GROUP AEG00001\n"
+ + "BEGIN PRESENTATION_TEXT PT000001\n"
+ + "DATA PRESENTATION_TEXT\n"
+ + "END PRESENTATION_TEXT PT000001\n"
+ + "END PAGE PGN00001\n"
+ + "END PAGE_GROUP PGP00001\n"
+ + "END DOCUMENT DOC00001\n";
+
+ Assert.assertEquals(sb.toString(), format);
+ }
+
+ @Test
+ public void testAFPPainter() throws IFException, IOException {
+ AFPDocumentHandler afpDocumentHandler = mock(AFPDocumentHandler.class);
+ when(afpDocumentHandler.getPaintingState()).thenReturn(new AFPPaintingState());
+ when(afpDocumentHandler.getResourceManager()).thenReturn(new AFPResourceManager(null));
+
+ DataStream ds = mock(DataStream.class);
+ when(afpDocumentHandler.getDataStream()).thenReturn(ds);
+ PageObject po = new PageObject(new Factory(), "PAGE0001", 0, 0, 0, 0, 0);
+ when(ds.getCurrentPage()).thenReturn(po);
+
+ AFPPainter afpPainter = new MyAFPPainter(afpDocumentHandler);
+ afpPainter.setFont("any", "normal", 400, null, null, Color.BLACK);
+ afpPainter.drawText(0, 0, 0, 0, null, "test");
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ po.writeToStream(bos);
+
+ InputStream bis = new ByteArrayInputStream(bos.toByteArray());
+ StringBuilder sb = new StringBuilder();
+ new AFPParser(true).read(bis, sb);
+ Assert.assertTrue(sb.toString(),
+ sb.toString().contains("DATA PRESENTATION_TEXT AMB AMI SCFL TRN t TRN e TRN s TRN t"));
+ }
+
+ class MyAFPPainter extends AFPPainter {
+ public MyAFPPainter(AFPDocumentHandler documentHandler) {
+ super(documentHandler);
+ }
+
+ protected FOUserAgent getUserAgent() {
+ FopFactory fopFactory = FopFactory.newInstance(new File(".").toURI());
+ return fopFactory.newFOUserAgent();
+ }
+
+ protected FontInfo getFontInfo() {
+ FontInfo f = new FontInfo();
+ f.addFontProperties("any", FontTriplet.DEFAULT_FONT_TRIPLET);
+ MultiByteFont font = new MultiByteFont(null, EmbeddingMode.AUTO);
+ font.setWidthArray(new int[100]);
+ f.addMetrics("any", new AFPFontConfig.AFPTrueTypeFont("", true,
+ new FopCharacterSet("", "UTF-16BE", "", font, null, null), null, null));
+ return f;
+ }
+ }
+}
diff --git a/test/java/org/apache/fop/render/ps/ImageHandlingTestCase.java b/test/java/org/apache/fop/render/ps/ImageHandlingTestCase.java
index 02e96806f..3c05e9ad7 100644
--- a/test/java/org/apache/fop/render/ps/ImageHandlingTestCase.java
+++ b/test/java/org/apache/fop/render/ps/ImageHandlingTestCase.java
@@ -18,18 +18,27 @@
/* $Id$ */
package org.apache.fop.render.ps;
+
+import java.awt.Rectangle;
+import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import org.junit.Test;
+import org.w3c.dom.Document;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.apache.commons.io.IOUtils;
+import org.apache.batik.anim.dom.SAXSVGDocumentFactory;
+
+import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM;
import org.apache.xmlgraphics.ps.DSCConstants;
+import org.apache.xmlgraphics.ps.PSGenerator;
import org.apache.xmlgraphics.ps.PSResource;
import org.apache.xmlgraphics.ps.dsc.DSCException;
import org.apache.xmlgraphics.ps.dsc.DSCParser;
@@ -39,6 +48,8 @@ import org.apache.xmlgraphics.ps.dsc.events.DSCCommentTitle;
import org.apache.xmlgraphics.ps.dsc.events.DSCEvent;
import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.apps.FopFactory;
+import org.apache.fop.fonts.FontInfo;
import org.apache.fop.render.intermediate.IFContext;
/**
@@ -159,4 +170,26 @@ public class ImageHandlingTestCase extends AbstractPostScriptTest {
return sb.toString();
}
+ @Test
+ public void testPSImageHandlerSVG() throws IOException {
+ FOUserAgent ua = FopFactory.newInstance(new File(".").toURI()).newFOUserAgent();
+ String svg = "<svg xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns=\"http://www.w3.org/2000/svg\" "
+ + "width=\"210mm\" height=\"297mm\" font-size=\"20\" stroke-width=\"0.1mm\" font-family=\"Arial\">\n"
+ + " <filter id=\"drop-shadow-font\" width=\"150%\" height=\"150%\">\n"
+ + " <feGaussianBlur in=\"SourceAlpha\" result=\"blur\" stdDeviation=\"1\"/>\n"
+ + " <feOffset in=\"blur\" result=\"offsetBlur\" dy=\"1\" dx=\"1\"/>\n"
+ + " <feBlend in=\"SourceGraphic\" in2=\"offsetBlur\" mode=\"normal\"/>\n"
+ + " </filter>\n"
+ + " <text x=\"4.9mm\" filter=\"url(#drop-shadow-font)\" y=\"10.5mm\" fill=\"black\" "
+ + "rotate=\"30 30 0 15\">Hello SVG with FOP</text>\n"
+ + "</svg>";
+ SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory(null);
+ Document doc = factory.createDocument(null, IOUtils.toInputStream(svg));
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ new PSImageHandlerSVG().handleImage(
+ new PSRenderingContext(ua, new PSGenerator(bos), new FontInfo()),
+ new ImageXMLDOM(null, doc, ""),
+ new Rectangle());
+ assertTrue(bos.toString().contains("/DataSource Data"));
+ }
}
diff --git a/test/java/org/apache/fop/render/ps/PSPainterTestCase.java b/test/java/org/apache/fop/render/ps/PSPainterTestCase.java
index b678fdb4b..3efbb47d4 100644
--- a/test/java/org/apache/fop/render/ps/PSPainterTestCase.java
+++ b/test/java/org/apache/fop/render/ps/PSPainterTestCase.java
@@ -18,11 +18,16 @@ package org.apache.fop.render.ps;
import java.awt.Color;
import java.awt.Rectangle;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
+import javax.xml.transform.stream.StreamResult;
+
+import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.verification.VerificationMode;
@@ -38,15 +43,19 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.apache.xmlgraphics.ps.PSGenerator;
+import org.apache.xmlgraphics.ps.dsc.ResourceTracker;
import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.apps.FopFactory;
import org.apache.fop.fo.Constants;
+import org.apache.fop.fonts.EmbeddingMode;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.fonts.MultiByteFont;
import org.apache.fop.fonts.Typeface;
import org.apache.fop.render.intermediate.IFContext;
+import org.apache.fop.render.intermediate.IFException;
import org.apache.fop.render.intermediate.IFState;
import org.apache.fop.traits.BorderProps;
@@ -161,4 +170,69 @@ public class PSPainterTestCase {
fail("something broke...");
}
}
+
+ @Test
+ public void testOTF() throws IFException, IOException {
+ FOUserAgent ua = FopFactory.newInstance(new File(".").toURI()).newFOUserAgent();
+ final IFState state = IFState.create();
+ PSDocumentHandler dh = new PSDocumentHandler(new IFContext(ua)) {
+ protected PSFontResource getPSResourceForFontKey(String key) {
+ return new PSFontResource() {
+ String getName() {
+ return state.getFontFamily();
+ }
+ void notifyResourceUsageOnPage(ResourceTracker resourceTracker) {
+ }
+ };
+ }
+ };
+ FontInfo fi = new FontInfo();
+ addFont(fi, "OTFFont", true);
+ addFont(fi, "TTFFont", false);
+
+ dh.setFontInfo(fi);
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ dh.setResult(new StreamResult(bos));
+ dh.startDocument();
+ state.setFontSize(10);
+ state.setTextColor(Color.BLACK);
+ state.setFontStyle("");
+ PSPainter p = new PSPainter(dh, state) {
+ protected String getFontKey(FontTriplet triplet) throws IFException {
+ return state.getFontFamily();
+ }
+ };
+
+ state.setFontFamily("TTFFont");
+ p.drawText(0, 0, 0, 0, null, "test1");
+
+ state.setFontFamily("OTFFont");
+ p.drawText(0, 0, 0, 0, null, "test2");
+ p.drawText(0, 0, 0, 0, null, "test3");
+
+ state.setFontFamily("TTFFont");
+ p.drawText(0, 0, 0, 0, null, "test4");
+
+ Assert.assertTrue(bos.toString(), bos.toString().endsWith("BT\n"
+ + "/TTFFont 0.01 F\n"
+ + "1 0 0 -1 0 0 Tm\n"
+ + "<00000000000000000000> t\n"
+ + "/OTFFont.0 0.01 F\n"
+ + "1 0 0 -1 0 0 Tm\n"
+ + "<FFFFFFFFFF> t\n"
+ + "/OTFFont.0 0.01 F\n"
+ + "1 0 0 -1 0 0 Tm\n"
+ + "<FFFFFFFFFF> t\n"
+ + "/TTFFont 0.01 F\n"
+ + "1 0 0 -1 0 0 Tm\n"
+ + "<00000000000000000000> t\n"));
+ }
+
+ private void addFont(FontInfo fi, String name, boolean otf) {
+ fi.addFontProperties(name, name, "", 0);
+ MultiByteFont mbf = new MultiByteFont(null, EmbeddingMode.AUTO);
+ mbf.setWidthArray(new int[100]);
+ mbf.setIsOTFFile(otf);
+ fi.addMetrics(name, mbf);
+ }
}
diff --git a/test/layoutengine/standard-testcases/basic_link_to_last_page.xml b/test/layoutengine/standard-testcases/basic_link_to_last_page.xml
new file mode 100644
index 000000000..df99c7cde
--- /dev/null
+++ b/test/layoutengine/standard-testcases/basic_link_to_last_page.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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$ -->
+<testcase>
+ <info>
+ <p>This test checks links to and from the last page.</p>
+ </info>
+ <fo>
+ <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+ <fo:layout-master-set>
+ <fo:simple-page-master margin="2cm" master-name="odd" page-height="297mm" page-width="210mm">
+ <fo:region-body column-count="2" column-gap="28pt"/>
+ </fo:simple-page-master>
+ <fo:simple-page-master margin="2cm" master-name="even" page-height="297mm" page-width="210mm">
+ <fo:region-body column-count="2" column-gap="28pt"/>
+ </fo:simple-page-master>
+ <fo:simple-page-master margin="2cm" master-name="last" page-height="297mm" page-width="210mm">
+ <fo:region-body column-count="2" column-gap="28pt"/>
+ </fo:simple-page-master>
+ <fo:page-sequence-master master-name="basicPSM">
+ <fo:repeatable-page-master-alternatives>
+ <fo:conditional-page-master-reference master-reference="last" odd-or-even="any" page-position="last"/>
+ <fo:conditional-page-master-reference master-reference="odd" odd-or-even="odd" page-position="any"/>
+ <fo:conditional-page-master-reference master-reference="even" odd-or-even="even" page-position="any"/>
+ </fo:repeatable-page-master-alternatives>
+ </fo:page-sequence-master>
+ </fo:layout-master-set>
+ <fo:bookmark-tree>
+ <fo:bookmark internal-destination="title" starting-state="show">
+ <fo:bookmark-title>title</fo:bookmark-title>
+ </fo:bookmark>
+ </fo:bookmark-tree>
+ <fo:page-sequence id="lastpagesequence" master-reference="basicPSM">
+ <fo:flow flow-name="xsl-region-body">
+ <fo:block id="par" break-after="page">par</fo:block>
+ <fo:block id="par2" break-after="page">par2</fo:block>
+ <fo:block id="par3" break-after="page">par3</fo:block>
+ <fo:block>before-title</fo:block>
+ <fo:block id="title" keep-with-next="always">title</fo:block>
+ <fo:block>
+ <fo:basic-link internal-destination="par2">
+ siehe <fo:inline keep-together="always">
+ Seite <fo:page-number-citation ref-id="par2"/>
+ </fo:inline>
+ </fo:basic-link>
+ </fo:block>
+ <fo:block break-before="column">title2</fo:block>
+ <fo:block>
+ <fo:basic-link internal-destination="par3">
+ siehe <fo:inline keep-together="always">
+ Seite <fo:page-number-citation ref-id="par3"/>
+ </fo:inline>
+ </fo:basic-link>
+ </fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+ </fo:root>
+ </fo>
+ <checks>
+ <eval expected="(P2,par2)" xpath="((/areaTree/pageSequence/pageViewport)[4]//inlineparent[@internal-link])[1]/@internal-link"/>
+ <eval expected="(P3,par3)" xpath="((/areaTree/pageSequence/pageViewport)[4]//inlineparent[@internal-link])[2]/@internal-link"/>
+ <eval expected="(P5,title)" xpath="/areaTree/bookmarkTree/bookmark/@internal-link"/>
+ <eval expected="4" xpath="count(/areaTree/pageSequence/pageViewport)"/>
+ </checks>
+</testcase>
diff --git a/test/layoutengine/standard-testcases/page-sequence-force-page-count-end-on-even.xml b/test/layoutengine/standard-testcases/page-sequence-force-page-count-end-on-even.xml
new file mode 100644
index 000000000..42fa263d6
--- /dev/null
+++ b/test/layoutengine/standard-testcases/page-sequence-force-page-count-end-on-even.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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$ -->
+<testcase>
+ <info>
+ <p>
+ This checks that when force-page-count=end-on-even that the last simple-
+ page-master is used when a single page overflows to a second
+ page and the page count is forced to end-on-even.
+ </p>
+ </info>
+ <fo>
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+ <fo:layout-master-set>
+ <fo:simple-page-master margin="2cm" master-name="last" page-height="297mm"
+ page-width="210mm">
+ <fo:region-body/>
+ <fo:region-after extent="22.5mm" region-name="after-last"/>
+ </fo:simple-page-master>
+ <fo:simple-page-master margin="2cm" master-name="any" page-height="297mm"
+ page-width="210mm">
+ <fo:region-body/>
+ </fo:simple-page-master>
+ <fo:page-sequence-master master-name="master">
+ <fo:repeatable-page-master-alternatives>
+ <fo:conditional-page-master-reference master-reference="last" odd-or-even="any"
+ page-position="last"/>
+ <fo:conditional-page-master-reference master-reference="any" odd-or-even="any"
+ page-position="any"/>
+ </fo:repeatable-page-master-alternatives>
+ </fo:page-sequence-master>
+ </fo:layout-master-set>
+ <fo:page-sequence force-page-count="end-on-odd" master-reference="master">
+ <fo:static-content flow-name="after-last">
+ <fo:block-container background-color="rgb(209,211,212)" height="22.5mm">
+ <fo:block>Last-Page-3</fo:block>
+ </fo:block-container>
+ </fo:static-content>
+ <fo:flow flow-name="xsl-region-body">
+ <fo:block>Page 1</fo:block>
+ <fo:block break-before="page">Page 2</fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+ <fo:page-sequence force-page-count="end-on-odd" master-reference="master">
+ <fo:static-content flow-name="after-last">
+ <fo:block-container background-color="rgb(209,211,212)" height="22.5mm">
+ <fo:block>Last-Page-5</fo:block>
+ </fo:block-container>
+ </fo:static-content>
+ <fo:flow flow-name="xsl-region-body">
+ <fo:block>Page-4</fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+</fo:root>
+
+ </fo>
+ <checks>
+ <eval expected="Last-Page-3" xpath="(//pageViewport)[3]//regionAfter//word"/>
+ <eval expected="Last-Page-5" xpath="(//pageViewport)[5]//regionAfter//word"/>
+ <eval expected="5" xpath="count(//pageViewport)"/>
+ </checks>
+</testcase>
diff --git a/test/layoutengine/standard-testcases/region-body_column-count_span_5.xml b/test/layoutengine/standard-testcases/region-body_column-count_span_5.xml
new file mode 100644
index 000000000..55f7989c1
--- /dev/null
+++ b/test/layoutengine/standard-testcases/region-body_column-count_span_5.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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: region-body_column-count_span_4.xml 993357 2010-09-07 13:45:39Z jeremias $ -->
+<testcase>
+ <info>
+ <p>
+ This test checks multi-column documents. Check that spanned section that overflow
+ the current page, don't span to the next page.
+ </p>
+ </info>
+ <fo>
+ <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
+ <fo:layout-master-set>
+ <fo:simple-page-master master-name="odd" page-height="200mm" page-width="150mm">
+ <fo:region-body column-count="2"/>
+ </fo:simple-page-master>
+ </fo:layout-master-set>
+ <fo:page-sequence master-reference="odd">
+ <fo:flow flow-name="xsl-region-body">
+ <fo:block-container id="overflow-block-ct" keep-together.within-page="always"
+ height="200.1mm" span="all">
+ <fo:block id="overflow-block">overflow-block</fo:block>
+ </fo:block-container>
+ <fo:block id="col1">col1</fo:block>
+ <fo:block id="col2" break-before="column">col2</fo:block>
+ </fo:flow>
+ </fo:page-sequence>
+ </fo:root>
+ </fo>
+ <checks>
+ <eval expected="2" xpath="count(//pageViewport)"/>
+ </checks>
+</testcase>