diff options
author | Simon Pepping <spepping@apache.org> | 2004-08-01 19:48:51 +0000 |
---|---|---|
committer | Simon Pepping <spepping@apache.org> | 2004-08-01 19:48:51 +0000 |
commit | dec1e96ca07e2a9ae6ef626eed7d89d3a0ebed9b (patch) | |
tree | a76bbf27c4ffb041ab1cca25109da3564411d4f3 | |
parent | 7e4a5bba40e1ffb155d6192ec3e5edbd966716e6 (diff) | |
download | xmlgraphics-fop-dec1e96ca07e2a9ae6ef626eed7d89d3a0ebed9b.tar.gz xmlgraphics-fop-dec1e96ca07e2a9ae6ef626eed7d89d3a0ebed9b.zip |
First committed version
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@197850 13f79535-47bb-0310-9956-ffa450edef68
18 files changed, 8722 insertions, 0 deletions
diff --git a/src/documentation/content/xdocs/DnI/BookMaker.java b/src/documentation/content/xdocs/DnI/BookMaker.java new file mode 100644 index 000000000..91f730711 --- /dev/null +++ b/src/documentation/content/xdocs/DnI/BookMaker.java @@ -0,0 +1,334 @@ +/* + * Copyright 2004 The Apache Software Foundation. + * + * Licensed 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$ */ + +// Derived from examples/embedding/java/embedding/ExampleXML2PDF.java +// in FOP-0.20.5 + +//Java +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.io.FileInputStream; +import java.io.FileOutputStream; + +import java.util.Vector; + +//JAXP +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.TransformerException; +import javax.xml.transform.Source; +import javax.xml.transform.Result; +import javax.xml.transform.stream.StreamSource; +import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.sax.SAXSource; +import javax.xml.transform.sax.SAXResult; + +import javax.xml.parsers.SAXParserFactory; +import javax.xml.parsers.FactoryConfigurationError; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.ParserConfigurationException; + +// SAX +import org.xml.sax.InputSource; +import org.xml.sax.XMLReader; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; +import org.xml.sax.ErrorHandler; + +// XML Commons +import org.apache.xml.resolver.tools.CatalogResolver; + +import org.apache.commons.cli.Options; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.OptionGroup; +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.HelpFormatter; +import org.apache.commons.cli.Parser; +import org.apache.commons.cli.GnuParser; +import org.apache.commons.cli.ParseException; + +//Avalon +import org.apache.avalon.framework.ExceptionUtil; +import org.apache.avalon.framework.logger.ConsoleLogger; +import org.apache.avalon.framework.logger.Logger; + +//FOP +import org.apache.fop.apps.Driver; +import org.apache.fop.apps.FOPException; +import org.apache.fop.messaging.MessageHandler; + +/** + * This class converts an XML file to PDF using + * JAXP (XSLT) and FOP (XSL:FO). + */ +public class BookMaker implements ErrorHandler { + + private Logger logger; + + private File xmlFile, xsltFile, outFile, pdfFile; + private boolean useCatalog; + private Vector xsltParams = null; + + public BookMaker() { + //Setup logger + logger = new ConsoleLogger(ConsoleLogger.LEVEL_INFO); + } + + /** + * org.xml.sax.ErrorHandler#warning + **/ + public void warning(SAXParseException e) { + logger.warn(e.toString()); + } + + /** + * org.xml.sax.ErrorHandler#error + **/ + public void error(SAXParseException e) { + logger.error(e.toString()); + } + + /** + * org.xml.sax.ErrorHandler#fatalError + **/ + public void fatalError(SAXParseException e) throws SAXException { + logger.error(e.toString()); + throw e; + } + + public void makeBook() + throws IOException, FOPException, TransformerException, + FactoryConfigurationError, + ParserConfigurationException, SAXException { + + OutputStream out = null; + + try { + + Source xmlSource, xsltSource; + Result result; + CatalogResolver resolver = null; + + // Setup entity and URI resolver + if (useCatalog) { + resolver = new CatalogResolver(); + logger.info("Using " + resolver.getClass().getName() + + " as entity/URI resolver"); + } + + //Setup XSLT transformer + TransformerFactory tFactory = TransformerFactory.newInstance(); + if (useCatalog) { + tFactory.setURIResolver(resolver); + } + + //Setup input and xslt sources + if (useCatalog) { + + SAXParser parser; + XMLReader xmlReader; + FileInputStream fis; + InputSource is; + + // throws FactoryConfigurationError + SAXParserFactory sFactory = SAXParserFactory.newInstance(); + sFactory.setNamespaceAware(true); + + // Setup input source + // throws ParserConfigurationException + parser = sFactory.newSAXParser(); + // throws SAXException + xmlReader = parser.getXMLReader(); + logger.info("Using " + xmlReader.getClass().getName() + + " as SAX parser"); + xmlReader.setErrorHandler(this); + xmlReader.setEntityResolver(resolver); + + // Setup SAX source + fis = new FileInputStream(xmlFile); + is = new InputSource(fis); + xmlSource = new SAXSource(xmlReader, is); + + // Setup xslt source + // throws ParserConfigurationException + parser = sFactory.newSAXParser(); + // throws SAXException + xmlReader = parser.getXMLReader(); + logger.info("Using " + xmlReader.getClass().getName() + + " as SAX parser"); + xmlReader.setErrorHandler(this); + xmlReader.setEntityResolver(resolver); + + // Setup SAX source + fis = new FileInputStream(xsltFile); + is = new InputSource(fis); + xsltSource = new SAXSource(xmlReader, is); + + } else { + xmlSource = new StreamSource(xmlFile); + xsltSource = new StreamSource(xsltFile); + } + + // Setup output result + if (pdfFile != null) { + //Setup FOP + MessageHandler.setScreenLogger(logger); + Driver driver = new Driver(); + driver.setLogger(logger); + driver.setRenderer(Driver.RENDER_PDF); + out = new FileOutputStream(pdfFile); + driver.setOutputStream(out); + //Resulting SAX events (the generated FO) + // must be piped through to FOP + result = new SAXResult(driver.getContentHandler()); + } else { + out = new FileOutputStream(outFile); + result = new StreamResult(out); + } + + // Setup the transformer + Transformer transformer + = tFactory.newTransformer(xsltSource); + logger.info("Using " + transformer.getClass().getName() + + " as TrAX transformer"); + + // Set the value of parameters, if any, defined for stylesheet + if (xsltParams != null) { + for (int i = 0; i < xsltParams.size(); i += 2) { + transformer.setParameter + ((String) xsltParams.elementAt(i), + (String) xsltParams.elementAt(i + 1)); + } + } + + //Start XSLT transformation and FOP processing + transformer.transform(xmlSource, result); + + } finally { + if (out != null) { + out.close(); + } + } + } + + private static Options createOptions() { + + Options options = new Options(); + OptionGroup og; + Option o; + + o = new Option("h", "help", false, "Print help"); + options.addOption(o); + + o = new Option("c", "useCatalog", false, "Use catalog"); + options.addOption(o); + + o = new Option("xml", "xmlFile", true, "XML input file"); + o.setArgName("file"); + options.addOption(o); + + o = new Option("xsl", "xslFile", true, "XSLT stylesheet"); + o.setArgName("file"); + options.addOption(o); + + // mutually exclusive output options + og = new OptionGroup(); + o = new Option("out", "outFile", true, "(X)HTML/FO output file"); + o.setArgName("file"); + og.addOption(o); + + o = new Option("pdf", "pdfFile", true, "PDF output file"); + o.setArgName("file"); + og.addOption(o); + + options.addOptionGroup(og); + + o = new Option("p", "parameter", true, + "Parameter for the XSLT transformation"); + o.setArgs(2); + o.setArgName("name value"); + options.addOption(o); + + return options; + } + + public static void main(String[] args) { + + BookMaker app = new BookMaker(); + + try { + + // Setup options + Options options = createOptions(); + + // Parse command line + // GNU parser allow multi-letter short options + Parser parser = new GnuParser(); + CommandLine cl = null; + cl = parser.parse(options, args); + if (cl.hasOption("h")) { + // automatically generate the help statement + HelpFormatter formatter = new HelpFormatter(); + formatter.printHelp("BookMaker", options); + System.exit(0); + } + + //Setup input and output files and parameters + if (cl.hasOption("c")) { + app.useCatalog = true; + } + if (cl.hasOption("xml")) { + app.xmlFile = new File(cl.getOptionValue("xml")); + } + if (cl.hasOption("xsl")) { + app.xsltFile = new File(cl.getOptionValue("xsl")); + } + if (cl.hasOption("out")) { + app.outFile = new File(cl.getOptionValue("out")); + } + if (cl.hasOption("pdf")) { + app.pdfFile = new File(cl.getOptionValue("pdf")); + } + if (cl.hasOption("p")) { + String[] params = cl.getOptionValues("p"); + app.xsltParams = new Vector(); + for (int i = 0; i < params.length; ++i) { + app.xsltParams.addElement(params[i]); + } + } + + app.logger.info("Input: XML (" + app.xmlFile + ")"); + app.logger.info("Stylesheet: " + app.xsltFile); + if (app.pdfFile != null) { + app.logger.info("Output: PDF (" + app.pdfFile + ")"); + } else { + app.logger.info("Output: (X)HTML/FO (" + app.outFile + ")"); + } + app.logger.info(""); + app.logger.info("Transforming..."); + + app.makeBook(); + + app.logger.info("Transforming done"); + } catch (Exception e) { + app.logger.error(ExceptionUtil.printStackTrace(e)); + System.exit(1); + } + } +} diff --git a/src/documentation/content/xdocs/DnI/Makefile b/src/documentation/content/xdocs/DnI/Makefile new file mode 100644 index 000000000..98014017f --- /dev/null +++ b/src/documentation/content/xdocs/DnI/Makefile @@ -0,0 +1,126 @@ +# Copyright 2004 The Apache Software Foundation. +# +# Licensed 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$ + +BOOK=book.xml +CHAPTERS=addareas.xml areatree.xml configuration.xml fonts.xml \ + foptrees.xml fotree.xml getnextbreakposs.xml overview.xml \ + preparation.xml properties.xml rendering.xml +CUSTOM_DOCBOOK_XHTML_STYLESHEET=cust-xhtml-docbook.xsl +CUSTOM_DOCBOOK_HTML_STYLESHEET=cust-html-docbook.xsl +CUSTOM_DOCBOOK_FO_STYLESHEET=cust-fo-docbook.xsl +STYLESHEETS=$(CUSTOM_DOCBOOK_XHTML_STYLESHEET) \ + $(CUSTOM_DOCBOOK_HTML_STYLESHEET) \ + $(CUSTOM_DOCBOOK_FO_STYLESHEET) +BOOKMAKER=BookMaker.java + +# destinations +BUILD_DIR=../../../../../build/ +BOOKMAKERCLASSPATH=$(BUILD_DIR)/classes +BOOKMAKER_CLASS=$(BOOKMAKERCLASSPATH)/BookMaker.class +DNI_BUILD_DIR=$(BUILD_DIR)/site/DnI +XHTML_DIR=$(DNI_BUILD_DIR)/xhtml +HTML_DIR=$(DNI_BUILD_DIR)/html +PDF_DIR=$(DNI_BUILD_DIR) + +JAVACLASSES=/usr/local/javaclasses +FOPCLASSPATH=$(JAVACLASSES)/fop-0.20.5.jar +AVALONCLASSPATH=$(JAVACLASSES)/avalon-framework-cvs-20020806.jar +SAXONCLASSPATH=$(JAVACLASSES)/saxon.jar +RESOLVERCLASSPATH=$(JAVACLASSES)/endorsed/resolver-xml-commons.jar +XERCESCLASSPATH=$(JAVACLASSES)/endorsed/xml-apis.jar:$(JAVACLASSES)/endorsed/xercesImpl.jar +CLICLASSPATH=$(JAVACLASSES)/commons-cli-1.0.jar + +all: xhtml html pdf + +xhtml: $(XHTML_DIR)/book-xhtml.xml +html: $(HTML_DIR)/book.html +fo: $(PDF_DIR)/book.fo +pdf: $(PDF_DIR)/book.pdf + +$(XHTML_DIR)/book-xhtml.xml: $(BOOK) $(CHAPTERS) $(CUSTOM_DOCBOOK_XHTML_STYLESHEET) $(BOOKMAKER_CLASS) + [ -d $(XHTML_DIR) ] || mkdir -p $(XHTML_DIR) + java $(JAVAFLAGS) \ + -classpath $(XERCESCLASSPATH):$(SAXONCLASSPATH):$(AVALONCLASSPATH):$(RESOLVERCLASSPATH):$(CLICLASSPATH):$(BOOKMAKERCLASSPATH):$(CLASSPATH) \ + BookMaker $(PROGOPTS) --parameter base.dir $(XHTML_DIR)/ -xml $< -xsl $(CUSTOM_DOCBOOK_XHTML_STYLESHEET) -out $@ + +$(HTML_DIR)/book.html: $(BOOK) $(CHAPTERS) $(CUSTOM_DOCBOOK_HTML_STYLESHEET) $(BOOKMAKER_CLASS) + [ -d $(HTML_DIR) ] || mkdir -p $(HTML_DIR) + java $(JAVAFLAGS) \ + -classpath $(XERCESCLASSPATH):$(SAXONCLASSPATH):$(AVALONCLASSPATH):$(RESOLVERCLASSPATH):$(CLICLASSPATH):$(BOOKMAKERCLASSPATH):$(CLASSPATH) \ + BookMaker $(PROGOPTS) --parameter base.dir $(HTML_DIR)/ -xml $< -xsl $(CUSTOM_DOCBOOK_HTML_STYLESHEET) -out $@ + +$(PDF_DIR)/book.fo: $(BOOK) $(CHAPTERS) $(CUSTOM_DOCBOOK_FO_STYLESHEET) $(BOOKMAKER_CLASS) + [ -d $(PDF_DIR) ] || mkdir -p $(PDF_DIR) + java $(JAVAFLAGS) \ + -classpath $(XERCESCLASSPATH):$(SAXONCLASSPATH):$(AVALONCLASSPATH):$(RESOLVERCLASSPATH):$(CLICLASSPATH):$(BOOKMAKERCLASSPATH):$(CLASSPATH) \ + BookMaker $(PROGOPTS) -xml $< -xsl $(CUSTOM_DOCBOOK_FO_STYLESHEET) -out $@ + +$(PDF_DIR)/book.pdf: $(BOOK) $(CHAPTERS) $(CUSTOM_DOCBOOK_FO_STYLESHEET) $(BOOKMAKER_CLASS) + [ -d $(PDF_DIR) ] || mkdir -p $(PDF_DIR) + java $(JAVAFLAGS) \ + -classpath $(XERCESCLASSPATH):$(SAXONCLASSPATH):$(FOPCLASSPATH):$(AVALONCLASSPATH):$(RESOLVERCLASSPATH):$(CLICLASSPATH):$(BOOKMAKERCLASSPATH):$(CLASSPATH) \ + BookMaker $(PROGOPTS) -xml $< -xsl $(CUSTOM_DOCBOOK_FO_STYLESHEET) -pdf $@ + +$(BOOKMAKERCLASSPATH)/%.class: %.java + [ -d $(BOOKMAKERCLASSPATH) ] || mkdir -p $(BOOKMAKERCLASSPATH) + javac -classpath $(FOPCLASSPATH):$(AVALONCLASSPATH):$(RESOLVERCLASSPATH):$(CLICLASSPATH):$(CLASSPATH) \ + -d $(BOOKMAKERCLASSPATH) $< + +############################ distribution file ######################### + +CURRENT_DIR=documentation + +zip: documentation.zip + +documentation.zip: $(BOOK) $(CHAPTERS) $(STYLESHEETS) $(BOOKMAKER) Makefile README + -rm -f $@ + cd .. && zip $(CURRENT_DIR)/$@ ${^:%=$(CURRENT_DIR)/%} + +############################ test section ############################### + +TEST=test.xml +TEST_CHAPTERS=getnextbreakposs.xml overview.xml + +test-saxon.html: $(TEST) $(TEST_CHAPTERS) $(CUSTOM_DOCBOOK_HTML_STYLESHEET) $(BOOKMAKER_CLASS) + java $(JAVAFLAGS) -classpath $(XERCESCLASSPATH):$(SAXONCLASSPATH):$(AVALONCLASSPATH):$(RESOLVERCLASSPATH):$(CLICLASSPATH):$(BOOKMAKERCLASSPATH):$(CLASSPATH) BookMaker $(PROGOPTS) --parameter base.dir $(HTML_DIR)/ -xml $< -xsl $(CUSTOM_DOCBOOK_HTML_STYLESHEET) -out $@ + +test-saxon.xhtml: $(TEST) $(TEST_CHAPTERS) $(CUSTOM_DOCBOOK_XHTML_STYLESHEET) $(BOOKMAKER_CLASS) + java $(JAVAFLAGS) -classpath $(XERCESCLASSPATH):$(SAXONCLASSPATH):$(AVALONCLASSPATH):$(RESOLVERCLASSPATH):$(CLICLASSPATH):$(BOOKMAKERCLASSPATH):$(CLASSPATH) BookMaker $(PROGOPTS) --parameter base.dir $(XHTML_DIR)/ -xml $< -xsl $(CUSTOM_DOCBOOK_XHTML_STYLESHEET) -out $@ + +test-saxon.fo: $(TEST) $(TEST_CHAPTERS) $(CUSTOM_DOCBOOK_FO_STYLESHEET) $(BOOKMAKER_CLASS) + java $(JAVAFLAGS) -classpath $(XERCESCLASSPATH):$(SAXONCLASSPATH):$(AVALONCLASSPATH):$(RESOLVERCLASSPATH):$(CLICLASSPATH):$(BOOKMAKERCLASSPATH):$(CLASSPATH) BookMaker $(PROGOPTS) -xml $< -xsl $(CUSTOM_DOCBOOK_FO_STYLESHEET) -out $@ + +test-saxon.pdf: $(TEST) $(TEST_CHAPTERS) $(CUSTOM_DOCBOOK_FO_STYLESHEET) $(BOOKMAKER_CLASS) + java $(JAVAFLAGS) -classpath $(XERCESCLASSPATH):$(SAXONCLASSPATH):$(FOPCLASSPATH):$(AVALONCLASSPATH):$(RESOLVERCLASSPATH):$(CLICLASSPATH):$(BOOKMAKERCLASSPATH):$(CLASSPATH) BookMaker $(PROGOPTS) -xml $< -xsl $(CUSTOM_DOCBOOK_FO_STYLESHEET) -pdf $@ + +test-saxon-stf.pdf: $(TEST) $(TEST_CHAPTERS) $(CUSTOM_DOCBOOK_FO_STYLESHEET) $(BOOKMAKER_CLASS) + java $(JAVAFLAGS) -classpath $(XERCESCLASSPATH):$(SAXONCLASSPATH):$(FOPCLASSPATH):$(AVALONCLASSPATH):$(RESOLVERCLASSPATH):$(CLICLASSPATH):$(BOOKMAKERCLASSPATH):$(CLASSPATH) XML2PDF_STF $(PROGOPTS) -xml $< -xsl $(CUSTOM_DOCBOOK_FO_STYLESHEET) -pdf $@ + +test-xalan.html: $(TEST) $(TEST_CHAPTERS) $(CUSTOM_DOCBOOK_HTML_STYLESHEET) $(BOOKMAKER_CLASS) + java $(JAVAFLAGS) -classpath $(FOPCLASSPATH):$(AVALONCLASSPATH):$(RESOLVERCLASSPATH):$(CLICLASSPATH):$(BOOKMAKERCLASSPATH):$(CLASSPATH) BookMaker $(PROGOPTS) --parameter base.dir $(HTML_DIR)/ -xml $< -xsl $(CUSTOM_DOCBOOK_HTML_STYLESHEET) -out $@ + +test-xalan.xhtml: $(TEST) $(TEST_CHAPTERS) $(CUSTOM_DOCBOOK_XHTML_STYLESHEET) $(BOOKMAKER_CLASS) + java $(JAVAFLAGS) -classpath $(FOPCLASSPATH):$(AVALONCLASSPATH):$(RESOLVERCLASSPATH):$(CLICLASSPATH):$(BOOKMAKERCLASSPATH):$(CLASSPATH) BookMaker $(PROGOPTS) --parameter base.dir $(XHTML_DIR)/ -xml $< -xsl $(CUSTOM_DOCBOOK_XHTML_STYLESHEET) -out $@ + +test-xalan.fo: $(TEST) $(TEST_CHAPTERS) $(CUSTOM_DOCBOOK_FO_STYLESHEET) $(BOOKMAKER_CLASS) + java $(JAVAFLAGS) -classpath $(FOPCLASSPATH):$(AVALONCLASSPATH):$(RESOLVERCLASSPATH):$(CLICLASSPATH):$(BOOKMAKERCLASSPATH):$(CLASSPATH) BookMaker $(PROGOPTS) -xml $< -xsl $(CUSTOM_DOCBOOK_FO_STYLESHEET) -out $@ + +test-xalan.pdf: $(TEST) $(TEST_CHAPTERS) $(CUSTOM_DOCBOOK_FO_STYLESHEET) $(BOOKMAKER_CLASS) + java $(JAVAFLAGS) -classpath $(FOPCLASSPATH):$(AVALONCLASSPATH):$(RESOLVERCLASSPATH):$(CLICLASSPATH):$(BOOKMAKERCLASSPATH):$(CLASSPATH) BookMaker $(PROGOPTS) -xml $< -xsl $(CUSTOM_DOCBOOK_FO_STYLESHEET) -pdf $@ + +test-xalan-stf.pdf: $(TEST) $(TEST_CHAPTERS) $(CUSTOM_DOCBOOK_FO_STYLESHEET) $(BOOKMAKER_CLASS) + java $(JAVAFLAGS) -classpath $(FOPCLASSPATH):$(AVALONCLASSPATH):$(RESOLVERCLASSPATH):$(CLICLASSPATH):$(BOOKMAKERCLASSPATH):$(CLASSPATH) XML2PDF_STF $(PROGOPTS) -xml $< -xsl $(CUSTOM_DOCBOOK_FO_STYLESHEET) -pdf $@ + diff --git a/src/documentation/content/xdocs/DnI/README b/src/documentation/content/xdocs/DnI/README new file mode 100644 index 000000000..9138da809 --- /dev/null +++ b/src/documentation/content/xdocs/DnI/README @@ -0,0 +1,77 @@ +Readme for `FOP's design and implementation' + +This directory contains the documentation entitled `FOP's design and +implementation'. + +The book is structured according to the Docbook XML DTD version 4.2, +top-level element book. + +The top level file is book.xml. It calls in the various chapter files. + +The book can be converted to XHTML, HTML and FO using the Docbook XSL +stylesheets. For each of these formats there are customization XSL +stylesheets, which should be called as the main stylesheet of the +conversion. The customization stylesheets were written against version +1.64.1. The customization for FO is rather heavy, and may prove +incompatible with later versions of the docbook stylesheets. Of +course, you can always convert without the customization or with your +own customization. The changes will only affect the layout, not the +content of the book. + +The customization stylesheets for XHTML and HTML use the ability of +the docbook stylesheets to write the resulting files in chunks. It +makes sense to send the conversion result into a separate +directory. If you make both conversions, you must send them to +different directories, as they produce files of the same name. You can +produce the result in a single file by making a small change at the +top of the customization stylesheets: import the stylesheet +docbook.xsl instead of chunk.xsl. + +For the XHTML and HTML conversions I have obtained the best conversion +results using Saxon. I have used FOP-0.20.5 for FO Processor. + +The top-level file assumes that the docbook DTD files are located in +`http://www.oasis-open.org/docbook/xml/4.2/'. The customization +stylesheets assume that the docbook stylesheets are located in +`http://cvs.sourceforge.net/viewcvs.py/*checkout*/docbook/xsl/'. I am +not quite sure if the latter URL is correct. If you want to use local +files from your XML installation, you must change these paths at the +top of the top-level XML file and of each customization stylesheet. +Alternatively, you can use catalog entries to map the Public ID for +the Docbook DTD and the system id of the docbook XSL stylesheets to +your local paths. + +You can use the included java class BookMaker to generate the various +forms of the documentation. Note that it requires the Jakarta Commons +CLI package. Call BookMaker with the option '--help' to get a short +overview of its usage. Use the included Makefile, or learn from it how +the BookMaker class can be called. If you use the Makefile, you must +edit the class paths to reflect your java setup. Set the environment +variable PROGOPTS=--useCatalog if you want to use a catalog. I have +better results with Xerces and the catalog resolver; therefore Xerces +is placed before Saxon in the class paths. + +If you do not use a catalog, you can also use Saxon and FOP from the +command line. The following are typical invocations. Here the +classpaths have obvious meanings. JAVAFLAGS are any other options for +java, possibly none. + +java $JAVAFLAGS -cp "$SAXONCLASSPATH:$CLASSPATH" \ + com.icl.saxon.StyleSheet \ + -o ../documentation-xhtml/book-xhtml.xml \ + book.xml cust-xhtml-docbook.xsl + +java $JAVAFLAGS -cp "$SAXONCLASSPATH:$CLASSPATH" \ + com.icl.saxon.StyleSheet \ + -o ../documentation-html/book.html \ + book.xml cust-html-docbook.xsl + +java $JAVAFLAGS \ + -cp $SAXONCLASSPATH:$FOPCLASSPATH:$AVALONCLASSPATH:$CLASSPATH \ + org.apache.fop.apps.Fop \ + -xml book.xml -xsl cust-html-docbook.xsl -pdf book.pdf + +I will try to construct an ant build file and an XML catalog which +make conversion with your own XML and Java system easier. + +$Id$ diff --git a/src/documentation/content/xdocs/DnI/addareas.xml b/src/documentation/content/xdocs/DnI/addareas.xml new file mode 100644 index 000000000..9ceb4ff49 --- /dev/null +++ b/src/documentation/content/xdocs/DnI/addareas.xml @@ -0,0 +1,971 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * Copyright 2004 The Apache Software Foundation. + * + * Licensed 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$ --> + +<!-- +<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" + "docbookx.dtd"> + --> + + <chapter> + <title>Phase 2b: The <literal>addAreas</literal> call tree</title> + + <section> + <title>Overview</title> + + <para>This section presents a verbose overview of the +<literal>addAreas</literal> call tree. The following section presents +the Layout Managers in more detail.</para> + + <itemizedlist> + + <listitem> + <simpara>FlowLM receives from its parent LM an iterator with a +single pagebreak. The first belongs to BlockLM1, the second belongs to +BlockLM2. FlowLM itself holds 2 child BPs. The flow consists of two +blocks. FlowLM sets up an iterator with its 2 BPs.</simpara> + </listitem> + + <listitem> + <simpara>BlockLM1 receives from its parent LM the iterator +with those 2 BPs, of which only the first one belongs to it. Its leaf +position is 13. BlockLM itself holds 14 child BPs, which all belong to +a single LineLM. The block consists of 14 lines. BlockLM sets up an +iterator corresponding to the first BP, containing the child BPs +0–13.</simpara> + </listitem> + + <listitem> + <simpara>LineLM receives from its parent LM an iterator with +those 14 BPs. The leaf positions are 3, 6, 11, 12, 13, 16, 19, 21, 23, +24, 25, 26, 27, 28. LineLM itself holds 29 child BPs, which all belong +to a single TextLM. LineLM maintains the position of the next BP in +<literal>vecInlineBreaks</literal>, <literal>iStartPos</literal>. +Initially it is set to 0. For each of its 14 BPs in the iterator, +LineLM sets up an iterator with the child BPs in +<literal>vecInlineBreaks</literal> from <literal>iStartPos</literal> +up to an including the index <literal>iLeafPos</literal> to which the +iterator BP points. Then it <literal>updates</literal> iStartPos to +point to the next child BP. The iterators contain the child BP ranges: +0–3, 4–6, 7–11, 12, 13, 14–16, 17–19, 20–21, 22–23, 24, 25, 26, 27, +28.</simpara> + + <screen>while (parentIter.hasNext()) { + LineBreakPosition lbp = (LineBreakPosition) parentIter.next(); + ... + PositionIterator inlinePosIter = + new BreakPossPosIter(vecInlineBreaks, iStartPos, + lbp.getLeafPos() + 1); + iStartPos = lbp.getLeafPos() + 1; + ... + while ((childLM = inlinePosIter.getNextChildLM()) != null) { + childLM.addAreas(inlinePosIter, lc); + ... + } + ... +} +</screen> + </listitem> + + <listitem> +<simpara>TextLM receives from its parent LM an iterator with the BPs +0–3. The leaf positions are 0, 1, 2, 3. It has itself 47 items in +<literal>vecAreaInfo</literal>. It iterates over the 4 corresponding +AIs, records the start of the first one, counts the word spaces, and +records the end of the last one. This line contains the characters +from 0 up to 13 and has no word spaces.</simpara> + </listitem> + + <listitem> + <simpara>TextLM receives from its parent LM an iterator with +the BPs 4–6. The leaf positions are 5, 7, 8. It iterates over the +three corresponding AIs. This line contains the characters from 13 up +to 26 and has one word space. Note that the AIs 4 and 6 remain unused +because they do not have a corresponding BP. These AIs represent areas +that were too long, and over which the LM backed up.</simpara> + </listitem> + + <listitem> + <simpara>TextLM receives from its parent LM an iterator with +the BPs 7–11. The leaf positions are 11, 12, 13, 14, 15. It iterates +over the five corresponding AIs. This line contains the characters +from 26 up to 40 and has no word spaces. Note that the AIs 9 and 10 +remain unused because they do not have a corresponding BP.</simpara> + </listitem> + + <listitem> + <simpara>TextLM receives from its parent LM an iterator with +the single BP 12. The leaf position is 16. This line contains the +characters from 40 up to 42 and has no word spaces.</simpara> + </listitem> + + <listitem> + <simpara>TextLM receives from its parent LM an iterator with +the single BP 13. The leaf position is 18. This line contains the +characters from 43 up to 60 and has no word spaces. Note that the AI +17 remains unused because it does not have a corresponding BP. Note +also that character 42 has been dropped, because it would be a leading +space.</simpara> + </listitem> + + <listitem> + <simpara>etc. until all 14 line areas are done. LineLM +returns.</simpara> + </listitem> + + <listitem> + <simpara>The second BP in the iterator from FlowLM belongs to +BlockLM2. The loop <literal>while (parentIter.hasNext())</literal> +ends because the LM of the next object is different from the current +LM (<literal>BreakPossPosIter.checkNext()</literal>), and BlockLM1 +returns. FlowLM's loop <literal>while ((childLM = +breakPosIter.getNextChildLM()) != null)</literal> then passes the +iterator to BlockLM2.</simpara> + </listitem> + + <listitem> + <simpara>BlockLM2 receives from its parent LM the iterator with those 2 +BPs. The cursor is at one, because BlockLM1 has used the first object. +Only the second BP belongs to BlockLM2. Its leaf position is +0. BlockLM itself holds 1 child BP, belonging to a LineLM. The block +consists of a single line. BlockLM sets up an iterator corresponding +to the second BP, containing a single child BP.</simpara> + </listitem> + + <listitem> +<simpara>LineLM receives from its parent LM an iterator with that BP. +The leaf position is 1. LineLM itself holds 2 child BPs, one belonging +to a TextLM, the other to <literal>AddLMVisitor$2</literal>. LineLM +sets up an iterator corresponding to the BP, containing its two child +BPs.</simpara> + </listitem> + + <listitem> +<simpara>TextLM receives from its parent LM an iterator with the BPs 0 +and 1, of which only the first belongs to it. Its leaf position is 0. +It iterates over the corresponding AI. This text area contains the +characters from 0 up to 1, i.e. <literal>" "</literal>, and has one +word space. This converted to a space area.</simpara> + </listitem> + + <listitem> + <simpara><literal>AddLMVisitor$2</literal> receives from its +parent LM an iterator with the BPs 0 and 1. The cursor is at one, +because TextLM has used the first object. Only the second BP belongs +to <literal>AddLMVisitor$2</literal>. Its leaf position is +0.</simpara> + </listitem> + + <listitem> + <simpara>This completes the line. LineLM returns.</simpara> + </listitem> + + <listitem> + <simpara>BlockLM2 returns.</simpara> + </listitem> + + <listitem> + <simpara>FlowLM returns.</simpara> + </listitem> + </itemizedlist> + + </section> + + <section> + <title>Detailed overviews</title> + + <section> + <title>PageLM</title> + +<screen> + bbp = { + breakps: instance of org.apache.fop.layoutmgr.BreakPoss(id=1167) + org.apache.fop.layoutmgr.LeafPosition.iLeafPos: 0 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.FlowLayoutManager(id=1169) +} + + bbp.breakps.position = { + iLeafPos: 1 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.FlowLayoutManager(id=1169) +} + + list = "[org.apache.fop.layoutmgr.BreakPoss@1aa2c23]" + + list.get(0).position = { + iLeafPos: 1 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.FlowLayoutManager(id=1169) +} + + list.get(0).position.layoutManager = "org.apache.fop.layoutmgr.FlowLayoutManager@6963d0" +</screen> + </section> + + <section> + <title>FlowLM</title> + +<screen> + this = "org.apache.fop.layoutmgr.FlowLayoutManager@6963d0" + + lfp = { + iLeafPos: 1 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.FlowLayoutManager(id=1169) +} + + iStartPos = 0 + + blockBreaks = "[org.apache.fop.layoutmgr.BreakPoss@111bfbc, org.apache.fop.layoutmgr.BreakPoss@4310d0]" + + blockBreaks.get(iStartPos).position = { + iLeafPos: 13 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.BlockLayoutManager(id=1183) +} + + blockBreaks.get(iStartPos).position.layoutManager = "org.apache.fop.layoutmgr.BlockLayoutManager@19e09a4" + + blockBreaks.get(iStartPos+1).position = { + iLeafPos: 0 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.BlockLayoutManager(id=1186) +} + + blockBreaks.get(iStartPos+1).position.layoutManager = "org.apache.fop.layoutmgr.BlockLayoutManager@144b18f" +</screen> + </section> + + <section> + <title>BlockLM1</title> + +<screen> + this = "org.apache.fop.layoutmgr.BlockLayoutManager@19e09a4" + + lfp = { + iLeafPos: 13 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.BlockLayoutManager(id=1183) +} + + iStartPos = 0 + + childBreaks = "[ +org.apache.fop.layoutmgr.BreakPoss@2b249, +org.apache.fop.layoutmgr.BreakPoss@106daba, +org.apache.fop.layoutmgr.BreakPoss@1021f34, +org.apache.fop.layoutmgr.BreakPoss@4eb043, +org.apache.fop.layoutmgr.BreakPoss@163956, +org.apache.fop.layoutmgr.BreakPoss@10e434d, +org.apache.fop.layoutmgr.BreakPoss@16477d9, +org.apache.fop.layoutmgr.BreakPoss@f864fe, +org.apache.fop.layoutmgr.BreakPoss@1ae9aaa, +org.apache.fop.layoutmgr.BreakPoss@2c17f7, +org.apache.fop.layoutmgr.BreakPoss@d9896e, +org.apache.fop.layoutmgr.BreakPoss@1cda59b, +org.apache.fop.layoutmgr.BreakPoss@33788d, +org.apache.fop.layoutmgr.BreakPoss@12fb0af +]" + + childBreaks.get(0).position = { + dAdjust: 0.0 + ipdAdjust: 1.0 + startIndent: 0 + lineHeight: 19200 + baseline: 17000 + org.apache.fop.layoutmgr.LeafPosition.iLeafPos: 3 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.LineLayoutManager(id=1199) +} + + childBreaks.get(0).position.layoutManager = "org.apache.fop.layoutmgr.LineLayoutManager@c06258" + + childBreaks.get(1).position = { + dAdjust: 0.0 + ipdAdjust: 1.0 + startIndent: 0 + lineHeight: 19200 + baseline: 17000 + org.apache.fop.layoutmgr.LeafPosition.iLeafPos: 6 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.LineLayoutManager(id=1199) +} + + childBreaks.get(1).position.layoutManager = "org.apache.fop.layoutmgr.LineLayoutManager@c06258" + + childBreaks.get(2).position = { + dAdjust: 0.0 + ipdAdjust: 1.0 + startIndent: 0 + lineHeight: 19200 + baseline: 17000 + org.apache.fop.layoutmgr.LeafPosition.iLeafPos: 11 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.LineLayoutManager(id=1199) +} + + childBreaks.get(2).position.layoutManager = "org.apache.fop.layoutmgr.LineLayoutManager@c06258" + + childBreaks.get(3).position = { + dAdjust: 7.0 + ipdAdjust: 1.0 + startIndent: 0 + lineHeight: 19200 + baseline: 17000 + org.apache.fop.layoutmgr.LeafPosition.iLeafPos: 12 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.LineLayoutManager(id=1199) +} + + childBreaks.get(3).position.layoutManager = "org.apache.fop.layoutmgr.LineLayoutManager@c06258" + + childBreaks.get(4).position = { + dAdjust: 0.0 + ipdAdjust: -1.0 + startIndent: 0 + lineHeight: 19200 + baseline: 17000 + org.apache.fop.layoutmgr.LeafPosition.iLeafPos: 13 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.LineLayoutManager(id=1199) +} + + childBreaks.get(4).position.layoutManager = "org.apache.fop.layoutmgr.LineLayoutManager@c06258" + + childBreaks.get(5).position = { + dAdjust: 0.0 + ipdAdjust: 1.0 + startIndent: 0 + lineHeight: 19200 + baseline: 17000 + org.apache.fop.layoutmgr.LeafPosition.iLeafPos: 16 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.LineLayoutManager(id=1199) +} + + childBreaks.get(5).position.layoutManager = "org.apache.fop.layoutmgr.LineLayoutManager@c06258" + + childBreaks.get(6).position = { + dAdjust: 0.0 + ipdAdjust: 1.0 + startIndent: 0 + lineHeight: 19200 + baseline: 17000 + org.apache.fop.layoutmgr.LeafPosition.iLeafPos: 19 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.LineLayoutManager(id=1199) +} + + childBreaks.get(6).position.layoutManager = "org.apache.fop.layoutmgr.LineLayoutManager@c06258" + + childBreaks.get(7).position = { + dAdjust: 0.0 + ipdAdjust: 1.0 + startIndent: 0 + lineHeight: 19200 + baseline: 17000 + org.apache.fop.layoutmgr.LeafPosition.iLeafPos: 21 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.LineLayoutManager(id=1199) +} + + childBreaks.get(7).position.layoutManager = "org.apache.fop.layoutmgr.LineLayoutManager@c06258" + + childBreaks.get(8).position = { + dAdjust: 0.0 + ipdAdjust: 1.0 + startIndent: 0 + lineHeight: 19200 + baseline: 17000 + org.apache.fop.layoutmgr.LeafPosition.iLeafPos: 23 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.LineLayoutManager(id=1199) +} + + childBreaks.get(8).position.layoutManager = "org.apache.fop.layoutmgr.LineLayoutManager@c06258" + + childBreaks.get(9).position = { + dAdjust: 0.0 + ipdAdjust: 1.0 + startIndent: 0 + lineHeight: 19200 + baseline: 17000 + org.apache.fop.layoutmgr.LeafPosition.iLeafPos: 24 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.LineLayoutManager(id=1199) +} + + childBreaks.get(9).position.layoutManager = "org.apache.fop.layoutmgr.LineLayoutManager@c06258" + + childBreaks.get(10).position = { + dAdjust: 0.0 + ipdAdjust: 1.0 + startIndent: 0 + lineHeight: 19200 + baseline: 17000 + org.apache.fop.layoutmgr.LeafPosition.iLeafPos: 25 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.LineLayoutManager(id=1199) +} + + childBreaks.get(10).position.layoutManager = "org.apache.fop.layoutmgr.LineLayoutManager@c06258" + + childBreaks.get(11).position = { + dAdjust: 0.0 + ipdAdjust: 1.0 + startIndent: 0 + lineHeight: 19200 + baseline: 17000 + org.apache.fop.layoutmgr.LeafPosition.iLeafPos: 26 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.LineLayoutManager(id=1199) +} + + childBreaks.get(11).position.layoutManager = "org.apache.fop.layoutmgr.LineLayoutManager@c06258" + + childBreaks.get(12).position = { + dAdjust: 0.0 + ipdAdjust: 1.0 + startIndent: 0 + lineHeight: 19200 + baseline: 17000 + org.apache.fop.layoutmgr.LeafPosition.iLeafPos: 27 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.LineLayoutManager(id=1199) +} + + childBreaks.get(12).position.layoutManager = "org.apache.fop.layoutmgr.LineLayoutManager@c06258" + + childBreaks.get(13).position = { + dAdjust: 0.0 + ipdAdjust: 1.0 + startIndent: 0 + lineHeight: 19200 + baseline: 17000 + org.apache.fop.layoutmgr.LeafPosition.iLeafPos: 28 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.LineLayoutManager(id=1199) +} + + childBreaks.get(13).position.layoutManager = "org.apache.fop.layoutmgr.LineLayoutManager@c06258" +</screen> + </section> + + <section> + <title>LineLM</title> + +<screen> + this = "org.apache.fop.layoutmgr.LineLayoutManager@c06258" + + lbp = { + dAdjust: 0.0 + ipdAdjust: 1.0 + startIndent: 0 + lineHeight: 19200 + baseline: 17000 + org.apache.fop.layoutmgr.LeafPosition.iLeafPos: 3 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.LineLayoutManager(id=1199) +} + + iStartPos = 0 + + vecInlineBreaks = "[ +org.apache.fop.layoutmgr.BreakPoss@17e4dee, +org.apache.fop.layoutmgr.BreakPoss@12e7c6a, +org.apache.fop.layoutmgr.BreakPoss@ea5461, +org.apache.fop.layoutmgr.BreakPoss@49cf9f, +org.apache.fop.layoutmgr.BreakPoss@1de0b5e, +org.apache.fop.layoutmgr.BreakPoss@bc5596, +org.apache.fop.layoutmgr.BreakPoss@970c0e, +org.apache.fop.layoutmgr.BreakPoss@987197, +org.apache.fop.layoutmgr.BreakPoss@497904, +org.apache.fop.layoutmgr.BreakPoss@1a7f9dc, +org.apache.fop.layoutmgr.BreakPoss@104e28b, +org.apache.fop.layoutmgr.BreakPoss@1b54362, +org.apache.fop.layoutmgr.BreakPoss@15b0e2c, +org.apache.fop.layoutmgr.BreakPoss@ff9053, +org.apache.fop.layoutmgr.BreakPoss@5c7734, +org.apache.fop.layoutmgr.BreakPoss@96212a, +org.apache.fop.layoutmgr.BreakPoss@5b675e, +org.apache.fop.layoutmgr.BreakPoss@df83e5, +org.apache.fop.layoutmgr.BreakPoss@4c6320, +org.apache.fop.layoutmgr.BreakPoss@ffd135, +org.apache.fop.layoutmgr.BreakPoss@1000bcf, +org.apache.fop.layoutmgr.BreakPoss@754fc, +org.apache.fop.layoutmgr.BreakPoss@15c998a, +org.apache.fop.layoutmgr.BreakPoss@6458a6, +org.apache.fop.layoutmgr.BreakPoss@1f82ab4, +org.apache.fop.layoutmgr.BreakPoss@1bb9696, +org.apache.fop.layoutmgr.BreakPoss@9b6220, +org.apache.fop.layoutmgr.BreakPoss@1474e45, +org.apache.fop.layoutmgr.BreakPoss@63a721 +]" + + vecInlineBreaks.get(0).position = { + iLeafPos: 0 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1246) +} + + vecInlineBreaks.get(0).position.layoutManager = "org.apache.fop.layoutmgr.TextLayoutManager@57ea52" + + vecInlineBreaks.get(1).position = { + iLeafPos: 1 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1246) +} + + vecInlineBreaks.get(1).position.layoutManager = "org.apache.fop.layoutmgr.TextLayoutManager@57ea52" + + vecInlineBreaks.get(2).position = { + iLeafPos: 2 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1246) +} + + vecInlineBreaks.get(2).position.layoutManager = "org.apache.fop.layoutmgr.TextLayoutManager@57ea52" + + vecInlineBreaks.get(3).position = { + iLeafPos: 3 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1246) +} + + vecInlineBreaks.get(3).position.layoutManager = "org.apache.fop.layoutmgr.TextLayoutManager@57ea52" + + vecInlineBreaks.get(4).position = { + iLeafPos: 5 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1246) +} + + vecInlineBreaks.get(4).position.layoutManager = "org.apache.fop.layoutmgr.TextLayoutManager@57ea52" + + vecInlineBreaks.get(5).position = { + iLeafPos: 7 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1246) +} + + vecInlineBreaks.get(5).position.layoutManager = "org.apache.fop.layoutmgr.TextLayoutManager@57ea52" + + vecInlineBreaks.get(6).position = { + iLeafPos: 8 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1246) +} + + vecInlineBreaks.get(6).position.layoutManager = "org.apache.fop.layoutmgr.TextLayoutManager@57ea52" + + vecInlineBreaks.get(7).position = { + iLeafPos: 11 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1246) +} + + vecInlineBreaks.get(7).position.layoutManager = "org.apache.fop.layoutmgr.TextLayoutManager@57ea52" + + vecInlineBreaks.get(8).position = { + iLeafPos: 12 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1246) +} + + vecInlineBreaks.get(8).position.layoutManager = "org.apache.fop.layoutmgr.TextLayoutManager@57ea52" + + vecInlineBreaks.get(9).position = { + iLeafPos: 13 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1246) +} + + vecInlineBreaks.get(9).position.layoutManager = "org.apache.fop.layoutmgr.TextLayoutManager@57ea52" + + vecInlineBreaks.get(10).position = { + iLeafPos: 14 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1246) +} + + vecInlineBreaks.get(10).position.layoutManager = "org.apache.fop.layoutmgr.TextLayoutManager@57ea52" + + vecInlineBreaks.get(11).position = { + iLeafPos: 15 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1246) +} + + vecInlineBreaks.get(11).position.layoutManager = "org.apache.fop.layoutmgr.TextLayoutManager@57ea52" + + vecInlineBreaks.get(12).position = { + iLeafPos: 16 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1246) +} + + vecInlineBreaks.get(12).position.layoutManager = "org.apache.fop.layoutmgr.TextLayoutManager@57ea52" + + vecInlineBreaks.get(13).position = { + iLeafPos: 18 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1246) +} + + vecInlineBreaks.get(13).position.layoutManager = "org.apache.fop.layoutmgr.TextLayoutManager@57ea52" + + vecInlineBreaks.get(14).position = { + iLeafPos: 20 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1246) +} + + vecInlineBreaks.get(14).position.layoutManager = "org.apache.fop.layoutmgr.TextLayoutManager@57ea52" + + vecInlineBreaks.get(15).position = { + iLeafPos: 21 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1246) +} + + vecInlineBreaks.get(15).position.layoutManager = "org.apache.fop.layoutmgr.TextLayoutManager@57ea52" + + vecInlineBreaks.get(16).position = { + iLeafPos: 22 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1246) +} + + vecInlineBreaks.get(16).position.layoutManager = "org.apache.fop.layoutmgr.TextLayoutManager@57ea52" + + vecInlineBreaks.get(17).position = { + iLeafPos: 23 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1246) +} + + vecInlineBreaks.get(17).position.layoutManager = "org.apache.fop.layoutmgr.TextLayoutManager@57ea52" + + vecInlineBreaks.get(18).position = { + iLeafPos: 25 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1246) +} + + vecInlineBreaks.get(18).position.layoutManager = "org.apache.fop.layoutmgr.TextLayoutManager@57ea52" +</screen> + </section> + + <section> + <title>TextLM</title> + +<screen> + this = "org.apache.fop.layoutmgr.TextLayoutManager@57ea52" + + this.chars = { +w, a, t, e, r, s, t, a, a, t, s, i, n, g, e, n, i, e, u, r, + , m, i, n, i, s, t, e, r, s, p, o, r, t, e, f, e, u, i, l, l, e, + , a, a, n, d, a, c, h, t, s, t, r, e, k, k, e, r, ., + , V, e, r, n, e, d, e, r, l, a, n, d, s, t, e, + , v, a, k, l, i, t, e, r, a, t, u, u, r, + , v, e, r, s, c, h, i, l, l, e, n, d, + , v, e, r, h, o, l, l, a, n, d, s, t, e, + , v, a, k, l, i, t, e, r, a, t, u, u, r, ., + , b, e, s, t, u, u, r, s, t, a, k, e, n, + , l, a, n, d, s, t, a, a, l, + , b, e, l, a, n, g, r, i, j, k, . +} + + tbpNext = { + iLeafPos: 0 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1246) +} + + vecAreaInfo = "[ +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@107bd0d, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@12922f6, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@1b66b06, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@12c9557, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@9f0d, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@ca3783, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@2a6ff, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@21d23b, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@7124af, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@1f7708, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@1bfbfb8, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@1c3e9ba, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@125d61e, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@10c6cfc, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@c72243, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@19a8416, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@155d3a3, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@1b994de, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@dc9766, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@57e787, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@1217e67, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@1f1bd98, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@1d686c1, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@128edf2, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@1dddba, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@c7e8a7, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@7b4703, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@1732ed2, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@1071521, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@1fc3c84, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@e93999, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@1c486f2, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@1779885, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@be76c7, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@682406, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@115126e, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@6d2380, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@135b1f3, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@35e6e3, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@c9630a, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@185572a, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@11daa0e, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@879860, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@24de7d, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@8b058b, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@1192059, +org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@9ac0f5 +]" + + vecAreaInfo.get(0) = { + iStartIndex: 0 + iBreakIndex: 2 + iWScount: 0 + ipdArea: instance of org.apache.fop.traits.MinOptMax(id=1304) + this$0: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1246) +} + + vecAreaInfo.get(1) = { + iStartIndex: 2 + iBreakIndex: 5 + iWScount: 0 + ipdArea: instance of org.apache.fop.traits.MinOptMax(id=1308) + this$0: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1246) +} + + vecAreaInfo.get(2) = { + iStartIndex: 5 + iBreakIndex: 11 + iWScount: 0 + ipdArea: instance of org.apache.fop.traits.MinOptMax(id=1310) + this$0: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1246) +} + + vecAreaInfo.get(3) = { + iStartIndex: 11 + iBreakIndex: 13 + iWScount: 0 + ipdArea: instance of org.apache.fop.traits.MinOptMax(id=1312) + this$0: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1246) +} + + vecAreaInfo.get(4) = { + iStartIndex: 13 + iBreakIndex: 15 + iWScount: 0 + ipdArea: instance of org.apache.fop.traits.MinOptMax(id=1314) + this$0: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1246) +} + + vecAreaInfo.get(5) = { + iStartIndex: 13 + iBreakIndex: 20 + iWScount: 0 + ipdArea: instance of org.apache.fop.traits.MinOptMax(id=1316) + this$0: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1246) +} + + vecAreaInfo.get(6) = { + iStartIndex: 20 + iBreakIndex: 42 + iWScount: 1 + ipdArea: instance of org.apache.fop.traits.MinOptMax(id=1318) + this$0: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1246) +} + + vecAreaInfo.get(7) = { + iStartIndex: 20 + iBreakIndex: 23 + iWScount: 1 + ipdArea: instance of org.apache.fop.traits.MinOptMax(id=1320) + this$0: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1246) +} + + vecAreaInfo.get(8) = { + iStartIndex: 23 + iBreakIndex: 26 + iWScount: 0 + ipdArea: instance of org.apache.fop.traits.MinOptMax(id=1322) + this$0: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1246) +} + + vecAreaInfo.get(9) = { + iStartIndex: 26 + iBreakIndex: 30 + iWScount: 0 + ipdArea: instance of org.apache.fop.traits.MinOptMax(id=1324) + this$0: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1246) +} + + vecAreaInfo.get(10) = { + iStartIndex: 26 + iBreakIndex: 42 + iWScount: 0 + ipdArea: instance of org.apache.fop.traits.MinOptMax(id=1326) + this$0: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1246) +} + + vecAreaInfo.get(11) = { + iStartIndex: 26 + iBreakIndex: 29 + iWScount: 0 + ipdArea: instance of org.apache.fop.traits.MinOptMax(id=1328) + this$0: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1246) +} + + vecAreaInfo.get(12) = { + iStartIndex: 29 + iBreakIndex: 30 + iWScount: 0 + ipdArea: instance of org.apache.fop.traits.MinOptMax(id=1330) + this$0: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1246) +} + + vecAreaInfo.get(13) = { + iStartIndex: 30 + iBreakIndex: 33 + iWScount: 0 + ipdArea: instance of org.apache.fop.traits.MinOptMax(id=1332) + this$0: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1246) +} + + vecAreaInfo.get(14) = { + iStartIndex: 33 + iBreakIndex: 35 + iWScount: 0 + ipdArea: instance of org.apache.fop.traits.MinOptMax(id=1334) + this$0: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1246) +} + + vecAreaInfo.get(15) = { + iStartIndex: 35 + iBreakIndex: 40 + iWScount: 0 + ipdArea: instance of org.apache.fop.traits.MinOptMax(id=1336) + this$0: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1246) +} + + vecAreaInfo.get(16) = { + iStartIndex: 40 + iBreakIndex: 42 + iWScount: 0 + ipdArea: instance of org.apache.fop.traits.MinOptMax(id=1338) + this$0: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1246) +} + + vecAreaInfo.get(17) = { + iStartIndex: 42 + iBreakIndex: 60 + iWScount: 1 + ipdArea: instance of org.apache.fop.traits.MinOptMax(id=1340) + this$0: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1246) +} + + vecAreaInfo.get(18) = { + iStartIndex: 43 + iBreakIndex: 60 + iWScount: 0 + ipdArea: instance of org.apache.fop.traits.MinOptMax(id=1342) + this$0: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1246) +} +</screen> + </section> + + <section> + <title>BlockLM2</title> + +<screen> + this = "org.apache.fop.layoutmgr.BlockLayoutManager@144b18f" + + lfp = { + iLeafPos: 0 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.BlockLayoutManager(id=1186) +} + + iStartPos = 0 + + childBreaks = "[org.apache.fop.layoutmgr.BreakPoss@145f939]" + + childBreaks.get(0).position = { + dAdjust: 0.0 + ipdAdjust: -1.0 + startIndent: 0 + lineHeight: 14400 + baseline: 12750 + org.apache.fop.layoutmgr.LeafPosition.iLeafPos: 1 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.LineLayoutManager(id=1377) +} + + childBreaks.get(0).position.layoutManager = "org.apache.fop.layoutmgr.LineLayoutManager@df2d38" +</screen> + </section> + + <section> + <title>LineLM</title> + +<screen> + this = "org.apache.fop.layoutmgr.LineLayoutManager@df2d38" + + lbp = { + dAdjust: 0.0 + ipdAdjust: -1.0 + startIndent: 0 + lineHeight: 14400 + baseline: 12750 + org.apache.fop.layoutmgr.LeafPosition.iLeafPos: 1 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.LineLayoutManager(id=1377) +} + + iStartPos = 0 + + vecInlineBreaks = "[ +org.apache.fop.layoutmgr.BreakPoss@eb67e8, +org.apache.fop.layoutmgr.BreakPoss@f2ea42 +]" + + vecInlineBreaks.get(0).position = { + iLeafPos: 0 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1385) +} + + vecInlineBreaks.get(0).position.layoutManager = "org.apache.fop.layoutmgr.TextLayoutManager@e265d0" + + vecInlineBreaks.get(1).position = { + iLeafPos: 0 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.AddLMVisitor$2(id=1389) +} + + vecInlineBreaks.get(1).position.layoutManager = "org.apache.fop.layoutmgr.AddLMVisitor$2@2f356f" +</screen> + </section> + + <section> + <title>TextLM</title> + +<screen> + this = "org.apache.fop.layoutmgr.TextLayoutManager@e265d0" + + this.chars = { + +} + + tbpNext = { + iLeafPos: 0 + org.apache.fop.layoutmgr.Position.layoutManager: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1385) +} + + vecAreaInfo = "[org.apache.fop.layoutmgr.TextLayoutManager$AreaInfo@996cca]" + + vecAreaInfo.get(0) = { + iStartIndex: 0 + iBreakIndex: 1 + iWScount: 1 + ipdArea: instance of org.apache.fop.traits.MinOptMax(id=1396) + this$0: instance of org.apache.fop.layoutmgr.TextLayoutManager(id=1385) +} +</screen> + </section> + + <section> + <title><literal>AddLMVisitor$2</literal></title> + <simpara>No data</simpara> + </section> + + </section> + </chapter> + +<!-- Local Variables: --> +<!-- current-language-environment: UTF-8 --> +<!-- coding: utf-8 --> +<!-- default-input-method: TeX --> +<!-- End: --> diff --git a/src/documentation/content/xdocs/DnI/areatree.xml b/src/documentation/content/xdocs/DnI/areatree.xml new file mode 100644 index 000000000..5d361e3ca --- /dev/null +++ b/src/documentation/content/xdocs/DnI/areatree.xml @@ -0,0 +1,420 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * Copyright 2004 The Apache Software Foundation. + * + * Licensed 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$ --> + +<!-- +<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" + "docbookx.dtd"> + --> + + <chapter> + <title>Phase 2: Building the Area tree</title> + + <section> + <title>Initiating the layout process</title> + +<para>In the <literal>PageSequence.end()</literal> method the +<literal>FOTreeHandler</literal> object +<literal>foInputHandler</literal> notifies the +<literal>FOTreeListeners</literal> of the PageSequence-end +event. There is only one listener, the +<literal>FOTreeControl</literal> object +<literal>foTreeControl</literal>. This listener asks its +<literal>LayoutManagerLS</literal> object to format the FO subtree of +the <literal>PageSequence</literal> FO node. This object constructs a +<literal>PageLayoutManager</literal> for the +<literal>PageSequence</literal> FO node, which does the work.</para> + +<screen> +org.apache.fop.fo.pagination.PageSequence.end(): +this.getFOTreeControl().getFOInputHandler().endPageSequence(this): +-> foTreeControl.getFOInputHandler().endPageSequence(this) +-> foInputHandler.endPageSequence(this) (type FOTreeHandler): +</screen> + +<para>This method only calls +<literal>FOTreeHandler.notifyPageSequenceComplete(pageSequence)</literal>, +which notifies the <literal>FOTreeListeners</literal> of the +PageSequence-end event. The <literal>PageSequence</literal> object +attaches itself to the event, from which the listeners can retrieve it +again.</para> + +<para>There is only one listener. It is an +<literal>org.apache.fop.apps.Document</literal> object. It is the same +object as <literal>pageSequence.root.foTreeControl</literal>. Its +method <literal>foPageSequenceComplete(event)</literal> is called, +which is a method of the <literal>FOTreeListener</literal> +interface. It handles an <literal>FOTreeEvent</literal> that is fired +when a <literal>PageSequence</literal> object has been +completed.</para> + +<para>The listener formats the FO subtree of the +<literal>PageSequence</literal> FO node. It calls its layout +strategy's method <literal>LayoutManagerLS.format(pageSeq, +areaTree)</literal>.</para> + +<para>This method creates a new <literal>PageLayoutManager</literal> +for the <literal>PageSequence</literal> FO node and calls its +<literal>run</literal> method (could start another thread). The pages +in this page sequence are completely layed out by the +<literal>PageLayoutManager</literal>, in its +<literal>doLayout</literal> method. The first step in the layout +process is getting the page setup from the page masters. Then the FO +tree is processed.</para> + +<screen> + [1] org.apache.fop.layoutmgr.PageLayoutManager.doLayout (PageLayoutManager.java:220) + [2] org.apache.fop.layoutmgr.PageLayoutManager.run (PageLayoutManager.java:208) + [3] org.apache.fop.layoutmgr.LayoutManagerLS.format (LayoutManagerLS.java:83) + [4] org.apache.fop.apps.Document.foPageSequenceComplete (Document.java:348) + [5] org.apache.fop.fo.FOTreeHandler.notifyPageSequenceComplete (FOTreeHandler.java:497) + [6] org.apache.fop.fo.FOTreeHandler.endPageSequence (FOTreeHandler.java:215) + [7] org.apache.fop.fo.pagination.PageSequence.end (PageSequence.java:350) + [8] org.apache.fop.fo.FOTreeBuilder.endElement (FOTreeBuilder.java:223) + ... parser stuff + [16] org.apache.xerces.parsers.AbstractSAXParser.parse (null) + [17] org.apache.fop.apps.Driver.render (Driver.java:622) + [18] org.apache.fop.apps.Driver.render (Driver.java:558) + [19] org.apache.fop.apps.Fop.main (Fop.java:102) +</screen> + +<screen> +main[1] dump pageLM + pageLM = { + pageNumberGenerator: instance of org.apache.fop.fo.pagination.PageNumberGenerator(id=1005) + pageCount: 1 + pageNumberString: "1" + isFirstPage: true + bFirstPage: false + curPage: null + curBody: null + curSpan: null + curSpanColumns: 0 + curFlow: null + flowBPD: 0 + flowIPD: 0 + areaTree: instance of org.apache.fop.area.AreaTree(id=1025) + pageSequence: instance of org.apache.fop.fo.pagination.PageSequence(id=997) + currentSimplePageMaster: null + staticContentLMs: instance of java.util.HashMap(id=1033) + lmls: instance of org.apache.fop.layoutmgr.LayoutManagerLS(id=1034) + org.apache.fop.layoutmgr.AbstractLayoutManager.userAgent: instance of org.apache.fop.apps.FOUserAgent(id=1035) + org.apache.fop.layoutmgr.AbstractLayoutManager.parentLM: null + org.apache.fop.layoutmgr.AbstractLayoutManager.fobj: instance of org.apache.fop.fo.pagination.PageSequence(id=997) + org.apache.fop.layoutmgr.AbstractLayoutManager.foID: null + org.apache.fop.layoutmgr.AbstractLayoutManager.markers: null + org.apache.fop.layoutmgr.AbstractLayoutManager.bFinished: false + org.apache.fop.layoutmgr.AbstractLayoutManager.curChildLM: null + org.apache.fop.layoutmgr.AbstractLayoutManager.childLMiter: instance of org.apache.fop.layoutmgr.LMiter(id=1036) + org.apache.fop.layoutmgr.AbstractLayoutManager.bInited: false +} +</screen> + + <para>The above calling sequence contains two configuration +points. FOP's area tree building process can be modified by +registering other listeners with the FO tree handler. It can also be +configured by giving the Document object a different layout strategy +object. See also the <literal>AddLMVisitor</literal> class which +controls the creation of Layout Managers. +<warning> + <simpara>TO BE EXPANDED</simpara> + </warning></para> + + </section> + + <section> + <title>Creating the page and body areas</title> + + <section> + <title>Overview</title> + + <para>Create the layout (<literal>doLayout</literal>) <itemizedlist spacing="compact"> + <listitem> + <para>First create a new Page Viewport +(<literal>makeNewPage</literal>). <itemizedlist spacing="compact"> + <listitem> + <para>First finish the current page +(<literal>finishPage</literal>).</para> + </listitem> + <listitem> + <para>Then create the new page viewport +(<literal>createPage</literal>). <itemizedlist spacing="compact"> + <listitem> + <para>First get the page master +(<literal>getSimplePageMasterToUse</literal>, +<literal>pageSequence.getPageSequenceMaster</literal> or +<literal>pageSequence.getSimplePageMaster</literal>).</para> + </listitem> + <listitem> + <para>Then get the body +(<literal>currentSimplePageMaster.getRegion</literal>, from +<literal>currentSimplePageMaster</literal>'s +<literal>regions</literal> map).</para> + </listitem> + <listitem> + <para>Then create the page viewport +(<literal>createPageAreas(currentSimplePageMaster)</literal>). +<itemizedlist spacing="compact"> + <listitem> + <para>From the properties of the page +master create the page reference rectangle, a new page, a new +FODimension object, and a CTM object.</para> + </listitem> + <listitem> + <para>For each region in the page master +(in our example we only have a body): <itemizedlist spacing="compact"> + <listitem> + <para>make a region viewport +(<literal>makeRegionViewport</literal>), which involves calculating +the position of the region on the page, using the FODimension and CTM +objects. +</para> + </listitem> + <listitem> + <para>make the reference area +(<literal>makeRegionBodyReferenceArea</literal>, +<literal>makeRegionReferenceArea</literal>).</para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + + <para>At this point the page viewport and its region viewports +have been laid out.</para> + + <para> <itemizedlist spacing="compact"> + <listitem> + <simpara>Then create the body's main reference area +(<literal>createBodyMainReferenceArea</literal>).</simpara> + </listitem> + <listitem> + <simpara>Then create a Span +(<literal>createSpan</literal>).</simpara> + </listitem> + <listitem> + <simpara>And get the flowIPD +(curFlow.<literal>getIPD</literal>()).</simpara> + </listitem> + </itemizedlist></para> + + <para>At this point the body has a single span area with a +single flow area without children. +</para> + + </section> + + <section> + <title>Detailed view</title> + + <para>The call stack when creating the region viewports: +<screen> + [1] org.apache.fop.layoutmgr.PageLayoutManager.makeRegionViewport (PageLayoutManager.java:832) + [2] org.apache.fop.layoutmgr.PageLayoutManager.createPageAreas (PageLayoutManager.java:805) + [3] org.apache.fop.layoutmgr.PageLayoutManager.createPage (PageLayoutManager.java:748) + [4] org.apache.fop.layoutmgr.PageLayoutManager.makeNewPage (PageLayoutManager.java:467) + [5] org.apache.fop.layoutmgr.PageLayoutManager.doLayout (PageLayoutManager.java:220) +</screen> +</para> + +<para>At the end of <literal>createPageAreas</literal> the following +properties of the page have been established:</para> + +<para>The page reference rectangle: +<screen> + pageRefRect = { + x: 56692 + y: 56692 + width: 481891 + height: 728505 + serialVersionUID: -4345857070255674764 +} +</screen> +</para> + +<para>The page reference area: +<screen> + page = { + regionBefore: null + regionStart: null + regionBody: instance of org.apache.fop.area.RegionViewport(id=1279) + regionEnd: null + regionAfter: null + unresolved: null +} +</screen> + +<screen> + page.regionBody = { + region: instance of org.apache.fop.area.BodyRegion(id=1280) + viewArea: instance of java.awt.Rectangle(id=1281) + clip: false + org.apache.fop.area.Area.areaClass: 0 + org.apache.fop.area.Area.ipd: 0 + org.apache.fop.area.Area.props: null +} +</screen> + +<screen> + page.regionBody.region = { + beforeFloat: null + mainReference: null + footnote: null + columnGap: 18000 + columnCount: 1 + refIPD: 0 + org.apache.fop.area.RegionReference.regionClass: 2 + org.apache.fop.area.RegionReference.ctm: instance of org.apache.fop.area.CTM(id=1282) + org.apache.fop.area.RegionReference.blocks: instance of java.util.ArrayList(id=1283) + org.apache.fop.area.Area.areaClass: 0 + org.apache.fop.area.Area.ipd: 0 + org.apache.fop.area.Area.props: null +} +</screen> + +<screen> + page.regionBody.viewArea = { + x: 56692 + y: 56692 + width: 481891 + height: 728505 + serialVersionUID: -4345857070255674764 +} +</screen> +</para> + +<para>The <literal>PageViewport</literal> is returned:</para> + +<screen> + curPage = { + page: instance of org.apache.fop.area.Page(id=1261) + viewArea: instance of java.awt.Rectangle(id=1289) + clip: false + pageNumber: null + idReferences: null + unresolved: null + pendingResolved: null + markerFirstStart: null + markerLastStart: null + markerFirstAny: null + markerLastEnd: null + markerLastAny: null +} +</screen> + +<para>When <literal>makeNewPage</literal> returns, the Page +LayoutManager has a Page Viewport and a Body Region object. The layout +dimensions have been calculated:</para> + +<screen> + this = { + pageNumberGenerator: instance of org.apache.fop.fo.pagination.PageNumberGenerator(id=1003) + pageCount: 1 + pageNumberString: "1" + isFirstPage: false + bFirstPage: false + curPage: instance of org.apache.fop.area.PageViewport(id=1288) + curBody: instance of org.apache.fop.area.BodyRegion(id=1280) + curSpan: null + curSpanColumns: 0 + curFlow: null + flowBPD: 728505 + flowIPD: 0 + areaTree: instance of org.apache.fop.area.AreaTree(id=1005) + pageSequence: instance of org.apache.fop.fo.pagination.PageSequence(id=1006) + currentSimplePageMaster: instance of org.apache.fop.fo.pagination.SimplePageMaster(id=1007) + staticContentLMs: instance of java.util.HashMap(id=1008) + lmls: instance of org.apache.fop.layoutmgr.LayoutManagerLS(id=1009) + org.apache.fop.layoutmgr.AbstractLayoutManager.userAgent: instance of org.apache.fop.apps.FOUserAgent(id=1010) + org.apache.fop.layoutmgr.AbstractLayoutManager.parentLM: null + org.apache.fop.layoutmgr.AbstractLayoutManager.fobj: instance of org.apache.fop.fo.pagination.PageSequence(id=1006) + org.apache.fop.layoutmgr.AbstractLayoutManager.foID: null + org.apache.fop.layoutmgr.AbstractLayoutManager.markers: null + org.apache.fop.layoutmgr.AbstractLayoutManager.bFinished: false + org.apache.fop.layoutmgr.AbstractLayoutManager.curChildLM: null + org.apache.fop.layoutmgr.AbstractLayoutManager.childLMiter: instance of org.apache.fop.layoutmgr.LMiter(id=1011) + org.apache.fop.layoutmgr.AbstractLayoutManager.bInited: false +} +</screen> + +<para>The method <literal>createBodyMainReferenceArea()</literal> adds +a <literal>MainReferenceArea</literal> to the body region:</para> + +<screen> + curBody = { + beforeFloat: null + mainReference: instance of org.apache.fop.area.MainReference(id=1293) + footnote: null + columnGap: 18000 + columnCount: 1 + refIPD: 0 + org.apache.fop.area.RegionReference.regionClass: 2 + org.apache.fop.area.RegionReference.ctm: instance of org.apache.fop.area.CTM(id=1282) + org.apache.fop.area.RegionReference.blocks: instance of java.util.ArrayList(id=1283) + org.apache.fop.area.Area.areaClass: 0 + org.apache.fop.area.Area.ipd: 0 + org.apache.fop.area.Area.props: null +} +</screen> + +<screen> + curBody.mainReference = { + spanAreas: instance of java.util.ArrayList(id=1294) + columnGap: 0 + width: 0 + org.apache.fop.area.Area.areaClass: 0 + org.apache.fop.area.Area.ipd: 0 + org.apache.fop.area.Area.props: null +} +</screen> + +<screen> + curBody.mainReference.spanAreas = "[]" +</screen> + +<para>After <literal>createSpan(1)</literal>:</para> + +<screen> + curBody.mainReference.spanAreas = "[org.apache.fop.area.Span@1581e80]" +</screen> + +<screen> + curBody.mainReference.spanAreas.get(0) = { + flowAreas: instance of java.util.ArrayList(id=1299) + height: 0 + org.apache.fop.area.Area.areaClass: 0 + org.apache.fop.area.Area.ipd: 481891 + org.apache.fop.area.Area.props: null +} +</screen> + + </section> + </section> + </chapter> + +<!-- Local Variables: --> +<!-- current-language-environment: UTF-8 --> +<!-- coding: utf-8 --> +<!-- default-input-method: TeX --> +<!-- End: --> diff --git a/src/documentation/content/xdocs/DnI/book.xml b/src/documentation/content/xdocs/DnI/book.xml new file mode 100644 index 000000000..a528fe31b --- /dev/null +++ b/src/documentation/content/xdocs/DnI/book.xml @@ -0,0 +1,122 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * Copyright 2004 The Apache Software Foundation. + * + * Licensed 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$ --> + +<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" + "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [ +<!ENTITY ch.overview SYSTEM "overview.xml"> +<!ENTITY ch.preparation SYSTEM "preparation.xml"> +<!ENTITY ch.fotree SYSTEM "fotree.xml"> +<!ENTITY ch.areatree SYSTEM "areatree.xml"> +<!ENTITY ch.getnextbreakposs SYSTEM "getnextbreakposs.xml"> +<!ENTITY ch.addareas SYSTEM "addareas.xml"> +<!ENTITY ch.rendering SYSTEM "rendering.xml"> +<!ENTITY ch.foptrees SYSTEM "foptrees.xml"> +<!ENTITY ch.properties SYSTEM "properties.xml"> +<!ENTITY ch.fonts SYSTEM "fonts.xml"> +<!ENTITY ch.configuration SYSTEM "configuration.xml"> +]> + +<book> + <bookinfo> + + <title>FOP's Design and Implementation</title> + + <authorgroup> + <author> + <firstname>Simon</firstname> + <surname>Pepping</surname> + <affiliation> + <orgname>FOP team</orgname> + <orgdiv>Apache Software Foundation</orgdiv> + </affiliation> + </author> + </authorgroup> + + <copyright> + <year>2004</year> + <holder>The Apache Software Foundation</holder> + </copyright> + + <legalnotice> + <para>Licensed 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 + +<screen> + <ulink url="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</ulink> +</screen> + +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.</para> + </legalnotice> + + <revhistory> + <revision> + <revnumber>0.x</revnumber> + <date>2003, 2004</date> + <revremark>Various early, partial versions</revremark> + </revision> + <revision> + <revnumber>1.0</revnumber> + <date>01 August 2004</date> + <revremark>Committed to the FOP code repository</revremark> + </revision> + </revhistory> + + <abstract> + <simpara>FOP is a Formatting Object Processor of the Apache +project. It aims to provide a standards compliant implementation of +XSL-FO. It understands Unicode, has bidirectional writing +capabilities, and implements a wide range of rendering +formats.</simpara> + + <simpara>FOP is a work in progress. Its code is under continuing +development. This documentation describes the state of the code at the +time the documentation was written. At the time you read this +documentation the code may be different. Note also that different +parts of the documentation were written or revised at different +times.</simpara> + + </abstract> + + </bookinfo> + +&ch.overview; +&ch.preparation; +&ch.fotree; +&ch.areatree; +&ch.getnextbreakposs; +&ch.addareas; +&ch.rendering; +&ch.foptrees; +&ch.properties; +&ch.fonts; +&ch.configuration; + +</book> + +<!-- Local Variables: --> +<!-- current-language-environment: UTF-8 --> +<!-- coding: utf-8 --> +<!-- default-input-method: TeX --> +<!-- End: --> diff --git a/src/documentation/content/xdocs/DnI/configuration.xml b/src/documentation/content/xdocs/DnI/configuration.xml new file mode 100644 index 000000000..0e857836a --- /dev/null +++ b/src/documentation/content/xdocs/DnI/configuration.xml @@ -0,0 +1,109 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * Copyright 2004 The Apache Software Foundation. + * + * Licensed 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$ --> + +<!-- +<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" + "docbookx.dtd"> + --> + +<chapter> + <title>Configuration</title> + + <para>Configuration is based on the <literal>Configurable</literal> +and <literal>Configuration</literal> interfaces of +<literal>avalon</literal>: + +<screen> +org.apache.avalon.framework.configuration.Configurable +org.apache.avalon.framework.configuration.Configuration +</screen> + +A type that implements <literal>Configurable</literal> can be +configured by calling its method <literal>configure(Configuration +configuration)</literal>, where the argument is the +<literal>Configuration</literal> object that holds the user +configuration settings. It can also be configured by calling the +static method <literal>ContainerUtil.configure(object, cfg)</literal> +of the class + +<screen> +ContainerUtil = org.apache.avalon.framework.container.ContainerUtil +</screen> + +This method checks if <literal>object</literal> implements +<literal>Configurable</literal>. If not, no configuration is +attempted.</para> + +<para>The following classes implement <literal>Configurable</literal>: +<itemizedlist spacing="compact"> + <listitem> + <para><literal>render.AbstractRenderer</literal> and its +subclasses (all renderers). Only +<literal>render.pdf.PDFRenderer</literal> and +<literal>render.ps.PSRenderer</literal> have meaningful +implementations of the <literal>configure</literal> method. The +command line module configures each renderer from the user +configuration file with the subconfiguration +<literal>renderers/renderer[@mime=$mimetype]</literal>.</para> + </listitem> + <listitem> + <para><literal>svg.PDFTranscoder</literal></para> + </listitem> + <listitem> + <para><literal>svg.PDFDocumentGraphics2D</literal>. This class +is configured by <literal>svg.PDFTranscoder</literal> via +<literal>ContainerUtil.configure(graphics, this.cfg)</literal>. +</para> + </listitem> + </itemizedlist></para> + +<para>In addition <literal>render.ps.AbstractPSTranscoder</literal> +has a member <literal>Configuration cfg</literal>. It configures +graphics via <literal>ContainerUtil.configure(graphics, +this.cfg)</literal>. The graphics are of type +<literal>render.ps.AbstractPSDocumentGraphics2D</literal>, which does +not implement <literal>Configurable</literal>, so that no +configuration takes place.</para> + +<para><literal>render.pdf.PDFRenderer</literal> and +<literal>svg.PDFDocumentGraphics2D</literal> both call +<literal>fonts.FontSetup.buildFontListFromConfiguration(cfg)</literal> +and +<literal>pdf.PDFFilterList.buildFilterMapFromConfiguration(cfg)</literal>.</para> + +<para>Configuration info is used by: <itemizedlist spacing="compact"> + <listitem> + <para><literal>fonts.FontSetup.buildFontListFromConfiguration(cfg)</literal>. It +uses <literal>fonts/font/font-triplet</literal> from the renderer +subconfiguration.</para> + </listitem> + <listitem> + <para><literal>pdf.PDFFilterList.buildFilterMapFromConfiguration(cfg)</literal>. It +uses <literal>filterList/value</literal> from the renderer +subconfiguration</para> + </listitem> + <listitem> + <para><literal>render.ps.PSRenderer.configure(cfg)</literal>. It +uses <literal>auto-rotate-landscape</literal> as a Boolean. +</para> + </listitem> + </itemizedlist></para> + +</chapter> diff --git a/src/documentation/content/xdocs/DnI/cust-fo-docbook.xsl b/src/documentation/content/xdocs/DnI/cust-fo-docbook.xsl new file mode 100644 index 000000000..503b0a81c --- /dev/null +++ b/src/documentation/content/xdocs/DnI/cust-fo-docbook.xsl @@ -0,0 +1,534 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * Copyright 2004 The Apache Software Foundation. + * + * Licensed 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$ --> + +<xsl:stylesheet + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:fo="http://www.w3.org/1999/XSL/Format" + xmlns="http://www.w3.org/1999/xhtml" + xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0" + version="1.0"> + + <xsl:import + href="http://cvs.sourceforge.net/viewcvs.py/*checkout*/docbook/xsl/fo/docbook.xsl"/> + + <!-- Add other variable definitions here --> + <xsl:variable name="paper.type" select="'A4'"/> + <xsl:param name="section.autolabel" select="1"/> + <xsl:param name="section.label.includes.component.label" select="1"/> + <xsl:param name="marker.section.level" select="1"/> + <xsl:param name="component.title.several.objects" select="1"/> + <xsl:param name="fop.extensions" select="1"/> + <xsl:param name="draft.mode" select="'no'"/> + <xsl:param name="draft.watermark.image"/> + <!-- Double sided does not produce good headers and footers --> + <xsl:param name="double.sided" select="1"/> + <!-- Add to the section title properties --> + <xsl:attribute-set name="section.title.properties"> + <xsl:attribute name="text-align">start</xsl:attribute> + <xsl:attribute name="hyphenate">false</xsl:attribute> + </xsl:attribute-set> + <!-- Reintroduce the attribute set component.title.properties --> + <xsl:attribute-set name="component.title.properties"> + <xsl:attribute name="keep-with-next.within-column">always</xsl:attribute> + <xsl:attribute name="space-before.optimum"> + <xsl:value-of select="$body.font.master"/> + <xsl:text>pt</xsl:text> + </xsl:attribute> + <xsl:attribute name="space-before.minimum"> + <xsl:value-of select="$body.font.master * 0.8"/> + <xsl:text>pt</xsl:text> + </xsl:attribute> + <xsl:attribute name="space-before.maximum"> + <xsl:value-of select="$body.font.master * 1.2"/> + <xsl:text>pt</xsl:text> + </xsl:attribute> + <xsl:attribute name="text-align">start</xsl:attribute> + <xsl:attribute name="hyphenate">false</xsl:attribute> + </xsl:attribute-set> + <!-- spacing between label and title --> + <xsl:attribute-set name="component.title.label.properties"> + <xsl:attribute name="keep-with-next.within-column">always</xsl:attribute> + <xsl:attribute name="space-after.optimum"> + <xsl:value-of select="$body.font.master"/> + <xsl:text>pt</xsl:text> + </xsl:attribute> + <xsl:attribute name="space-after.minimum"> + <xsl:value-of select="$body.font.master * 0.8"/> + <xsl:text>pt</xsl:text> + </xsl:attribute> + <xsl:attribute name="space-after.maximum"> + <xsl:value-of select="$body.font.master * 1.2"/> + <xsl:text>pt</xsl:text> + </xsl:attribute> + <xsl:attribute name="font-size"> + <xsl:value-of select="$body.font.master * 2.0736"/> + <xsl:text>pt</xsl:text> + </xsl:attribute> + </xsl:attribute-set> + <xsl:attribute-set name="book.titlepage.author.properties"> + <xsl:attribute name="font-size"> + <xsl:value-of select="$body.font.master * 1.728"/> + <xsl:text>pt</xsl:text> + </xsl:attribute> + </xsl:attribute-set> + <xsl:attribute-set name="book.titlepage.affiliation.properties"> + <xsl:attribute name="space-before"> + <xsl:value-of select="$body.font.master * 1.2"/> + <xsl:text>pt</xsl:text> + </xsl:attribute> + <xsl:attribute name="font-style"> + <xsl:text>italic</xsl:text> + </xsl:attribute> + <xsl:attribute name="font-size"> + <xsl:value-of select="$body.font.master * 1.44"/> + <xsl:text>pt</xsl:text> + </xsl:attribute> + <xsl:attribute name="font-weight"> + <xsl:text>normal</xsl:text> + </xsl:attribute> + </xsl:attribute-set> + <!-- No headers and footers on blank pages --> + <xsl:param name="headers.on.blank.pages" select="0"/> + <xsl:param name="footers.on.blank.pages" select="0"/> + <xsl:param name="headers.on.first.pages" select="0"/> + <xsl:param name="header.left.width" + select="'proportional-column-width(1)'"/> + <xsl:param name="header.center.width" + select="'proportional-column-width(5)'"/> + <xsl:param name="header.right.width" + select="'proportional-column-width(1)'"/> + <!-- No left margin for titles --> + <xsl:param name="title.margin.left" select="'0pc'"/> + + <!-- + * Similar to mode object.title.markup + * but call template substitute-markup with the abbreviated title + --> + <xsl:template match="*" mode="object.titleabbrev.markup"> + <xsl:param name="allow-anchors" select="0"/> + <xsl:variable name="template"> + <xsl:apply-templates select="." mode="object.title.template"/> + </xsl:variable> + + <xsl:call-template name="substitute-markup"> + <xsl:with-param name="allow-anchors" select="$allow-anchors"/> + <xsl:with-param name="template" select="$template"/> + <xsl:with-param name="title" select="titleabbrev"/> + </xsl:call-template> + </xsl:template> + + <!-- + * Construct titleabbrev with mode object.titleabbrev.markup + * so that the section label is included + --> + <xsl:template match="section/title + |simplesect/title + |sect1/title + |sect2/title + |sect3/title + |sect4/title + |sect5/title" + mode="titlepage.mode" + priority="2"> + <xsl:variable name="section" select="parent::*"/> + <fo:block keep-with-next.within-column="always"> + <xsl:variable name="id"> + <xsl:call-template name="object.id"> + <xsl:with-param name="object" select="$section"/> + </xsl:call-template> + </xsl:variable> + + <xsl:variable name="level"> + <xsl:call-template name="section.level"> + <xsl:with-param name="node" select="$section"/> + </xsl:call-template> + </xsl:variable> + + <xsl:variable name="marker"> + <xsl:choose> + <xsl:when test="$level <= $marker.section.level">1</xsl:when> + <xsl:otherwise>0</xsl:otherwise> + </xsl:choose> + </xsl:variable> + + <xsl:variable name="title"> + <xsl:apply-templates select="$section" mode="object.title.markup"> + <xsl:with-param name="allow-anchors" select="1"/> + </xsl:apply-templates> + </xsl:variable> + + <xsl:variable name="titleabbrev"> + <xsl:apply-templates select="$section" mode="titleabbrev.markup"/> + </xsl:variable> + + <!-- Use for running head only if actual titleabbrev element --> + <xsl:variable name="titleabbrev.elem"> + <xsl:if test="$section/titleabbrev"> + <xsl:apply-templates select="$section" + mode="object.titleabbrev.markup"/> + </xsl:if> + </xsl:variable> + + <xsl:if test="$passivetex.extensions != 0"> + <fotex:bookmark xmlns:fotex="http://www.tug.org/fotex" + fotex-bookmark-level="{$level + 2}" + fotex-bookmark-label="{$id}"> + <xsl:value-of select="$titleabbrev"/> + </fotex:bookmark> + </xsl:if> + + <xsl:if test="$axf.extensions != 0"> + <xsl:attribute name="axf:outline-level"> + <xsl:value-of select="count(ancestor::*)-1"/> + </xsl:attribute> + <xsl:attribute name="axf:outline-expand">false</xsl:attribute> + <xsl:attribute name="axf:outline-title"> + <xsl:value-of select="$title"/> + </xsl:attribute> + </xsl:if> + + <xsl:call-template name="section.heading"> + <xsl:with-param name="level" select="$level"/> + <xsl:with-param name="title" select="$title"/> + <xsl:with-param name="marker" select="$marker"/> + <xsl:with-param name="titleabbrev" select="$titleabbrev.elem"/> + </xsl:call-template> + </fo:block> + </xsl:template> + + <!-- + * Use the attribute set component.title.properties + * Use mode several.objects.title.markup for actual title + --> + + <xsl:template name="component.title"> + <xsl:param name="node" select="."/> + <xsl:param name="pagewide" select="0"/> + <xsl:variable name="id"> + <xsl:call-template name="object.id"> + <xsl:with-param name="object" select="$node"/> + </xsl:call-template> + </xsl:variable> + <xsl:variable name="title"> + <xsl:apply-templates select="$node" mode="object.title.markup"> + <xsl:with-param name="allow-anchors" select="1"/> + </xsl:apply-templates> + </xsl:variable> + <xsl:variable name="titleabbrev"> + <xsl:apply-templates select="$node" mode="titleabbrev.markup"/> + </xsl:variable> + + <xsl:if test="$passivetex.extensions != 0"> + <fotex:bookmark xmlns:fotex="http://www.tug.org/fotex" + fotex-bookmark-level="2" + fotex-bookmark-label="{$id}"> + <xsl:value-of select="$titleabbrev"/> + </fotex:bookmark> + </xsl:if> + + <fo:block xsl:use-attribute-sets="component.title.properties"> + <xsl:if test="$pagewide != 0"> + <!-- Doesn't work to use 'all' here since not a child of fo:flow --> + <xsl:attribute name="span">inherit</xsl:attribute> + </xsl:if> + <xsl:attribute name="hyphenation-character"> + <xsl:call-template name="gentext"> + <xsl:with-param name="key" select="'hyphenation-character'"/> + </xsl:call-template> + </xsl:attribute> + <xsl:attribute name="hyphenation-push-character-count"> + <xsl:call-template name="gentext"> + <xsl:with-param name="key" + select="'hyphenation-push-character-count'"/> + </xsl:call-template> + </xsl:attribute> + <xsl:attribute name="hyphenation-remain-character-count"> + <xsl:call-template name="gentext"> + <xsl:with-param name="key" + select="'hyphenation-remain-character-count'"/> + </xsl:call-template> + </xsl:attribute> + <xsl:if test="$axf.extensions != 0"> + <xsl:attribute name="axf:outline-level"> + <xsl:value-of select="count($node/ancestor::*)"/> + </xsl:attribute> + <xsl:attribute name="axf:outline-expand">false</xsl:attribute> + <xsl:attribute name="axf:outline-title"> + <xsl:value-of select="$title"/> + </xsl:attribute> + </xsl:if> + <xsl:choose> + <xsl:when test="$component.title.several.objects != 0"> + <xsl:apply-templates select="$node" + mode="several.objects.title.markup"/> + </xsl:when> + <xsl:otherwise> + <xsl:copy-of select="$title"/> + </xsl:otherwise> + </xsl:choose> + </fo:block> + </xsl:template> + + <!-- + * Docbook-XSL's templates only allow a string value + * for the label and title. + * We want label and title in different fo elements. + * Mode several.objects.title.markup + --> + <xsl:template match="chapter" mode="several.objects.title.markup"> + + <fo:block xsl:use-attribute-sets="component.title.label.properties"> + <xsl:call-template name="gentext"> + <xsl:with-param name="key" select="'Chapter'"/> + </xsl:call-template> + <xsl:text> </xsl:text> + <xsl:apply-templates select="." mode="insert.label.markup"> + <xsl:with-param name="label"> + <xsl:apply-templates select="." mode="label.markup"/> + </xsl:with-param> + </xsl:apply-templates> + </fo:block> + + <fo:block> + <xsl:apply-templates select="." mode="insert.title.markup"> + <xsl:with-param name="title"> + <xsl:apply-templates select="." mode="title.markup"> + </xsl:apply-templates> + </xsl:with-param> + </xsl:apply-templates> + </fo:block> + + </xsl:template> + + <!-- + * Modify the header content: + * chapter number, + * section title only on odd pages, + * section number also with abbreviated titles + --> + <xsl:template name="header.content"> + <xsl:param name="pageclass" select="''"/> + <xsl:param name="sequence" select="''"/> + <xsl:param name="position" select="''"/> + <xsl:param name="gentext-key" select="''"/> + + <fo:block> + + <!-- sequence can be odd, even, first, blank --> + <!-- position can be left, center, right --> + <xsl:choose> + <xsl:when test="$sequence = 'blank'"> + <!-- nothing on blank pages --> + </xsl:when> + + <xsl:when test="$sequence = 'first'"> + <!-- nothing for first pages --> + </xsl:when> + + <xsl:when test="$position='left' or $position='right'"> + <!-- only draft on the left and right sides --> + <xsl:call-template name="draft.text"/> + </xsl:when> + + <xsl:when test="($sequence='odd' or $sequence='even') + and $position='center'"> + <xsl:if test="$pageclass != 'titlepage'"> + <xsl:choose> + <xsl:when test="ancestor::book and ($double.sided != 0) + and $sequence='odd'"> + <fo:retrieve-marker retrieve-class-name="section.head.marker" + retrieve-position="first-including-carryover" + retrieve-boundary="page-sequence"/> + </xsl:when> + <xsl:otherwise> + <xsl:apply-templates select="." mode="label.markup"/> + <xsl:text>. </xsl:text> + <xsl:apply-templates select="." mode="titleabbrev.markup"/> + </xsl:otherwise> + </xsl:choose> + </xsl:if> + </xsl:when> + + </xsl:choose> + </fo:block> + </xsl:template> + + <!-- Parametrize the widths of the header components --> + <xsl:template name="header.table"> + <xsl:param name="pageclass" select="''"/> + <xsl:param name="sequence" select="''"/> + <xsl:param name="gentext-key" select="''"/> + + <!-- default is a single table style for all headers --> + <!-- Customize it for different page classes or sequence location --> + + <xsl:choose> + <xsl:when test="$pageclass = 'index'"> + <xsl:attribute name="margin-left">0pt</xsl:attribute> + </xsl:when> + </xsl:choose> + + <xsl:variable name="candidate"> + <fo:table table-layout="fixed" width="100%"> + <xsl:call-template name="head.sep.rule"> + <xsl:with-param name="pageclass" select="$pageclass"/> + <xsl:with-param name="sequence" select="$sequence"/> + <xsl:with-param name="gentext-key" select="$gentext-key"/> + </xsl:call-template> + + <fo:table-column column-number="1" + column-width="{$header.left.width}"/> + <fo:table-column column-number="2" + column-width="{$header.center.width}"/> + <fo:table-column column-number="3" + column-width="{$header.right.width}"/> + <fo:table-body> + <fo:table-row height="14pt"> + <fo:table-cell text-align="left" display-align="before"> + <xsl:if test="$fop.extensions = 0"> + <xsl:attribute name="relative-align">baseline</xsl:attribute> + </xsl:if> + <fo:block> + <xsl:call-template name="header.content"> + <xsl:with-param name="pageclass" select="$pageclass"/> + <xsl:with-param name="sequence" select="$sequence"/> + <xsl:with-param name="position" select="'left'"/> + <xsl:with-param name="gentext-key" select="$gentext-key"/> + </xsl:call-template> + </fo:block> + </fo:table-cell> + <fo:table-cell text-align="center" display-align="before"> + <xsl:if test="$fop.extensions = 0"> + <xsl:attribute name="relative-align">baseline</xsl:attribute> + </xsl:if> + <fo:block> + <xsl:call-template name="header.content"> + <xsl:with-param name="pageclass" select="$pageclass"/> + <xsl:with-param name="sequence" select="$sequence"/> + <xsl:with-param name="position" select="'center'"/> + <xsl:with-param name="gentext-key" select="$gentext-key"/> + </xsl:call-template> + </fo:block> + </fo:table-cell> + <fo:table-cell text-align="right" display-align="before"> + <xsl:if test="$fop.extensions = 0"> + <xsl:attribute name="relative-align">baseline</xsl:attribute> + </xsl:if> + <fo:block> + <xsl:call-template name="header.content"> + <xsl:with-param name="pageclass" select="$pageclass"/> + <xsl:with-param name="sequence" select="$sequence"/> + <xsl:with-param name="position" select="'right'"/> + <xsl:with-param name="gentext-key" select="$gentext-key"/> + </xsl:call-template> + </fo:block> + </fo:table-cell> + </fo:table-row> + </fo:table-body> + </fo:table> + </xsl:variable> + + <!-- Really output a header? --> + <xsl:choose> + <xsl:when test="$pageclass = 'titlepage' and $gentext-key = 'book' + and $sequence='first'"> + <!-- no, book titlepages have no headers at all --> + </xsl:when> + <xsl:when test="($sequence = 'blank' and $headers.on.blank.pages = 0) + or ($sequence = 'first' and $headers.on.first.pages = 0)"> + <!-- no output --> + </xsl:when> + <xsl:otherwise> + <xsl:copy-of select="$candidate"/> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <!-- author and affiliation on the titlepage --> + <xsl:template match="author" mode="titlepage.mode"> + <fo:block xsl:use-attribute-sets="book.titlepage.author.properties"> + <xsl:call-template name="anchor"/> + <xsl:call-template name="person.name"/> + </fo:block> + <xsl:apply-templates select="affiliation" mode="titlepage.mode"/> + </xsl:template> + + <xsl:template match="affiliation" mode="titlepage.mode"> + <fo:block xsl:use-attribute-sets="book.titlepage.affiliation.properties"> + <xsl:for-each select="*"> + <xsl:if test="position() != 1"> + <xsl:text>, </xsl:text> + </xsl:if> + <xsl:apply-templates mode="titlepage.mode"/> + </xsl:for-each> + </fo:block> + </xsl:template> + + <!-- + * I am not sure about the purpose of this template; + * in FOP it causes an extra page, which is not blank. + --> + <xsl:template name="book.titlepage.separator"> + <!-- + <fo:block xmlns:fo="http://www.w3.org/1999/XSL/Format" break-after="page"/> +--> + </xsl:template> + + <!-- Add revhistory to the verso page --> + <xsl:template name="book.titlepage.verso"> + <xsl:choose> + <xsl:when test="bookinfo/title"> + <xsl:apply-templates mode="book.titlepage.verso.auto.mode" + select="bookinfo/title"/> + </xsl:when> + <xsl:when test="title"> + <xsl:apply-templates mode="book.titlepage.verso.auto.mode" + select="title"/> + </xsl:when> + </xsl:choose> + + <xsl:apply-templates mode="book.titlepage.verso.auto.mode" + select="bookinfo/corpauthor"/> + <xsl:apply-templates mode="book.titlepage.verso.auto.mode" + select="bookinfo/authorgroup"/> + <xsl:apply-templates mode="book.titlepage.verso.auto.mode" + select="bookinfo/author"/> + <xsl:apply-templates mode="book.titlepage.verso.auto.mode" + select="bookinfo/othercredit"/> + <xsl:apply-templates mode="book.titlepage.verso.auto.mode" + select="bookinfo/pubdate"/> + <xsl:apply-templates mode="book.titlepage.verso.auto.mode" + select="bookinfo/copyright"/> + <xsl:apply-templates mode="book.titlepage.verso.auto.mode" + select="bookinfo/abstract"/> + <xsl:apply-templates mode="book.titlepage.verso.auto.mode" + select="bookinfo/revhistory"/> + <xsl:apply-templates mode="book.titlepage.verso.auto.mode" + select="bookinfo/legalnotice"/> + </xsl:template> + + <xsl:template match="revhistory" mode="book.titlepage.verso.auto.mode"> + <fo:block xsl:use-attribute-sets="book.titlepage.verso.style + normal.para.spacing"> + <xsl:apply-templates select="." mode="book.titlepage.verso.mode"/> + </fo:block> + </xsl:template> + +</xsl:stylesheet> diff --git a/src/documentation/content/xdocs/DnI/cust-html-docbook.xsl b/src/documentation/content/xdocs/DnI/cust-html-docbook.xsl new file mode 100644 index 000000000..ce688571e --- /dev/null +++ b/src/documentation/content/xdocs/DnI/cust-html-docbook.xsl @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * Copyright 2004 The Apache Software Foundation. + * + * Licensed 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$ --> + +<xsl:stylesheet + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + version="1.0"> + + <xsl:import + href="http://cvs.sourceforge.net/viewcvs.py/*checkout*/docbook/xsl/html/chunk.xsl"/> + <!-- Use this import if you do not want chunks --> + <!-- + <xsl:import + href="http://cvs.sourceforge.net/viewcvs.py/*checkout*/docbook/xsl/html/docbook.xsl"/> +--> + + <xsl:param name="chunk.section.depth" select="2"/> + <xsl:param name="section.autolabel" select="1"/> + <xsl:param name="base.dir" select="'DnI-html/'"/> + +</xsl:stylesheet> diff --git a/src/documentation/content/xdocs/DnI/cust-xhtml-docbook.xsl b/src/documentation/content/xdocs/DnI/cust-xhtml-docbook.xsl new file mode 100644 index 000000000..0bfb38d6d --- /dev/null +++ b/src/documentation/content/xdocs/DnI/cust-xhtml-docbook.xsl @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * Copyright 2004 The Apache Software Foundation. + * + * Licensed 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$ --> + +<xsl:stylesheet + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns="http://www.w3.org/1999/xhtml" + version="1.0"> + + <xsl:import + href="http://cvs.sourceforge.net/viewcvs.py/*checkout*/docbook/xsl/xhtml/chunk.xsl"/> + + <!-- Use this import if you do not want chunks --> + <!-- + <xsl:import + href="http://cvs.sourceforge.net/viewcvs.py/*checkout*/docbook/xsl/xhtml/docbook.xsl"/> +--> + + <xsl:param name="chunker.output.encoding" select="'UTF-8'"/> + <xsl:param name="chunk.section.depth" select="2"/> + <xsl:param name="section.autolabel" select="1"/> + <xsl:param name="base.dir" select="'DnI-xhtml/'"/> + +</xsl:stylesheet> diff --git a/src/documentation/content/xdocs/DnI/fonts.xml b/src/documentation/content/xdocs/DnI/fonts.xml new file mode 100644 index 000000000..7c2b97263 --- /dev/null +++ b/src/documentation/content/xdocs/DnI/fonts.xml @@ -0,0 +1,297 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * Copyright 2004 The Apache Software Foundation. + * + * Licensed 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$ --> + +<!-- +<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" + "docbookx.dtd"> + --> + + <chapter> + <title>Fonts</title> + + <section> + <title>Font setup</title> + + <para>Terminology: +<itemizedlist> + <listitem> + <simpara>Index, font index: The index of a character in a +font, i.e. the place of the glyph for a character in a font.</simpara> + </listitem> + <listitem> + <simpara>Code point: The same as font index.</simpara> + </listitem> + <listitem> + <simpara>Character value: The two-byte +(<literal>char</literal>) value by which a character is represented in +memory and in Unicode. Note that this only works straightforwardly for +the basal plane (BMP) of Unicode, i.e. for <literal>characters <= +0xFFFF</literal>.</simpara> + </listitem> + <listitem> + <simpara>Unicode code point: The same as the character +value.</simpara> + </listitem> + </itemizedlist></para> + + <para>During compilation for each of the 14 base fonts a class is +generated from the XML font metric files. Each font class contains +the metric information and an encoding table (a +<literal>CodePointMapping</literal> object). The metric information is +static, the encoding table is an object member.</para> + + <para>During compilation also a class +<literal>CodePointMapping</literal> is generated, which contains the +known encodings as static values. For each known encoding it contains +a table as a static final array of int. The array holds an alternation +of font index and character value; in fact it is a mapping from +<literal>table[2i]</literal> to <literal>table[2i+1]</literal>, where +<literal>table[2i]</literal> is the font index and +<literal>table[2i+1]</literal> is the character.</para> + + <para>When an encoding is needed in the process, a +<literal>CodePointMapping</literal> object is created from the +encoding table. It contains a table (<literal>char array</literal>) +called <literal>latin1Map</literal> of the font indices for the +characters of the Latin1 range (<literal>0-0xFF</literal>) in +character value order. It also contains two tables (<literal>char +array</literal>s), called characters and codepoints, for the higher +character values. The table characters contains the character values +in order, and the table codepoints contains the corresponding font +indexes for this encoding in the same order. The characters can be +retrieved from these tables as follows: + +<screen>char <= 0xFF: index = latin1Map[character] +char > 0xFF: + find i such that characters[i] == char; + then index = codepoints[i] +</screen></para> + + <para>In the code the characters are retrieved from the +<literal>CodePointMapping</literal> object with its method +<literal>mapChar(char c)</literal>.</para> + + <para>In FOP's preparation stage the fonts are set up in the +method <literal>Driver.getContentHandler</literal>. It calls the +<literal>renderer</literal>'s method +<literal>setupFontInfo(currentDocument)</literal>. The +<literal>Document</literal> object <literal>currentDocument</literal> +(which is the <literal>foTreeControl</literal> object) is able to +store the font setup info and has methods to access the fonts +registered with it.</para> + +<para>The <literal>PrintRenderer</literal> (PostScript and PDF) then +calls <literal>FontSetup.setup(fontInfo, fontList)</literal>, where +<literal>fontInfo</literal> is <literal>the</literal> Document object +and <literal>fontList</literal> is the list of user configured fonts +registered with the <literal>renderer</literal> in its member +<literal>fontList</literal>. + <screen> + [1] org.apache.fop.fonts.FontSetup.setup (FontSetup.java:98) + [2] org.apache.fop.render.PrintRenderer.setupFontInfo (PrintRenderer.java:77) + [3] org.apache.fop.apps.Driver.getContentHandler (Driver.java:551) + [4] org.apache.fop.apps.Driver.render (Driver.java:602) + [5] org.apache.fop.apps.Driver.render (Driver.java:589) + [6] org.apache.fop.apps.Fop.main (Fop.java:102) +</screen></para> + + <para><literal>FontSetup.setup</literal> takes three actions: +<orderedlist> + <listitem> + <simpara>An object is created for each of the base 14 fonts +and registered with the <literal>fontInfo</literal> object in its +member fonts.</simpara> + </listitem> + <listitem> + <simpara>A series of triplets (family, style, weight) is set +up. To each triplet a font is assigned; this font will be used when a +font with the characteristics of that triplet is requested. The +triplets registered with <literal>fontInfo</literal> in its member +<literal>triplets</literal>. The member <literal>triplets</literal> is +a map which uses a string of the form +<literal>family,style,weight</literal> as a key. There is also a class +<literal>FontTriplet</literal>, which is not used.</simpara> + </listitem> + + <listitem> + <simpara>The user configured fonts are added.</simpara> + </listitem> + </orderedlist></para> + + <para>In the following listing <literal>treeBuilder</literal> is +the tree builder object set up in the preparation stage, and +<literal>foTreeControl</literal> is the document object. The list of +user configured fonts of the <literal>renderer</literal> is empty, and +the list of used fonts is still empty. + +<screen> + treeBuilder.foTreeControl.fonts = "{ + F1=org.apache.fop.fonts.base14.Helvetica@e3c624, + F2=org.apache.fop.fonts.base14.HelveticaOblique@e020c9, + F3=org.apache.fop.fonts.base14.HelveticaBold@13e58d4, + F4=org.apache.fop.fonts.base14.HelveticaBoldOblique@15a6029, + F5=org.apache.fop.fonts.base14.TimesRoman@17494c8, + F6=org.apache.fop.fonts.base14.TimesItalic@1e57e8f, + F7=org.apache.fop.fonts.base14.TimesBold@888e6c, + F8=org.apache.fop.fonts.base14.TimesBoldItalic@d3db51, + F9=org.apache.fop.fonts.base14.Courier@5f6303, + F10=org.apache.fop.fonts.base14.CourierOblique@117f31e, + F11=org.apache.fop.fonts.base14.CourierBold@1d7fbfb, + F12=org.apache.fop.fonts.base14.CourierBoldOblique@5d9084 + F13=org.apache.fop.fonts.base14.Symbol@39e5b5, + F14=org.apache.fop.fonts.base14.ZapfDingbats@1b5998f, +}" +</screen> + +<screen> + treeBuilder.foTreeControl.triplets = "{ + Computer-Modern-Typewriter,normal,400=F9, + Courier,italic,400=F10, + Courier,italic,700=F12, + Courier,normal,400=F9, + Courier,normal,700=F11, + Courier,oblique,400=F10, + Courier,oblique,700=F12, + Helvetica,italic,400=F2, + Helvetica,italic,700=F4, + Helvetica,normal,400=F1, + Helvetica,normal,700=F3, + Helvetica,oblique,400=F2, + Helvetica,oblique,700=F4, + Symbol,normal,400=F13, + Times Roman,italic,400=F6, + Times Roman,italic,700=F8, + Times Roman,normal,400=F5, + Times Roman,normal,700=F7, + Times Roman,oblique,400=F6, + Times Roman,oblique,700=F8, + Times,italic,400=F6, + Times,italic,700=F8, + Times,normal,400=F5, + Times,normal,700=F7, + Times,oblique,400=F6, + Times,oblique,700=F8, + Times-Roman,italic,400=F6, + Times-Roman,italic,700=F8, + Times-Roman,normal,400=F5, + Times-Roman,normal,700=F7, + Times-Roman,oblique,400=F6, + Times-Roman,oblique,700=F8, + ZapfDingbats,normal,400=F14, + any,italic,400=F6, + any,italic,700=F8, + any,normal,400=F5, + any,normal,700=F7, + any,oblique,400=F6, + any,oblique,700=F8, + monospace,italic,400=F10, + monospace,italic,700=F12, + monospace,normal,400=F9, + monospace,normal,700=F11, + monospace,oblique,400=F10, + monospace,oblique,700=F12, + sans-serif,italic,400=F2, + sans-serif,italic,700=F4, + sans-serif,normal,400=F1, + sans-serif,normal,700=F3, + sans-serif,oblique,400=F2, + sans-serif,oblique,700=F4, + serif,italic,400=F6, + serif,italic,700=F8, + serif,normal,400=F5, + serif,normal,700=F7, + serif,oblique,400=F6 + serif,oblique,700=F8, +}" +</screen> + +<screen> + treeBuilder.foTreeControl.atModel.renderer.fontList = null + treeBuilder.foTreeControl.usedFonts = "{}" +</screen></para> + + <para>User configured fonts should be listed in the member +<literal>fontList</literal> of the <literal>renderer</literal>. The +objects in the list are <literal>EmbedFontInfo</literal> objects. They +are created from the path to the metrics file, boolean kerning, the +list of triplets for which this font may be used, the path to the font +file. The triplets are <literal>FontTriplet</literal> objects. The +list may be created from an Avalon configuration object with +<literal>FontSetup.buildFontListFromConfiguration(Configuration +cfg)</literal>.</para> + + <para><literal>>FontSetup.addConfiguredFonts</literal> creates a +<literal>LazyFont</literal> font object from each +<literal>EmbedFontInfo</literal> object. <literal>LazyFont</literal> +fonts are not loaded until they are actually used. This makes it +possible to register a large number of fonts at low cost.</para> + + <para>Font weights are integers between 100 and 900. +<literal>Font.NORMAL</literal> and <literal>Font.BOLD</literal> are +set to 400 and 700, respectively. See +<literal>FontUtil.parseCSS2FontWeight</literal>.</para> + + </section> + + <section> + <title>Classes and interfaces used in the font package</title> + + <screen>IF FontMetrics +SubIF FontDescriptor + +IF MutableFont + +Abstract Class TypeFace: FontMetrics +Classes Courier etc. + +Abstract Class TypeFace: FontMetrics +Abstract Class CustomFont: FontDescriptor, MutableFont +Abstract Class CIDFont, Class SingleByteFont +Class MultiByteFont (sub CIDFont) + +Abstract Class TypeFace: FontMetrics +Abstract Class CustomFont: FontDescriptor, MutableFont +Class SingleByteFont + +Abstract Class TypeFace: FontMetrics +Class LazyFont: FontDescriptor + +Abstract Class TypeFace: FontMetrics +Class FontMetricsMapper, for AWT fonts +</screen> + + <para><literal>SingleByteFont</literal>, +<literal>MultiByteFont</literal>: A font is not really single or +multibyte. Rather the name <literal>SingleByteFont</literal> indicates +that the font does not contain more than 256 glyphs; the +implementation is optimized for this. In +<literal>MultiByteFont</literal> (actually CIDFont Type2) the +implementation is optimized for fonts with an unknown number of +glyphs.</para> + + </section> + + </chapter> + +<!-- Local Variables: --> +<!-- current-language-environment: UTF-8 --> +<!-- coding: utf-8 --> +<!-- default-input-method: TeX --> +<!-- End: --> diff --git a/src/documentation/content/xdocs/DnI/foptrees.xml b/src/documentation/content/xdocs/DnI/foptrees.xml new file mode 100644 index 000000000..46c70b11c --- /dev/null +++ b/src/documentation/content/xdocs/DnI/foptrees.xml @@ -0,0 +1,1065 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * Copyright 2004 The Apache Software Foundation. + * + * Licensed 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$ --> + +<!-- +<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" + "docbookx.dtd"> + --> + + <chapter> + <title>The trees in FOP</title> + + <section> + <title>Overview</title> + + <orderedlist> + <listitem> + <simpara>The FO document. Each XML document and therefore +also an FO document has a hierarchical structure that can be modeled +as a tree.</simpara> + </listitem> + + <listitem> + <simpara>The FO DOM tree. This tree has the same +hierarchical structure as an FO document, and is often built from an +XML document.</simpara> + </listitem> + </orderedlist> + + <para>FOP can work from either an FO document or an FO DOM tree. +FOP does not build a DOM tree from an FO document.</para> + + <orderedlist continuation="continues"> + <listitem> + <simpara>The FO tree. FOP builds this tree from either the FO document or +the FO DOM tree. The FO nodes in this tree correspond to the +elements in the FO document or the XML nodes in the FO DOM +tree. Note, however, that they are different from DOM tree +nodes.</simpara> + </listitem> + </orderedlist> + + <para>When a sufficient part of the FO tree has been built (in +current FOP the subtree of a PageSequence FO node), the layout process +is started. This process builds three trees.</para> + + <orderedlist continuation="continues"> + <listitem> + <simpara>The LM tree. This tree corresponds closely to the FO +tree because each FO node creates a layout manager. But there are +deviations. For example, a BlockLayoutManager creates a +LineLayoutManager for each consecutive sequence of child FO nodes that +generate inline areas.</simpara> + </listitem> + + <listitem> + <simpara>The BP tree. Each layout manager returns zero or more +BreakPoss to its parent. These BreakPoss are connected to BreakPoss +that the layout manager received from its child layout managers. This +is not a real tree. There are many BP without a parent BP. They are +connected to their siblings by their LM.</simpara> + </listitem> + + <listitem> + <simpara>The Area tree. Using the information stored in the BP +tree and in the LMs connected with the BPs, layout areas are +constructed. These areas are placed within other areas, which is +expressed in a tree hierarchy.</simpara> + </listitem> + </orderedlist> + + </section> + + <section> + <title>The tree of BreakPoss</title> + + <para>Each LM contains a list of BPs belonging to and returned +to it by the childLMs during the <literal>getNextBreakPoss</literal> +stack. These are the BPs that end an area of the childLM. The BP +contains an index <literal>position.iLeafPos</literal>, which connects +it to the BP with that index in the list of BPs of its own LM (the +childLM).</para> + + <para>For example, BlockLM's list <literal>childBreaks</literal> +contains the BPs that end a line (if the childLM is a LineLM). +LineLM's list <literal>vecInlineBreaks</literal> contains the BPs that +were returned to it as possible linebreaks by TextLM (if the childLM +is a TextLM). TextLM's list <literal>vecAreaInfo</literal> contains +<literal>AreaInfo</literal> objects. A BP in BlockLM's list +<literal>childBreaks</literal> belongs e.g. to a LineLM. Its index +<literal>position.iLeafPos</literal> points to the BP with that index +in <literal>vecInlineBreaks</literal> in ListLM. That BP belongs e.g. +to a TextLM, and its index <literal>position.iLeafPos</literal> points +to the <literal>AreaInfo</literal> object with that index in +<literal>vecAreaInfo</literal> in TextLM.</para> + + <screen> + +-----------------+ + LM | bp0 bp1 bp2 bp3 | + +-++--++--++--++--+ + .......................:|..:| :| :| + : +----------+ | :| :| + : | +----------+ :| :+----------------------+ + : | | ........:| :....... | + : | | : | : | + : +----------+---+--+ : +------+------+ : +--------------+------+ + LM | bp0 bp1 bp2 bp3 | LM | bp0 bp1 bp2 | LM | bp0 bp1 bp2 bp3 bp4 | + +-----------------+ +-------------+ +---------------------+ +</screen> + + <para>The BPs are held in a list by the LM shown in front of +them. They are associated with one of the childLMs, which is shown by +the dotted lines. Their member <literal>position.iLeafPos</literal> +connects them with the BP in their LM's list with that index, as shown +by the dashed lines.</para> + + </section> + + + <section> + <title>Example of an FO and area tree</title> + + <section> + <title>The FO file</title> + + <literallayout><![CDATA[<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" + xmlns:svg="http://www.w3.org/2000/svg"> + <fo:layout-master-set> + <fo:simple-page-master master-name="simpleA4" + page-height="29.7cm" page-width="21cm" + margin-top="2cm" + margin-bottom="2cm" margin-left="2cm" + margin-right="2cm"> + <fo:region-body/> + </fo:simple-page-master> + </fo:layout-master-set> + <fo:page-sequence master-reference="simpleA4"> + <fo:flow flow-name="xsl-region-body"> + <fo:block font-size="16pt" font-weight="bold" + space-after="5mm">Test FO + </fo:block> + </fo:flow> + </fo:page-sequence> +</fo:root>]]></literallayout> + + </section> + + <section> + <title>The corresponding FO tree</title> + + <para>In the listing below the notation has been shortened; +<literal>.[n]</literal> denotes the nth child, for which the full +notation is <literal>.children.elementData[n]</literal> . A number of +static members are not shown.</para> + + <para>The root: + +<screen> + root = "fo:root at line 2:44" + + root = { + layoutMasterSet: instance of org.apache.fop.fo.pagination.LayoutMasterSet(id=1089) + pageSequences: instance of java.util.ArrayList(id=1102) + runningPageNumberCounter: 0 + foTreeControl: instance of org.apache.fop.apps.Document(id=1103) + org.apache.fop.fo.FObj.propertyListTable: instance of org.apache.fop.fo.Property$Maker[248] (id=1094) + org.apache.fop.fo.FObj.propertyList: instance of org.apache.fop.fo.PropertyList(id=1104) + org.apache.fop.fo.FObj.propMgr: instance of org.apache.fop.fo.PropertyManager(id=1105) + org.apache.fop.fo.FObj.id: null + org.apache.fop.fo.FObj.children: instance of java.util.ArrayList(id=1106) + org.apache.fop.fo.FObj.markers: null + org.apache.fop.fo.FObj.systemId: "file:/path/to/fo-file" + org.apache.fop.fo.FObj.line: 2 + org.apache.fop.fo.FObj.column: 44 + org.apache.fop.fo.FONode.parent: null + org.apache.fop.fo.FONode.name: "fo:root" +} +</screen> +</para> + + <para>The root has no properties; the namespace nodes do not result in +properties: + +<screen> + root.propertyList = "{}" +</screen> +</para> + + <para>The root has two children: + +<screen> + root.children = "[ + fo:layout-master-set at line 3:25 + fo:page-sequence at line 12:49 +]" +</screen> +</para> + + <para>The first child of root is the layout master set: + +<screen> + root.[0] = "fo:layout-master-set at line 3:25" + + root.[0] = { + simplePageMasters: instance of java.util.HashMap(id=1111) + pageSequenceMasters: instance of java.util.HashMap(id=1112) + org.apache.fop.fo.FObj.propertyListTable: instance of org.apache.fop.fo.Property$Maker[248] (id=1094) + org.apache.fop.fo.FObj.propertyList: instance of org.apache.fop.fo.PropertyList(id=1113) + org.apache.fop.fo.FObj.propMgr: instance of org.apache.fop.fo.PropertyManager(id=1114) + org.apache.fop.fo.FObj.id: null + org.apache.fop.fo.FObj.children: instance of java.util.ArrayList(id=1115) + org.apache.fop.fo.FObj.markers: null + org.apache.fop.fo.FObj.systemId: "file:/path/to/fo-file" + org.apache.fop.fo.FObj.line: 3 + org.apache.fop.fo.FObj.column: 25 + org.apache.fop.fo.FONode.parent: instance of org.apache.fop.fo.pagination.Root(id=1088) + org.apache.fop.fo.FONode.name: "fo:layout-master-set" +} + + root.[0].propertyList = "{}" +</screen> +</para> + + <para>The layout master set contains a simple page master: + +<screen> + root.[0].children = "[ + fo:simple-page-master at line 8:28 +]" + + root.[0].[0] = "fo:simple-page-master at line 8:28" + + root.[0].[0] = { + regions: instance of java.util.HashMap(id=1120) + masterName: "simpleA4" + org.apache.fop.fo.FObj.propertyListTable: instance of org.apache.fop.fo.Property$Maker[248] (id=1094) + org.apache.fop.fo.FObj.propertyList: instance of org.apache.fop.fo.PropertyList(id=1122) + org.apache.fop.fo.FObj.propMgr: instance of org.apache.fop.fo.PropertyManager(id=1123) + org.apache.fop.fo.FObj.id: null + org.apache.fop.fo.FObj.children: null + org.apache.fop.fo.FObj.markers: null + org.apache.fop.fo.FObj.systemId: "file:/path/to/fo-file" + org.apache.fop.fo.FObj.line: 8 + org.apache.fop.fo.FObj.column: 28 + org.apache.fop.fo.FONode.parent: instance of org.apache.fop.fo.pagination.LayoutMasterSet(id=1089) + org.apache.fop.fo.FONode.name: "fo:simple-page-master" +} +</screen> +</para> + + <para>The properties of the simple page master: + +<screen> + root.[0].[0].propertyList = "{ + master-name=org.apache.fop.fo.StringProperty@1958bf9 + margin-top=org.apache.fop.fo.LengthProperty@118958e + margin-right=org.apache.fop.fo.LengthProperty@102b2b6 + margin-bottom=org.apache.fop.fo.LengthProperty@22d166 + margin-left=org.apache.fop.fo.LengthProperty@1e1962d + page-width=org.apache.fop.fo.LengthProperty@14a75bb + page-height=org.apache.fop.fo.LengthProperty@17779e3 +}" + + root.[0].[0].propertyList.get("master-name") = { + str: "simpleA4" + org.apache.fop.fo.Property.specVal: null +} + + root.[0].[0].propertyList.get("page-height") = { + length: instance of org.apache.fop.datatypes.FixedLength(id=1329) + org.apache.fop.fo.Property.specVal: null +} + + root.[0].[0].propertyList.get("page-height").length = "841889mpt" +</screen> +</para> + + <para>The simple page master has only one region, the body: + +<screen> + root.[0].[0].regions = "{body=fo:region-body at line 9:24}" +</screen> +</para> + + <para>The region body: + +<screen> + root.[0].[0].regions.get("body") = "fo:region-body at line 9:24" + + root.[0].[0].regions.get("body") = { + backgroundColor: null + org.apache.fop.fo.pagination.Region.layoutMaster: instance of org.apache.fop.fo.pagination.SimplePageMaster(id=1082) + org.apache.fop.fo.pagination.Region.regionName: "xsl-region-body" + org.apache.fop.fo.pagination.Region.overflow: 8 + org.apache.fop.fo.pagination.Region.wm: 49 + org.apache.fop.fo.FObj.propertyListTable: instance of org.apache.fop.fo.Property$Maker[248] (id=1094) + org.apache.fop.fo.FObj.propertyList: instance of org.apache.fop.fo.PropertyList(id=1344) + org.apache.fop.fo.FObj.propMgr: instance of org.apache.fop.fo.PropertyManager(id=1345) + org.apache.fop.fo.FObj.id: null + org.apache.fop.fo.FObj.children: null + org.apache.fop.fo.FObj.markers: null + org.apache.fop.fo.FObj.systemId: "file:/path/to/fo-file" + org.apache.fop.fo.FObj.line: 9 + org.apache.fop.fo.FObj.column: 24 + org.apache.fop.fo.FONode.parent: instance of org.apache.fop.fo.pagination.SimplePageMaster(id=1082) + org.apache.fop.fo.FONode.name: "fo:region-body" +} + + root.[0].[0].regions.get("body").propertyList = "{}" +</screen> +</para> + + <para>The second child of root is the page sequence: + +<screen> + root.[1] = "fo:page-sequence at line 12:49" + + root.[1] = { + root: instance of org.apache.fop.fo.pagination.Root(id=1088) + layoutMasterSet: instance of org.apache.fop.fo.pagination.LayoutMasterSet(id=1089) + flowMap: instance of java.util.HashMap(id=1090) + sequenceStarted: true + ipnValue: "auto" + currentPageNumber: 1 + explicitFirstNumber: 0 + firstPageNumber: 1 + pageNumberGenerator: instance of org.apache.fop.fo.pagination.PageNumberGenerator(id=1074) + forcePageCount: 8 + pageCount: 0 + isForcing: false + pageNumberType: 1 + thisIsFirstPage: true + simplePageMaster: instance of org.apache.fop.fo.pagination.SimplePageMaster(id=1082) + pageSequenceMaster: null + mainFlow: instance of org.apache.fop.fo.pagination.Flow(id=1092) + titleFO: null + org.apache.fop.fo.FObj.propertyListTable: instance of org.apache.fop.fo.Property$Maker[248] (id=1094) + org.apache.fop.fo.FObj.propertyList: instance of org.apache.fop.fo.PropertyList(id=1096) + org.apache.fop.fo.FObj.propMgr: instance of org.apache.fop.fo.PropertyManager(id=1097) + org.apache.fop.fo.FObj.id: null + org.apache.fop.fo.FObj.children: instance of java.util.ArrayList(id=1098) + org.apache.fop.fo.FObj.markers: null + org.apache.fop.fo.FObj.systemId: "file:/path/to/fo-file" + org.apache.fop.fo.FObj.line: 12 + org.apache.fop.fo.FObj.column: 49 + org.apache.fop.fo.FONode.parent: instance of org.apache.fop.fo.pagination.Root(id=1088) + org.apache.fop.fo.FONode.name: "fo:page-sequence" +} +</screen> +</para> + + <para>The page-sequence has one property, the reference to the page master: + +<screen> + root.[1].propertyList = "{ + master-reference=org.apache.fop.fo.StringProperty@104e28b +}" + + root.[1].propertyList.get("master-reference") = { + str: "simpleA4" + org.apache.fop.fo.Property.specVal: null +} +</screen> +</para> + + <para>The page-sequence has one child, the flow: + +<screen> + root.[1].children = "[ + fo:flow at line 13:42 +]" + + root.[1].[0] = "fo:flow at line 13:42" + + root.[1].[0] = { + pageSequence: instance of org.apache.fop.fo.pagination.PageSequence(id=1081) + markerSnapshot: null + flowName: "xsl-region-body" + contentWidth: 0 + org.apache.fop.fo.FObj.propertyListTable: instance of org.apache.fop.fo.Property$Maker[248] (id=1094) + org.apache.fop.fo.FObj.propertyList: instance of org.apache.fop.fo.PropertyList(id=1367) + org.apache.fop.fo.FObj.propMgr: instance of org.apache.fop.fo.PropertyManager(id=1368) + org.apache.fop.fo.FObj.id: null + org.apache.fop.fo.FObj.children: instance of java.util.ArrayList(id=1369) + org.apache.fop.fo.FObj.markers: null + org.apache.fop.fo.FObj.systemId: "file:/path/to/fo-file" + org.apache.fop.fo.FObj.line: 13 + org.apache.fop.fo.FObj.column: 42 + org.apache.fop.fo.FONode.parent: instance of org.apache.fop.fo.pagination.PageSequence(id=1081) + org.apache.fop.fo.FONode.name: "fo:flow" +} +</screen> +</para> + + <para>The flow has one property, the flow name: + +<screen> + root.[1].[0].propertyList = "{ + flow-name=org.apache.fop.fo.StringProperty@6458a6 +}" + + root.[1].[0].propertyList.get("flow-name") = { + str: "xsl-region-body" + org.apache.fop.fo.Property.specVal: null +} +</screen> +</para> + + <para>The flow has one child, a block: + +<screen> + root.children.elementData[1].children.elementData[0].children = "[ + fo:block at line 15:28 +]" + + root.[1].[0].[0] = "fo:block at line 15:28" + + root.[1].[0].[0] = { + align: 0 + alignLast: 0 + breakAfter: 0 + lineHeight: 0 + startIndent: 0 + endIndent: 0 + spaceBefore: 0 + spaceAfter: 0 + textIndent: 0 + keepWithNext: 0 + backgroundColor: null + blockWidows: 0 + blockOrphans: 0 + id: null + span: 59 + wsTreatment: 41 + lfTreatment: 98 + bWScollapse: true + anythingLaidOut: false + firstInlineChild: null + org.apache.fop.fo.FObjMixed.textInfo: instance of org.apache.fop.fo.TextInfo(id=1377) + org.apache.fop.fo.FObj.propertyListTable: instance of org.apache.fop.fo.Property$Maker[248] (id=1094) + org.apache.fop.fo.FObj.propertyList: instance of org.apache.fop.fo.PropertyList(id=1378) + org.apache.fop.fo.FObj.propMgr: instance of org.apache.fop.fo.PropertyManager(id=1379) + org.apache.fop.fo.FObj.id: null + org.apache.fop.fo.FObj.children: instance of java.util.ArrayList(id=1380) + org.apache.fop.fo.FObj.markers: null + org.apache.fop.fo.FObj.systemId: "file:/path/to/fo-file" + org.apache.fop.fo.FObj.line: 15 + org.apache.fop.fo.FObj.column: 28 + org.apache.fop.fo.FONode.parent: instance of org.apache.fop.fo.pagination.Flow(id=1092) + org.apache.fop.fo.FONode.name: "fo:block" +} + + root.[1].[0].[0].propertyList = "{ + font-size=org.apache.fop.fo.LengthProperty@ae4646 + font-weight=org.apache.fop.fo.StringProperty@187b287 + space-after=org.apache.fop.fo.SpaceProperty@1d9e2c7 +}" +</screen> +</para> + + <para>The block has two children: + +<screen> + root.[1].[0].[0].children = "[ + fo:text at line 15:35 + fo:text at line 16:7 +]" + + root.[1].[0].[0].[0] = "fo:text at line 15:35" + + root.[1].[0].[0].[0] = { + ca: instance of char[7] (id=1386) + start: 0 + length: 7 + textInfo: instance of org.apache.fop.fo.TextInfo(id=1377) + lastFOTextProcessed: instance of org.apache.fop.fo.FOText(id=1387) + prevFOTextThisBlock: null + nextFOTextThisBlock: instance of org.apache.fop.fo.FOText(id=1387) + ancestorBlock: instance of org.apache.fop.fo.flow.Block(id=1375) + org.apache.fop.fo.FObj.propertyListTable: instance of org.apache.fop.fo.Property$Maker[248] (id=1094) + org.apache.fop.fo.FObj.propertyList: null + org.apache.fop.fo.FObj.propMgr: null + org.apache.fop.fo.FObj.id: null + org.apache.fop.fo.FObj.children: null + org.apache.fop.fo.FObj.markers: null + org.apache.fop.fo.FObj.systemId: "file:/path/to/fo-file" + org.apache.fop.fo.FObj.line: 15 + org.apache.fop.fo.FObj.column: 35 + org.apache.fop.fo.FONode.parent: instance of org.apache.fop.fo.flow.Block(id=1375) + org.apache.fop.fo.FONode.name: "fo:text" +} +</screen> +</para> + + <para>This text node contains the text "Test FO": + +<screen> + root.[1].[0].[0].[0].ca = { +T, e, s, t, , F, O +} + + root.[1].[0].[0].[1] = "fo:text at line 16:7" + + root.[1].[0].[0].[1] = { + ca: instance of char[1] (id=1390) + start: 0 + length: 1 + textInfo: instance of org.apache.fop.fo.TextInfo(id=1377) + lastFOTextProcessed: instance of org.apache.fop.fo.FOText(id=1387) + prevFOTextThisBlock: instance of org.apache.fop.fo.FOText(id=1384) + nextFOTextThisBlock: null + ancestorBlock: instance of org.apache.fop.fo.flow.Block(id=1375) + org.apache.fop.fo.FObj.propertyListTable: instance of org.apache.fop.fo.Property$Maker[248] (id=1094) + org.apache.fop.fo.FObj.propertyList: null + org.apache.fop.fo.FObj.propMgr: null + org.apache.fop.fo.FObj.id: null + org.apache.fop.fo.FObj.children: null + org.apache.fop.fo.FObj.markers: null + org.apache.fop.fo.FObj.systemId: "file:/path/to/fo-file" + org.apache.fop.fo.FObj.line: 16 + org.apache.fop.fo.FObj.column: 7 + org.apache.fop.fo.FONode.parent: instance of org.apache.fop.fo.flow.Block(id=1375) + org.apache.fop.fo.FONode.name: "fo:text" +} +</screen> +</para> + + <para>This text node contains the text "\n": + +<screen> + root.[1].[0].[0].[1].ca = { +} +</screen> +</para> + </section> + + <section> + <title>The corresponding area tree</title> + + <para><itemizedlist> + <listitem> + <simpara>PageViewport has a Page page and a Rectangle2D +viewArea (reference/viewport pair).</simpara> + </listitem> + <listitem> + <simpara>Page has five RegionViewports.</simpara> + </listitem> + <listitem> + <simpara>RegionViewport has a RegionReference region and a +Rectangle2D viewArea (reference/viewport pair).</simpara> + </listitem> + <listitem> + <simpara>BodyRegion has a MainReference mainReference, a +BeforeFloat beforeFloat, and a Footnote footnote.</simpara> + </listitem> + <listitem> + <simpara>MainReference has a list of Spans.</simpara> + </listitem> + <listitem> + <simpara>Span has a list of Flows.</simpara> + </listitem> + <listitem> + <simpara>Flow has a list of Blocks.</simpara> + </listitem> + <listitem> + <simpara>Block has a list of Blocks or LineAreas.</simpara> + </listitem> + <listitem> + <simpara>LineArea has a list of InlineAreas.</simpara> + </listitem> + <listitem> + <simpara>Text Area (subclass of InlineArea) has text.</simpara> + </listitem> + </itemizedlist></para> + + <para>The structure of the area tree is as follows: + +<screen> +PageViewport +| ++-Page + | + +-RegionViewport + | + +-BodyRegion + | + +-MainReference + | | + | +-Span + | | | + | | +-Flow + | | + | +-Span + | | | + | | +-Flow + | | | + | | +-Block + | | | | + | | | +-LineArea + | | | | + | | | +-TextArea + | | | + | | +-Block + | | + | +-Span + | | | + | | +-Flow + | | + | +-Span + | | | + | | +-Flow + | | + | +-Span + | | + | +-Flow + | + +blocks + | + +CTM +</screen> +</para> + + <para>In the listing below members of an +<literal>arraylist</literal> are indicated by <literal>[n]</literal>, +which stands for <literal>get(n)</literal>. If the +<literal>arraylist</literal> is called <literal>children</literal>, +the word <literal>children</literal> has been omitted, so that +<literal>[n]</literal> then stands for +<literal>children.get(n)</literal>.</para> + + <para>Type: <literal>org.apache.fop.area.PageViewport</literal>: +<screen> + curPage = "PageViewport: page=1" + + curPage = { + page: instance of org.apache.fop.area.Page(id=1394) + viewArea: instance of java.awt.Rectangle(id=1395) + clip: false + pageNumber: "1" + idReferences: null + unresolved: null + pendingResolved: null + markerFirstStart: null + markerLastStart: null + markerFirstAny: null + markerLastEnd: null + markerLastAny: null +} +</screen> +</para> + + <para>Type: <literal>org.apache.fop.area.Page</literal>: +<screen> + curPage.page = { + regionBefore: null + regionStart: null + regionBody: instance of org.apache.fop.area.RegionViewport(id=1397) + regionEnd: null + regionAfter: null + unresolved: null +} +</screen> +</para> + + <para>Type: <literal>org.apache.fop.area.RegionViewport</literal>: +<screen> + curPage.page.regionBody = { + region: instance of org.apache.fop.area.BodyRegion(id=1077) + viewArea: instance of java.awt.Rectangle(id=1399) + clip: false + org.apache.fop.area.Area.areaClass: 0 + org.apache.fop.area.Area.ipd: 0 + org.apache.fop.area.Area.props: null +} +</screen> +</para> + + <para>Type: <literal>org.apache.fop.area.BodyRegion</literal>: +<screen> + curPage.page.regionBody.region = { + beforeFloat: null + mainReference: instance of org.apache.fop.area.MainReference(id=1401) + footnote: null + columnGap: 18000 + columnCount: 1 + refIPD: 0 + org.apache.fop.area.RegionReference.regionClass: 2 + org.apache.fop.area.RegionReference.ctm: instance of org.apache.fop.area.CTM(id=1402) + org.apache.fop.area.RegionReference.blocks: instance of java.util.ArrayList(id=1403) + org.apache.fop.area.Area.areaClass: 0 + org.apache.fop.area.Area.ipd: 0 + org.apache.fop.area.Area.props: null +} +</screen> +</para> + + <para>Type: <literal>org.apache.fop.area.MainReference</literal>: +<screen> + curPage.page.regionBody.region.mainReference = { + spanAreas: instance of java.util.ArrayList(id=1405) + columnGap: 0 + width: 0 + org.apache.fop.area.Area.areaClass: 0 + org.apache.fop.area.Area.ipd: 0 + org.apache.fop.area.Area.props: null +} +</screen> +</para> + + <para>The main reference contains five span areas. Four are +empty. Number 1 contains the text of this page. + +<screen> + curPage.page.regionBody.region.mainReference.spanAreas = "[ + org.apache.fop.area.Span@53c3f5 + org.apache.fop.area.Span@101ac93 + org.apache.fop.area.Span@125d61e + org.apache.fop.area.Span@155d3a3 + org.apache.fop.area.Span@718242 +]" +</screen> +</para> + + <para>Type: <literal>org.apache.fop.area.Span</literal>: +<screen> + curPage.page.regionBody.region.mainReference.spanAreas[0] = { + flowAreas: instance of java.util.ArrayList(id=1409) + height: 0 + org.apache.fop.area.Area.areaClass: 0 + org.apache.fop.area.Area.ipd: 481891 + org.apache.fop.area.Area.props: null +} +</screen> +</para> + + <screen> + curPage.page.regionBody.region.mainReference.spanAreas[0].flowAreas = "[ + org.apache.fop.area.Flow@e33e18 +]" +</screen> + + <para>Type: <literal>org.apache.fop.area.Flow</literal>: +<screen> + curPage.page.regionBody.region.mainReference.spanAreas[0].flowAreas[0] = { + stacking: 2 + width: 0 + org.apache.fop.area.BlockParent.xOffset: 0 + org.apache.fop.area.BlockParent.yOffset: 0 + org.apache.fop.area.BlockParent.width: 0 + org.apache.fop.area.BlockParent.height: 0 + org.apache.fop.area.BlockParent.children: null + org.apache.fop.area.BlockParent.orientation: 0 + org.apache.fop.area.Area.areaClass: 0 + org.apache.fop.area.Area.ipd: 481891 + org.apache.fop.area.Area.props: null +} +</screen> +</para> + + <para>Type: <literal>org.apache.fop.area.Span</literal>: +<screen> + curPage.page.regionBody.region.mainReference.spanAreas[1] = { + flowAreas: instance of java.util.ArrayList(id=1412) + height: 0 + org.apache.fop.area.Area.areaClass: 0 + org.apache.fop.area.Area.ipd: 481891 + org.apache.fop.area.Area.props: null +} +</screen> +</para> + + <screen> + curPage.page.regionBody.region.mainReference.spanAreas[0].flowAreas = "[ + org.apache.fop.area.Flow@e33e18 +]" +</screen> + + <para>Type: <literal>org.apache.fop.area.Flow</literal>: +<screen> + curPage.page.regionBody.region.mainReference.spanAreas[1].flowAreas[0] = { + stacking: 2 + width: 0 + org.apache.fop.area.BlockParent.xOffset: 0 + org.apache.fop.area.BlockParent.yOffset: 0 + org.apache.fop.area.BlockParent.width: 0 + org.apache.fop.area.BlockParent.height: 0 + org.apache.fop.area.BlockParent.children: instance of java.util.ArrayList(id=1416) + org.apache.fop.area.BlockParent.orientation: 0 + org.apache.fop.area.Area.areaClass: 0 + org.apache.fop.area.Area.ipd: 481891 + org.apache.fop.area.Area.props: null +} +</screen> +</para> + + <screen> + curPage.page.regionBody.region.mainReference.spanAreas[1].flowAreas[0].children = "[ + org.apache.fop.area.Block@61f533 + org.apache.fop.area.Block@12922f6 +]" +</screen> + + <para>Type: <literal>org.apache.fop.area.Block</literal>: +<screen> + curPage.page.regionBody.region.mainReference.spanAreas[1].flowAreas[0].[0] = { + stacking: 2 + positioning: 0 + org.apache.fop.area.BlockParent.xOffset: 0 + org.apache.fop.area.BlockParent.yOffset: 0 + org.apache.fop.area.BlockParent.width: 481891 + org.apache.fop.area.BlockParent.height: 19200 + org.apache.fop.area.BlockParent.children: instance of java.util.ArrayList(id=1419) + org.apache.fop.area.BlockParent.orientation: 0 + org.apache.fop.area.Area.areaClass: 0 + org.apache.fop.area.Area.ipd: 481891 + org.apache.fop.area.Area.props: null +} +</screen> +</para> + + <screen> + curPage.page.regionBody.region.mainReference.spanAreas[1].flowAreas[0].[0].children = "[ + org.apache.fop.area.LineArea@9f0d +]" +</screen> + + <para>Type: <literal>org.apache.fop.area.LineArea</literal>: +<screen> + curPage.page.regionBody.region.mainReference.spanAreas[1].flowAreas[0].[0].[0] = { + stacking: 0 + startIndent: 0 + length: 0 + lineHeight: 19200 + baseLine: 0 + inlineAreas: instance of java.util.ArrayList(id=1422) + org.apache.fop.area.Area.areaClass: 0 + org.apache.fop.area.Area.ipd: 0 + org.apache.fop.area.Area.props: null +} +</screen> +</para> + + <screen> + curPage.page.regionBody.region.mainReference.spanAreas[1].flowAreas[0].[0].[0].inlineAreas = "[ + org.apache.fop.area.inline.TextArea@21d23b +]" +</screen> + + <para>Type: <literal>org.apache.fop.area.inline.TextArea</literal>: +<screen> + curPage.page.regionBody.region.mainReference.spanAreas[1].flowAreas[0].[0].[0].inlineAreas[0] = { + text: "Test FO" + iTSadjust: 0 + org.apache.fop.area.inline.InlineArea.height: 14800 + org.apache.fop.area.inline.InlineArea.contentIPD: 59568 + org.apache.fop.area.inline.InlineArea.verticalPosition: 13688 + org.apache.fop.area.Area.areaClass: 0 + org.apache.fop.area.Area.ipd: 0 + org.apache.fop.area.Area.props: instance of java.util.HashMap(id=1426) +} +</screen> +</para> + + <para> +<screen> + curPage.page.regionBody.region.mainReference.spanAreas[1].flowAreas[0].[0].[0].inlineAreas[0].props = "{ + 4=16000 + 3=F3 + 7=#000000 +}" +</screen> +<variablelist> + <varlistentry> + <term>3</term> + <listitem> + <simpara><literal>org.apache.fop.area.Trait.FONT_NAME</literal></simpara> + </listitem> + </varlistentry> + <varlistentry> + <term>4</term> + <listitem> + <simpara><literal>org.apache.fop.area.Trait.FONT_SIZE</literal></simpara> + </listitem> + </varlistentry> + <varlistentry> + <term>7</term> + <listitem> + <simpara><literal>org.apache.fop.area.Trait.COLOR</literal></simpara> + </listitem> + </varlistentry> + </variablelist> +</para> + + <para>Type: <literal>org.apache.fop.area.Block</literal>: +<screen> + curPage.page.regionBody.region.mainReference.spanAreas[1].flowAreas[0].[1] = { + stacking: 2 + positioning: 0 + org.apache.fop.area.BlockParent.xOffset: 0 + org.apache.fop.area.BlockParent.yOffset: 0 + org.apache.fop.area.BlockParent.width: 0 + org.apache.fop.area.BlockParent.height: 14173 + org.apache.fop.area.BlockParent.children: null + org.apache.fop.area.BlockParent.orientation: 0 + org.apache.fop.area.Area.areaClass: 0 + org.apache.fop.area.Area.ipd: 0 + org.apache.fop.area.Area.props: null +} +</screen> +</para> + + <para>Type: <literal>org.apache.fop.area.Span</literal>: +<screen> + curPage.page.regionBody.region.mainReference.spanAreas[2] = { + flowAreas: instance of java.util.ArrayList(id=1429) + height: 0 + org.apache.fop.area.Area.areaClass: 0 + org.apache.fop.area.Area.ipd: 481891 + org.apache.fop.area.Area.props: null +} +</screen> +</para> + + <screen> + curPage.page.regionBody.region.mainReference.spanAreas[2].flowAreas = "[ + org.apache.fop.area.Flow@c72243 +]" +</screen> + + <para>Type: <literal>org.apache.fop.area.Flow</literal>: +<screen> + curPage.page.regionBody.region.mainReference.spanAreas[2].flowAreas[0] = { + stacking: 2 + width: 0 + org.apache.fop.area.BlockParent.xOffset: 0 + org.apache.fop.area.BlockParent.yOffset: 0 + org.apache.fop.area.BlockParent.width: 0 + org.apache.fop.area.BlockParent.height: 0 + org.apache.fop.area.BlockParent.children: null + org.apache.fop.area.BlockParent.orientation: 0 + org.apache.fop.area.Area.areaClass: 0 + org.apache.fop.area.Area.ipd: 481891 + org.apache.fop.area.Area.props: null +} +</screen> +</para> + + <para>Type: <literal>org.apache.fop.area.Span</literal>: +<screen> + curPage.page.regionBody.region.mainReference.spanAreas[3] = { + flowAreas: instance of java.util.ArrayList(id=1433) + height: 0 + org.apache.fop.area.Area.areaClass: 0 + org.apache.fop.area.Area.ipd: 481891 + org.apache.fop.area.Area.props: null +} +</screen> +</para> + + <screen> + curPage.page.regionBody.region.mainReference.spanAreas[3].flowAreas = "[ + org.apache.fop.area.Flow@dc9766 +]" +</screen> + + <para>Type: <literal>org.apache.fop.area.Flow</literal>: +<screen> + curPage.page.regionBody.region.mainReference.spanAreas[3].flowAreas[0] = { + stacking: 2 + width: 0 + org.apache.fop.area.BlockParent.xOffset: 0 + org.apache.fop.area.BlockParent.yOffset: 0 + org.apache.fop.area.BlockParent.width: 0 + org.apache.fop.area.BlockParent.height: 0 + org.apache.fop.area.BlockParent.children: null + org.apache.fop.area.BlockParent.orientation: 0 + org.apache.fop.area.Area.areaClass: 0 + org.apache.fop.area.Area.ipd: 481891 + org.apache.fop.area.Area.props: null +} +</screen> +</para> + + <para>Type: <literal>org.apache.fop.area.Span</literal>: +<screen> + curPage.page.regionBody.region.mainReference.spanAreas[4] = { + flowAreas: instance of java.util.ArrayList(id=1436) + height: 0 + org.apache.fop.area.Area.areaClass: 0 + org.apache.fop.area.Area.ipd: 481891 + org.apache.fop.area.Area.props: null +} +</screen> +</para> + + <screen> + curPage.page.regionBody.region.mainReference.spanAreas[4].flowAreas = "[ + org.apache.fop.area.Flow@1ec58a +]" +</screen> + + <para>Type: <literal>org.apache.fop.area.Flow</literal>: +<screen> + curPage.page.regionBody.region.mainReference.spanAreas[4].flowAreas[0] = { + stacking: 2 + width: 0 + org.apache.fop.area.BlockParent.xOffset: 0 + org.apache.fop.area.BlockParent.yOffset: 0 + org.apache.fop.area.BlockParent.width: 0 + org.apache.fop.area.BlockParent.height: 0 + org.apache.fop.area.BlockParent.children: null + org.apache.fop.area.BlockParent.orientation: 0 + org.apache.fop.area.Area.areaClass: 0 + org.apache.fop.area.Area.ipd: 481891 + org.apache.fop.area.Area.props: null +} +</screen> +</para> + + <screen> + curPage.page.regionBody.region.blocks = "[]" +</screen> + + <para>Type: <literal>org.apache.fop.area.CTM</literal>: +<screen> + curPage.page.regionBody.region.ctm = { + a: 1.0 + b: 0.0 + c: 0.0 + d: 1.0 + e: 56692.0 + f: 56692.0 + CTM_LRTB: instance of org.apache.fop.area.CTM(id=1439) + CTM_RLTB: instance of org.apache.fop.area.CTM(id=1440) + CTM_TBRL: instance of org.apache.fop.area.CTM(id=1441) +} +</screen> +</para> + + </section> + </section> + + </chapter> + +<!-- Local Variables: --> +<!-- current-language-environment: UTF-8 --> +<!-- coding: utf-8 --> +<!-- default-input-method: TeX --> +<!-- End: --> diff --git a/src/documentation/content/xdocs/DnI/fotree.xml b/src/documentation/content/xdocs/DnI/fotree.xml new file mode 100644 index 000000000..d0b7e6cf1 --- /dev/null +++ b/src/documentation/content/xdocs/DnI/fotree.xml @@ -0,0 +1,196 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * Copyright 2004 The Apache Software Foundation. + * + * Licensed 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$ --> + +<!-- +<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" + "docbookx.dtd"> + --> + + <chapter> + <title>Phase 1: Building the FO tree</title> + + <section> + <title>Creating the FO nodes</title> + + <para>FOP's first task is building a suitable data structure from +the XML input, which is an XML file with formatting objects or a +result tree with formatting objects from an XSLT transformation. One +could call this FOP's data binding. The data structure is an FO tree, +i.e., a tree of FONode objects. The structure of the FO tree exactly +parallels the structure of the XML file or the corresponding DOM tree, +but instead of XML nodes its nodes are objects of type +<literal>org.apache.fop.fo.FONode</literal>. The FO tree is built on +the basis of SAX parser events. The parser is responsible for parsing +the XML document; it calls FOP's callbacks when SAX events +occur.</para> + + <para>FOP's callbacks are implemented by the +<literal>FOTreeBuilder</literal> <literal>treebuilder</literal> +object, which is a SAX content handler. It was constructed in the +preparation phase, and registered with the parser as the content +handler. It has meaningful implementations of the methods +<literal>startDocument</literal>, <literal>endDocument</literal>, +<literal>startElement</literal>, <literal>endElement</literal>, and +<literal>characters</literal>.</para> + + <para><literal>treebuilder</literal> delegates its +<literal>startDocument</literal> and <literal>endDocument</literal> +methods to its <literal>FOTreeHandler</literal> object +<literal>foInputHandler</literal>. <literal>FOTreeHandler</literal> is +a subclas of <literal>FOInputHandler</literal>. +<screen> + treebuilder.foInputHandler = { + runtime: instance of java.lang.Runtime(id=635) + pageCount: 0 + initialMemory: 0 + startTime: 0 + foTreeListeners: instance of java.util.HashSet(id=636) + org.apache.fop.fo.FOInputHandler.foTreeControl: instance of org.apache.fop.apps.Document(id=634) + org.apache.avalon.framework.logger.AbstractLogEnabled.m_logger: instance of org.apache.avalon.framework.logger.ConsoleLogger(id=342) +} +</screen></para> + + <para>The first important task of <literal>treebuilder</literal> is +creating a suitable FO node for each element in the XML document. This +is done in its <literal>startElement</literal> method. Its most +important tool in this process is its <literal>fobjTable</literal> +object. <literal>fobjTable</literal> is a map of maps. For each +namespace supported by FOP it contains a map of local XML element name +to a Node maker object <literal>fobjMaker</literal>, of type +<literal>ElementMapping.Maker</literal>. In addition to the FO +namespace it contains makers for FOP's extensions namespace, the SVG +namespace and Batik's extensions namespace. +<screen> + treebuilder.fobjTable = "{ + http://www.w3.org/1999/XSL/Format={ + static-content=org.apache.fop.fo.FOElementMapping$SC@39e5b5, + table=org.apache.fop.fo.FOElementMapping$Ta@117f31e, + external-graphic=org.apache.fop.fo.FOElementMapping$EG@15a6029, + table-column=org.apache.fop.fo.FOElementMapping$TC@5f6303, + table-and-caption=org.apache.fop.fo.FOElementMapping$TAC@5d9084, + table-footer=org.apache.fop.fo.FOElementMapping$TB@bad8a8, + declarations=org.apache.fop.fo.FOElementMapping$Dec@e61fd1, + wrapper=org.apache.fop.fo.FOElementMapping$W@331059, + page-sequence=org.apache.fop.fo.FOElementMapping$PS@766a24, + single-page-master-reference=org.apache.fop.fo.FOElementMapping$SPMR@32784a, + footnote=org.apache.fop.fo.FOElementMapping$Foot@1774b9b, + multi-switch=org.apache.fop.fo.FOElementMapping$MS@104c575, + bidi-override=org.apache.fop.fo.FOElementMapping$BO@3fa5ac, + layout-master-set=org.apache.fop.fo.FOElementMapping$LMS@95cfbe, + float=org.apache.fop.fo.FOElementMapping$F@179dce4, + list-item=org.apache.fop.fo.FOElementMapping$LI@1950198, + basic-link=org.apache.fop.fo.FOElementMapping$BL@19bb25a, + multi-property-set=org.apache.fop.fo.FOElementMapping$MPS@da6bf4, + table-row=org.apache.fop.fo.FOElementMapping$TR@1e58cb8, + region-end=org.apache.fop.fo.FOElementMapping$RE@179935d, + block=org.apache.fop.fo.FOElementMapping$B@b9e45a, + leader=org.apache.fop.fo.FOElementMapping$L@3ef810, + table-header=org.apache.fop.fo.FOElementMapping$TB@100363, + list-item-body=org.apache.fop.fo.FOElementMapping$LIB@14e8cee, + multi-properties=org.apache.fop.fo.FOElementMapping$MP@67064, + region-after=org.apache.fop.fo.FOElementMapping$RA@bcda2d, + multi-case=org.apache.fop.fo.FOElementMapping$MC@97d01f, + block-container=org.apache.fop.fo.FOElementMapping$BC@e0a386, + title=org.apache.fop.fo.FOElementMapping$T@feb48, + retrieve-marker=org.apache.fop.fo.FOElementMapping$RM@11ff436, + color-profile=org.apache.fop.fo.FOElementMapping$CP@da3a1e, + character=org.apache.fop.fo.FOElementMapping$Ch@11dba45, + simple-page-master=org.apache.fop.fo.FOElementMapping$SPM@b03be0, + page-sequence-master=org.apache.fop.fo.FOElementMapping$PSM@2af081, + footnote-body=org.apache.fop.fo.FOElementMapping$FB@113a53d, + marker=org.apache.fop.fo.FOElementMapping$M@c5495e, + table-body=org.apache.fop.fo.FOElementMapping$TB@53fb57, + inline=org.apache.fop.fo.FOElementMapping$In@19a32e0, + table-cell=org.apache.fop.fo.FOElementMapping$TCell@8238f4, + list-block=org.apache.fop.fo.FOElementMapping$LB@16925b0, + region-start=org.apache.fop.fo.FOElementMapping$RS@297ffb, + table-caption=org.apache.fop.fo.FOElementMapping$TCaption@914f6a, + conditional-page-master-reference=org.apache.fop.fo.FOElementMapping$CPMR@1f4cbee, + list-item-label=org.apache.fop.fo.FOElementMapping$LIL@787d6a, + multi-toggle=org.apache.fop.fo.FOElementMapping$MT@71dc3d, + initial-property-set=org.apache.fop.fo.FOElementMapping$IPS@1326484, + repeatable-page-master-alternatives=org.apache.fop.fo.FOElementMapping$RPMA@16546ef, + repeatable-page-master-reference=org.apache.fop.fo.FOElementMapping$RPMR@1428ea, + flow=org.apache.fop.fo.FOElementMapping$Fl@18a49e0, + page-number=org.apache.fop.fo.FOElementMapping$PN@1f82982, + instream-foreign-object=org.apache.fop.fo.FOElementMapping$IFO@16d2633, + inline-container=org.apache.fop.fo.FOElementMapping$IC@e70e30, + root=org.apache.fop.fo.FOElementMapping$R@154864a, + region-before=org.apache.fop.fo.FOElementMapping$RBefore@3c9217, + region-body=org.apache.fop.fo.FOElementMapping$RB@9b42e6, + page-number-citation=org.apache.fop.fo.FOElementMapping$PNC@14520eb + }, + http://xml.apache.org/fop/extensions={ + bookmarks=org.apache.fop.fo.extensions.ExtensionElementMapping$B@1d7fbfb, + label=org.apache.fop.fo.extensions.ExtensionElementMapping$L@e020c9, + outline=org.apache.fop.fo.extensions.ExtensionElementMapping$O@888e6c + }, + http://www.w3.org/2000/svg={ + <default>=org.apache.fop.fo.extensions.svg.SVGElementMapping$SVGMaker@1742700, + svg=org.apache.fop.fo.extensions.svg.SVGElementMapping$SE@acb158 + }, + http://xml.apache.org/batik/ext={ + <default>=org.apache.fop.fo.extensions.svg.BatikExtensionElementMapping$SVGMaker@1af33d6, + batik=org.apache.fop.fo.extensions.svg.BatikExtensionElementMapping$SE@17431b9 + } + }" +</screen></para> + + <para>The values in this map are objects of subclasses of +<literal>ElementMapping.Maker</literal>. +<literal>ElementMapping.Maker</literal> is a static nested class of +<literal>ElementMapping</literal>. It has no members and a single +object method <literal>FONode make(FONode parent)</literal>. The +subclasses are static nested classes of +<literal>FOElementMapping</literal>. Each subclass has its own +implementation of the <literal>make</literal> method, and returns its +own subclass of FONode. For example, +<literal>FOElementMapping$R</literal> returns a +<literal>org.apache.fop.fo.pagination.Root</literal> object.</para> + + <para><literal>treebuilder</literal> delegates its +<literal>endElement</literal> method to the node's +<literal>end</literal> method, which allows FOP to take appropriate +action at the end of each FO element. The only node type whose +<literal>end</literal> method takes special action, is +<literal>org.apache.fop.fo.pagination.PageSequence</literal>. It hands +control to FOP's next phase, building of the area tree.</para> + + </section> + + <section> + <title>Creating the property values</title> + + <para>Formatting objects have many attributes by which the user +may finetune their behaviour. When the FO tree is built, the +attributes must be converted to properties. This conversion process +must implement XSLT's sometimes complicated rules of default values, +inheritance, shorthand notations etc. This is one of the tasks of the +property subsystem, which is described in its own <link +linkend="ch.properties">chapter</link>.</para> + + </section> + </chapter> + +<!-- Local Variables: --> +<!-- current-language-environment: UTF-8 --> +<!-- coding: utf-8 --> +<!-- default-input-method: TeX --> +<!-- End: --> diff --git a/src/documentation/content/xdocs/DnI/getnextbreakposs.xml b/src/documentation/content/xdocs/DnI/getnextbreakposs.xml new file mode 100644 index 000000000..96bd64390 --- /dev/null +++ b/src/documentation/content/xdocs/DnI/getnextbreakposs.xml @@ -0,0 +1,1227 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * Copyright 2004 The Apache Software Foundation. + * + * Licensed 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$ --> + +<!-- +<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" + "docbookx.dtd"> + --> + + <chapter> + <title>Phase 2a: The <literal>getNextBreakPoss</literal> call +tree</title> + + <section> + <title>Overview</title> + + <para> <itemizedlist spacing="compact"> + <listitem> + <para>Create a new layout context for the children.</para> + </listitem> + <listitem> + <para>Then process the flow: loop until the flow is exhausted +(isFinished()): <itemizedlist spacing="compact"> + <listitem> + <para>Get the next possible breakpoint (getNextBreakPoss). +<itemizedlist spacing="compact"> + <listitem> + <para>Loop until the list of child layout +managers is exhausted: <itemizedlist spacing="compact"> + <listitem> + <para> Get a child layout manager +(AbstractLayoutManager.getChildLM). The current child layout manager +is returned until it is finished. Then the layout manager for the next +child is returned.</para> + </listitem> + <listitem> + <para> Create a new layout context for +the children.</para> + </listitem> + <listitem> + <para> If the child layout manager is +not finished, get the next possible breakpoint +(getNextBreakPoss).</para> + </listitem> + <listitem> + <para> If a breakpoint is returned, +break the loop and return the breakpoint.</para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>This finishes a page.</para> + </listitem> + <listitem> + <para>Get the next possible breakpoint +(getNextBreakPoss) (<emphasis>continued</emphasis>) <itemizedlist spacing="compact"> + <listitem> + <para>Loop until the list of child layout +managers is exhausted: (<emphasis>continued</emphasis>) <itemizedlist spacing="compact"> + <listitem> + <para>Else if no breakpoint is returned, +do the next cycle with the next child layout manager.</para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>Mark the layout manager as finished (the +list of child layout managers is exhausted).</para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + + <para>At this point a complete (pseudo)tree of possible break +points for a page has been collected.</para> + + </section> + + <section> + <title>How do layout managers get layout managers for the child +FO nodes?</title> + +<para>Child layout managers are created and retrieved in the method +<literal>AbstractLayoutManager.getChildLM</literal>.</para> + +<para>The layout manager has a layout strategy, which has an +<literal>AddLMVisitor</literal> object, which is responsible for +creating layout managers for the FO nodes.</para> + +<para>The layout manager gets the layout manager for its next child from its +<literal>LMIter</literal> object <literal>childLMIter</literal>. This +<literal>LMIter</literal> object contains an iterator over the +children of the layout manager's FO node. It behaves itself as an +iterator over the list of layout managers for the children. It +constructs those layout managers when needed, in its +<literal>preLoadNext</literal> method. It does so by calling the +layout strategy's <literal>AddLMVisitor</literal> object's +<literal>addLayoutManager</literal> method. The +<literal>LMIter</literal> object gets the layout strategy via the +current layout manager, which it knows.</para> + +<para><literal>AddLMVisitor</literal>'s <literal>addLayoutManager</literal> +method first registers the LM list in its second argument, i.e. the +<literal>LMIter</literal> object's LM list, as its own member +<literal>currentLMlist</literal>. Then it asks the FO node to accept +it as the <literal>FOTreeVisitor</literal> +(<literal>acceptVisitor</literal>). The FO node then calls the +appropriate method of this FO tree visitor, in this case +(<literal>fo:flow</literal>) the method <literal>serveFlow</literal> +(<literal>AddLMVisitor.serveFlow</literal>). This method creates a +<literal>FlowLayoutManager</literal> object and adds it to the +<literal>currentLMList</literal>. Thus <literal>LMIter</literal> has a +layout manager for its next child. It returns this layout manager in +the call to its <literal>next()</literal> method, when the current +layout manager invokes its <literal>getChildLM</literal> method.</para> + +<para>Note that layout manager types may have their own subclass of +<literal>LMIter</literal>, +e.g. <literal>BlockLayoutManager$BlockLMiter</literal> and +<literal>AbstractList$ListItr</literal>, which may implement a +different method of creating child layout managers.</para> + +<para>The method <literal>acceptVisitor</literal> of the FO node calls the +appropriate method of its visitor. This procedure effectively +implements an indirect mapping from FO node type to layout +manager. The indirection allows the <literal>AddLMVisitor</literal> +object to return its own layout manager for each FO node type. Because +the <literal>AddLMVisitor</literal> object is part of the layout +strategy, this indirection allows the layout strategy to provide its +own layout managers for the layout process. In this manner, a +different layout strategy can be coupled to the other parts of the +program.</para> + +<para>Note that <literal>AbstractLayoutManager.getChildLM</literal> itself +does not behave as an iterator. The current child layout manager is +returned until it is finished. One can safely make multiple calls to +<literal>getChildLM</literal>. If the current child layout manager is +unfinished and does nothing in between the calls, it remains +unfinished, and is returned at every call. If the current child layout +manager is finished, the next layout manager is loaded, and, because +it is unfinished, returned at every call. If this is the last child +layout manager and it is finished, then null is returned because in +<literal>LMiter.preLoadNext</literal> +<literal>baseIter.hasNext()</literal> returns false. The latter case +is used in <literal>BlockLayoutManager.getNextBreakPoss</literal>.</para> + +<para>Stack trace: Creating a new layout manager for a child, in +<literal>LMiter.preLoadNext</literal>, in +<literal>AbstractLayoutManager.getChildLM</literal>:</para> + +<screen> + [1] org.apache.fop.layoutmgr.AbstractLayoutManager.<init> (AbstractLayoutManager.java:71) + [2] org.apache.fop.layoutmgr.BlockStackingLayoutManager.<init> (BlockStackingLayoutManager.java:70) + [3] org.apache.fop.layoutmgr.FlowLayoutManager.<init> (FlowLayoutManager.java:81) + [4] org.apache.fop.layoutmgr.AddLMVisitor.serveFlow (AddLMVisitor.java:894) + [5] org.apache.fop.fo.pagination.Flow.acceptVisitor (Flow.java:187) + [6] org.apache.fop.layoutmgr.AddLMVisitor.addLayoutManager (AddLMVisitor.java:198) + [7] org.apache.fop.layoutmgr.LMiter.preLoadNext (LMiter.java:88) + [8] org.apache.fop.layoutmgr.LMiter.hasNext (LMiter.java:77) + [9] org.apache.fop.layoutmgr.AbstractLayoutManager.getChildLM (AbstractLayoutManager.java:186) + [10] org.apache.fop.layoutmgr.PageLayoutManager.getNextBreakPoss (PageLayoutManager.java:253) + [11] org.apache.fop.layoutmgr.PageLayoutManager.doLayout (PageLayoutManager.java:228) +</screen> + + </section> + + <section> + <title>Block layout managers and their child layout managers</title> + +<para>Block LMs are different in their treatment of their child LMs. For +this purpose <literal>BlockLayoutManager</literal> defines a nested class <literal>BlockLMiter</literal>, +which is a subclass of <literal>LMiter</literal>.</para> + +<para>A <literal>BlockLMiter</literal> object has a member called proxy, +which is the basic <literal>LMiter</literal> over the children of the +block. If the proxy produces a child LM that does not generate inline +areas, the child LM is added to the list of child LMs as normal. But +if the childLM generates an inline area, a new +<literal>LineLayoutManager</literal> object is created +(<literal>BlockLayoutManager.BlockLMiter.createLineManager</literal>). This +LM asks the proxy to produce more child LMs. As long as these child +LMs generate inline areas, they are collected by the +<literal>LineLayoutManager</literal> object. Finally, the +<literal>LineLayoutManager</literal> object creates its +<literal>LMiter</literal> object as the +<literal>ListIterator</literal> over the list of collected child LMs.</para> + + </section> + + <section> + <title>About <literal>getNextBreakPoss</literal> and the list of +child layout managers</title> + +<para>Note that the breakpoint may come from a deeply nested child. Each +layout manager keeps a reference to its current child layout +manager. The whole list is descended again +(<literal>getChildLM</literal>) at the next call to +<literal>getNextBreakPoss</literal>.<warning> + <simpara>TO BE IMPROVED</simpara> + </warning> +</para> + +<para>Stack of layout managers: + <variablelist> + <varlistentry> + <term><literal>PageSequence</literal></term> + <listitem> + <simpara><literal>PageLayoutManager</literal></simpara> + </listitem> + </varlistentry> + <varlistentry> + <term><literal>Flow</literal></term> + <listitem> + <simpara><literal>FlowLayoutManager</literal></simpara> + </listitem> + </varlistentry> + <varlistentry> + <term><literal>Block</literal></term> + <listitem> + <simpara><literal>BlockLayoutManager</literal></simpara> + </listitem> + </varlistentry> + <varlistentry> + <term><literal>Block</literal></term> + <listitem> + <simpara><literal>LineLayoutManager</literal></simpara> + </listitem> + </varlistentry> + <varlistentry> + <term><literal>FOText</literal></term> + <listitem> + <simpara><literal>TextLayoutManager</literal></simpara> + </listitem> + </varlistentry> + </variablelist> +For <literal>BlockLayoutManager</literal> and +<literal>LineLayoutManager</literal> <literal>Block</literal> is the +same, but their <literal>childLMIter</literal> are different: +<literal>BlockLayoutManager$BlockLMiter</literal> vs +<literal>AbstractList$ListItr</literal></para> + +<screen> + [1] org.apache.fop.layoutmgr.TextLayoutManager.getNextBreakPoss (TextLayoutManager.java:270) + [2] org.apache.fop.layoutmgr.LineLayoutManager.getNextBreakPoss (LineLayoutManager.java:212) + [3] org.apache.fop.layoutmgr.BlockLayoutManager.getNextBreakPoss (BlockLayoutManager.java:229) + [4] org.apache.fop.layoutmgr.FlowLayoutManager.getNextBreakPoss (FlowLayoutManager.java:111) + [5] org.apache.fop.layoutmgr.PageLayoutManager.getNextBreakPoss (PageLayoutManager.java:261) + [6] org.apache.fop.layoutmgr.PageLayoutManager.doLayout (PageLayoutManager.java:228) +</screen> + +<para>A <literal>TextLayoutManager</literal>: +<screen> + this = { + vecAreaInfo: instance of java.util.ArrayList(id=1062) + chars: instance of char[13] (id=1064) + textInfo: instance of org.apache.fop.fo.TextInfo(id=1065) + iAreaStart: 0 + iNextStart: 0 + ipdTotal: null + spaceCharIPD: 4448 + hyphIPD: 5328 + halfWS: instance of org.apache.fop.traits.SpaceVal(id=1066) + iNbSpacesPending: 0 + org.apache.fop.layoutmgr.AbstractLayoutManager.userAgent: instance of org.apache.fop.apps.FOUserAgent(id=1067) + org.apache.fop.layoutmgr.AbstractLayoutManager.parentLM: instance of org.apache.fop.layoutmgr.LineLayoutManager(id=1068) + org.apache.fop.layoutmgr.AbstractLayoutManager.fobj: instance of org.apache.fop.fo.FOText(id=1069) + org.apache.fop.layoutmgr.AbstractLayoutManager.foID: null + org.apache.fop.layoutmgr.AbstractLayoutManager.markers: null + org.apache.fop.layoutmgr.AbstractLayoutManager.bFinished: false + org.apache.fop.layoutmgr.AbstractLayoutManager.curChildLM: null + org.apache.fop.layoutmgr.AbstractLayoutManager.childLMiter: instance of org.apache.fop.layoutmgr.LMiter(id=1070) + org.apache.fop.layoutmgr.AbstractLayoutManager.bInited: true +} +</screen> +</para> + +<para>Text in <literal>fo:text</literal> is handled by a +<literal>TextLayoutManager</literal>. Two routines add the text and +calculate the next possible break.</para> + + </section> + + <section> + <title><literal>LineLayoutManager.getNextBreakPoss</literal></title> + + <section> + <title>Prepare for the main loop</title> + + <itemizedlist spacing="compact"> + <listitem> + <simpara>Create a new empty list of possible line endings, +<literal>vecPossEnd</literal>.</simpara> + </listitem> + <listitem> + <simpara>Retrieve the <literal>ipd</literal> +<literal>availIPD</literal> from the layout context.</simpara> + </listitem> + <listitem> + <simpara>Create a new layout context (inline layout +context) for the child layout managers, based on the layout context +for this layout manager.</simpara> + </listitem> + <listitem> + <simpara>Clear the map of previous + <literal>ipd</literal>s.</simpara> + </listitem> + <listitem> + <simpara>Record the length of +<literal>vecInlineBreaks</literal>, which we can use to find the last +breakposs of the previous line.</simpara> + </listitem> + <listitem> + <simpara>Set <literal>prevBP</literal> to +<literal>null</literal>; <literal>prevBP</literal> contains the last +confirmed breakposs of this line.</simpara> + </listitem> + </itemizedlist> + </section> + + <section> + <title>The main loop over the list of child layout managers</title> + + <para>Loop until the list of child layout managers is +exhausted: <itemizedlist spacing="compact"> + <listitem> + <para>Get a child layout manager +(<literal>AbstractLayoutManager.getChildLM</literal>). The current +child layout manager is returned until it is finished. Then the layout +manager for the next child is returned.</para> + </listitem> + <listitem> + <para>Record the last breakposs.</para> + </listitem> + <listitem> + <para>Record whether the breakposs we are going to +find is the first breakposs of this line.</para> + </listitem> + <listitem> + <para>Record whether it is the first breakposs of +this child layout manager.</para> + </listitem> + <listitem> + <para>Initialize the inline layout context (note that +it is not a new layout context, the same inline layout context is used +by all child layout managers) (method +<literal>InlineStackingLayout.initChildLC</literal>): <itemizedlist spacing="compact"> + <listitem> + <para>Record whether this is a new area; it is a +new area if this is the start of a new line or of a new child +LM.</para> + </listitem> + <listitem> + <para>If this is the start of a new +line <itemizedlist spacing="compact"> + <listitem> + <para>record whether this is the first area +of this child LM,</para> + </listitem> + <listitem> + <para>set the leading space as passed by +argument.</para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>Else if this starts a new child +LM <itemizedlist spacing="compact"> + <listitem> + <para>record that this is the first area,</para> + </listitem> + <listitem> + <para>set the leading space from the previous +BP.</para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>Else set the leading space to + <literal>null</literal>.</para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>Record on the inline layout context whether +leading space is supppressed; it is suppressed if this is the start of +a new line, but not the start of this child LM, and the previous line +was not ended by a forced break.</para> + </listitem> + <listitem> + <para>Retrieve the next breakposs from the current child +LM (<literal>getNextBreakPoss</literal> method of child LM). If it is +not <literal>null</literal>: +<itemizedlist spacing="compact"> + <listitem> + <para>Calculate the <literal>ipd</literal> up to +the previous BP (method +<literal>InlineStackingLayout.updatePrevIPD</literal>): <itemizedlist spacing="compact"> + <listitem> + <para>Take an empty <literal>ipd</literal> + size.</para> + </listitem> + <listitem> + <para>If this starts a new line: <itemizedlist spacing="compact"> + <listitem> + <para>if it has a leading fence, add +leading space (?),</para> + </listitem> + <listitem> + <para>list the <literal>ipd</literal> +for the LM of this BP in the map of previous +<literal>ipd</literal>s.</para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>Else <itemizedlist spacing="compact"> + <listitem> + <para>retrieve the +<literal>ipd</literal> for the LM of this BP in the map of previous +<literal>ipd</literal>s,</para> + </listitem> + <listitem> + <para>if that is +<literal>null</literal> (first BP of this child LM) <itemizedlist spacing="compact"> + <listitem> + <para>retrieve the +<literal>ipd</literal> for the LM of the previous BP in the map of +previous <literal>ipd</literal>s,</para> + </listitem> + <listitem> + <para>add the leading space +of this BP,</para> + </listitem> + <listitem> + <para>add the pending space-end +(stacking size) of the previous BP,</para> + </listitem> + <listitem> + <para>list the +<literal>ipd</literal> for the LM of this BP in the map of previous +<literal>ipd</literal>s.</para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>Add to the <literal>ipd</literal> the +pending space-end (stacking size) of this BP.</para> + </listitem> + <listitem> + <para>Record whether this BP could end the +line: <itemizedlist spacing="compact"> + <listitem> + <para>if a break may occur after this BP, +record true;</para> + </listitem> + <listitem> + <para>else if this BP is suppressible at a +line break, return false;</para> + </listitem> + <listitem> + <para>else, return whether this is the last +child LM and it is finished, or the next area could start a new +line.</para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>If this BP could end the line, add trailing +space.</para> + </listitem> + <listitem> + <para>If this BP exceeds the line length +(<literal>bpDim.min > availIPD.max</literal>), <itemizedlist spacing="compact"> + <listitem> + <para>if the text should be justified or if +this is the first BP of this line, <itemizedlist spacing="compact"> + <listitem> + <para>if we are in a hyphenation try, +break the loop; we have exhausted our options and one of the previous +BPs should end the line (<literal>_exit of loop_</literal>);</para> + </listitem> + <listitem> + <para>if this BP could not end the +line, add it to the list of inline breaks, and continue with the next +iteration;</para> + </listitem> + <listitem> + <para>prepare to hyphenate: get the +hyphenation context for the text between the last and this BP (method +<literal>getHyphenContext</literal>): <itemizedlist spacing="compact"> + <listitem> + <para>add this BP to the list of +inline breaks; even though this is not a good BP, we add it to the +list, so that we can retrieve the text between the last and this +BP;</para> + </listitem> + <listitem> + <para>iterate back to the +previous BP in this list;</para> + </listitem> + <listitem> + <para>loop over the following +BPs in this list: <itemizedlist spacing="compact"> + <listitem> + <para>retrieve the text +between the preceding and this BP.</para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>remove this BP again from +the list of inline breaks.</para> + </listitem> + <listitem> + <para>create a hyphenation +object for the retrieved text, taking the language, country and other +hyphenation properties into account.</para> + </listitem> + <listitem> + <para>create a hyphenation +context object from it, and return that.</para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>store the hyphenation context +with the inline layout context.</para> + </listitem> + <listitem> + <para>Record on the inline layout +context that we are in a hyphenation try.</para> + </listitem> + <listitem> + <para>reset the child LMs to the +previous BP or to the start of the line.</para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>Else (if text should not be justified +and if this is not the first BP of this line) break the loop; one of +the previous BPs should end the line (<literal>_exit of +loop_</literal>);</para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>Else (if this BP does not exceed the line +length): <itemizedlist spacing="compact"> + <listitem> + <para>add this BP to the list of inline +breaks,</para> + </listitem> + <listitem> + <para>if this BP could end the line, +<itemizedlist spacing="compact"> + <listitem> + <para>record it as the last confirmed +BP: set prevBP to this BP.</para> + </listitem> + <listitem> + <para>if this BP is a forced line +break, break the loop; this BP (or one of the previous BPs?) should +end the line (<literal>_exit of loop_</literal>).</para> + </listitem> + <listitem> + <para>if this BP may fill the line +length (<literal>bpDim.max >= availIPD.min</literal>), add it to the +list of possible line endings, <literal>vecPossEnd</literal>, with a +cost which is equal to the difference of the optimal values of the +content length and the line length (<literal>Math.abs(availIPD.opt - +bpDim.opt)</literal>).</para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>If we are in a hypenation try, and the hyphenation +context has no more hyphenation points, break the loop; this or one of +the previous BPs should end the line (<literal>_exit of +loop_</literal>).</para> + </listitem> + </itemizedlist></para> + </section> + + <section> + <title>After the main loop</title> + + <para>There are five exit points of the main loop: <orderedlist> + <listitem> + <simpara>The last BP in the hyphenation try has exceeded +the line length.</simpara> + </listitem> + <listitem> + <simpara>The last BP has exceeded the line length, and +we cannot get a hyphenation context.</simpara> + </listitem> + <listitem> + <simpara>The last BP has exceeded the line length, and +we do not hyphenate.</simpara> + </listitem> + <listitem> + <simpara>The last BP has not exceeded the line length +but forces a line break.</simpara> + </listitem> + <listitem> + <simpara>We have run out of hyphenation points (and the +last BP has not exceeded the line length).</simpara> + </listitem> + <listitem> + <simpara>Natural end of the while loop: we are through +the list of child layout managers.</simpara> + </listitem> + </orderedlist></para> + +<para>If the last BP has exceeded the line length, it is not in the +list of inline breaks, and prevBP points to the last good break; +otherwise it is in the list of inline breaks, and prevBP points to +it.</para> + + <itemizedlist spacing="compact"> + <listitem> + <para>If we are through the list of child LMs, mark this + LM as finished.</para> + </listitem> + <listitem> + <para>If no BP was produced, return +<literal>null</literal>. (This should concur with being +finished?)</para> + </listitem> + <listitem> + <para>If prevBP is <literal>null</literal>, there is not +last good break; set it to this BP, even though it fails some +criteria: <itemizedlist spacing="compact"> + <listitem> + <para>it has exceeded the line length in the +hyphenation try or we cannot get a hyphenation context,</para> + </listitem> + <listitem> + <para>or it cannot end the line but it is the last +BP of the last child layout manager.</para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>If this BP is not a forced break, and there are +several possible line breaks, select the best one; make +<literal>prevBP</literal> point to it. (Could this produce the wrong +result if the BP has exceeded the line length and at the same time is +a forced line break? Should <literal>prevBP</literal> be tested for +being a forced break instead?)</para> + </listitem> + <listitem> + <para>If the last BP is not the actual breakpoint +<literal>prevBP</literal> (<literal>bp != prevBP</literal>) and the +material after <literal>prevBP</literal> is not suppressible at the +end of a line, back up to <literal>prevBP</literal> for a proper start +of the next line.</para> + </listitem> + <listitem> + <para>If the text should be justified and the breakpoint +is a forced line break (here <literal>prevBP</literal> is tested) or +this is the last line of the layout manager, set text alignment to +left-aligned.</para> + </listitem> + <listitem> + <para>Make a line break and return the associated + breakposs.</para> + </listitem> + </itemizedlist> + </section> + </section> + + <section> + <title><literal>LineLayoutManager.makeLineBreak</literal></title> + + <para>Arguments are: <itemizedlist spacing="compact"> + <listitem> + <para>index in <literal>vecInlineBreaks</literal> of + line breaking BP of last line,</para> + </listitem> + <listitem> + <para>target line length,</para> + </listitem> + <listitem> + <para>type of text alignment.</para> + </listitem> + </itemizedlist></para> + +<para>Calculate line dimensions. The Line LayoutManager contains the +parameters <literal>lineHeight</literal>, <literal>lead</literal> and +<literal>follow</literal> as members, which it received from its Block +LayoutManager parent at construction. The Blo ckLayoutManager contains +these parameters as members as well, and has received them from a +<literal>TextInfo</literal> object in the method set +<literal>BlockTextInfo</literal>. The <literal>TextInfo</literal> +object has a reference to the <literal>Font</literal> +object. <literal>lead</literal> is the font ascender, +<literal>follow</literal> is the font descender.</para> + +<para>The leading is the difference between +<literal>lineHeight</literal> and font height = ascender + +descender. The leading is split in two halves, one for above, the +other for below the line. The variable <literal>lineLead</literal> is +calculated as the distance from the baseline to the top of the line, +the variable <literal>maxtb</literal> is calculated as the distance +from the baseline to the bottom of the line. The variable +<literal>middlefollow</literal> set equal to <literal>maxtb</literal>. +These parameters correspond to the members <literal>lead</literal>, +<literal>total</literal> and <literal>follow</literal> of the +breakposs. <warning> + <simpara>Find out the exact meaning of these.</simpara> + </warning></para> + + <itemizedlist spacing="compact"> + <listitem> + <para>Loop over the breakposs in + <literal>vecInlineBreaks</literal>: <itemizedlist spacing="compact"> + <listitem> + <para>adjust <literal>lineLead</literal>, +<literal>maxtb</literal> and <literal>middlefollow</literal> if the +corresponding dimension of the BP is larger;</para> + </listitem> + <listitem> + <para>add the <literal>ipd</literal>s; a BP does +not just hold the <literal>ipd</literal> of the area since the +previous BP, but the cumulative <literal>ipd</literal> for all the +areas contributed by its layout manager; therefore care is taken to +add only the <literal>ipd</literal> of the last BP of each LM; more +precisely, the <literal>ipd</literal> of the last BP of the previous +LM is added when the next LM is encountered;</para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>Add the <literal>ipd</literal> of the last BP.</para> + </listitem> + <listitem> + <para>Resolve the trailing space of the last BP.</para> + </listitem> + <listitem> + <para>Adjust <literal>middlefollow</literal> if it is +smaller than <literal>maxtb - lineHeight</literal>.</para> + </listitem> + <listitem> + <para>Calculate the stretch or shrink factor +<literal>ipdAdjust</literal> for the stretch- and shrinkable elements +in this line: <itemizedlist spacing="compact"> + <listitem> + <para>if content optimum is larger than line + length optimum, <itemizedlist spacing="compact"> + <listitem> + <para>if content minimum is smaller than + line length optimum, <itemizedlist spacing="compact"> + <listitem> + <para>calculate +<literal>ipdAdjust</literal> between 0 and -1, real line length = line +length optimum,</para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>else (content minimum is larger than + line length optimum) <itemizedlist spacing="compact"> + <listitem> + <para><literal>ipdAdjust = +-1</literal>, real line length = content minimum,</para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>else (content optimum is smaller than line + length optimum), <itemizedlist spacing="compact"> + <listitem> + <para>if content maximum is larger than line + length optimum, <itemizedlist spacing="compact"> + <listitem> + <para>calculate +<literal>ipdAdjust</literal> between 0 and 1, real line length = line +length optimum,</para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>else (content maximum is smaller than + line length optimum), <itemizedlist spacing="compact"> + <listitem> + <para><literal>ipdAdjust = +1</literal>, real line length = content maximum.</para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>Calculate the stretch or shrink factor +<literal>dAdjust</literal> for white space and the indent: +<itemizedlist spacing="compact"> + <listitem> + <para>justify: calculate +<literal>dAdjust</literal>,</para> + </listitem> + <listitem> + <para>center or end: calculate the required + indent.</para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>Create a new <literal>LineBreakPosition</literal> +based on this LM, the last BP in <literal>vecInlineBreaks</literal> +and the calculated dimensions; use <literal>lineLead</literal> for the +baseline position and <literal>lineLead + middlefollow</literal> for +the <literal>lineHeight</literal>.</para> + </listitem> + <listitem> + <para>Create a <literal>BreakPoss</literal> from this + <literal>LineBreakPosition</literal> object.</para> + </listitem> + <listitem> + <para>Mark the BP as last if this LM is finished.</para> + </listitem> + <listitem> + <para>Set the stacking size of the BP +(<literal>bpd</literal>) equal to <literal>lineLead + +middlefollow</literal>.</para> + </listitem> + </itemizedlist> + </section> + + <section> + <title>Line LayoutManager, a sequence of breakposs</title> + +<para>The text is: "waterstaatsingenieur ministersportefeuille +aandachtstrekker. Vernederlandste vakliteratuur" etc. It consists of a +few long Dutch words, which can be found in the hyphenation exceptions +in <filename>nl.xml</filename>. The column width is 8cm. This text and +width have been chosen so that they force many hyphenations.</para> + +<para>This text is contained in a single <literal>FOText</literal> +node, and is dealt with by a single Text LayoutManager, which is a +child layout manager for the Line LayoutManager. The Text +LayoutManager maintains a list of area information objects, +<literal>vecAreaInfo</literal>, and the Line LayoutManager maintains a +list of breakposs, <literal>vecInlineBreaks</literal>. Each breakposs +refers to an area, in its <literal>position.iLeafPos</literal> +member.</para> + +<para>During the process of finding suitable line breaks, breakposs +are generated until one is found that exceeds the line length. Then +the Line LayoutManager backs up to the previous BP, either to start a +hyphenation try or to create the line break. When it creates a line +break, the last breakposs, which exceeds the line length, is not added +to the list of inline breaks. When it starts a hyphenation try, the +breakposs is added to that list, and removed again after the text for +hyphenation has been obtained. Each time, the corresponding area info +is left in the list of area information objects. As a consequence the +list <literal>vecAreaInfo</literal> is longer than the list +<literal>vecInlineBreaks</literal>, and some areas have no +corresponding breakposs.</para> + +<screen> +wa-ter-staats-in-ge-nieur mi-nis-ters-por-te-feuil-le aandachtstrekker. +0 2 5 1 1 1 2 2 2 2 3 3 3 4 4 6 + 1 3 5 0 3 6 9 0 3 5 0 2 0 + +text: waterstaatsingenieur wa ter staats in | +AreaInfo: 0: 0-20 (removed) 0: 0-2 1: 2-5 2: 5-11 3: 11-13 | +InlineBreaks: 0 (removed) 0 1 2 3 | + too long, hyphenate, | + back up V + +gen genieur _ministersportefeuille _mi nis | +4: 13-15 5: 13-20 6: 20-42 7: 20-23 8: 23-26 | + 4 5 (removed) 5 6 | +too long, too long, hyphenate | +line break, back up | +back up v + +ters tersportefeuille_ ter s por +9: 26-30 10: 26-42 11: 26-29 12: 29-30 13: 30-33 + 7 (removed) 7 8 9 +too long, too long, hyphenate, hyphenation +line break, back up error +back up + +te feuil | le | _aandachtstrekker. +14: 33-35 15: 35-40 | 16: 40-42 | 17: 42-60 +10 11 | 12 | 13 (removed) + last hyphenpoint, | | too long, + line break v | hyphenation fails, + | line break, + v back up + +aandachtstrekker. | etc. +18: 43-60 | +13 | +too long, | +hyphenation fails, | +first BP, | +line break v +</screen> + +<para>A few remarkable points: <orderedlist> + +<listitem> +<simpara>The first AreaInfo object is removed from the list during backing + up. This is because the previous BP, which is + <literal>null</literal>, does not belong to this child layout + manager, and therefore the whole child LM is reset.</simpara> +</listitem> + +<listitem> +<simpara>The last BP, no. 18, exceeds the line length, but because it is the + first BP of this line, it is accepted for the line break.</simpara> +</listitem> + +<listitem> +<simpara>BP 7 at position 29 falls at a point that is not a good hyphenation + point. This is probably caused by the fact that for this line only + the partial word is subjected to hyphenation. On the previous line + the complete word was subjected to hyphenation, and there was no BP + at position 29.</simpara> +</listitem> + +<listitem> +<simpara>For the word "aandachtstrekker." hyphenation fails + (<literal>hyph == null</literal> is returned). This may be due to + the period not being separated from the word. When the period is + removed, the word is properly broken.</simpara> +</listitem> + </orderedlist></para> + </section> + + <section> + <title><literal>TextLayoutManager.getNextBreakPoss</literal></title> + + <para> <itemizedlist spacing="compact"> + <listitem> + <para>If this is the first call to this Text +LayoutManager, initialize <literal>ipdTotal</literal> and record that +this breakposs is the first in <literal>iFlags</literal>.</para> + </listitem> + <listitem> + <para>If leading spaces must be suppressed, suppress all +leading space characters <literal>U+20</literal>. Return if this +finished the text.</para> + </listitem> + <listitem> + <para>For the remaining leading space characters, +<itemizedlist spacing="compact"> + <listitem> + <para>If this is a space <literal>U+20</literal> + or a non-breaking space <literal>U+A0</literal>, + <itemizedlist spacing="compact"> + <listitem> + <para>count it;</para> + </listitem> + <listitem> + <para>if this is the first character and this + is the first breakposs, <itemizedlist spacing="compact"> + <listitem> + <para>if the context has leading spaces, +add it (or <literal>halfWS</literal>?);</para> + </listitem> + <listitem> + <para>else add it (or +<literal>halfWS</literal>?) to the pending space, and add the pending +space to the <literal>space</literal> ipd.</para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>add the space width to the word +<literal>ipd</literal>.</para> + </listitem> + <listitem> + <para>set the pending space to + <literal>halfWS</literal>.</para> + </listitem> + <listitem> + <para>if this is a non-breaking space +<literal>U+A0</literal>, register it in +<literal>bSawNonSuppressible</literal>.</para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>Else (other space characters), <itemizedlist spacing="compact"> + <listitem> + <para>register it in + <literal>bSawNonSuppressible</literal>.</para> + </listitem> + <listitem> + <para>add the pending space to the space +<literal>ipd</literal>, and clear the pending space.</para> + </listitem> + <listitem> + <para>add the character width to the word + <literal>ipd</literal>.</para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>If this finishes the text, <itemizedlist spacing="compact"> + <listitem> + <para>register whether there were any +nonsuppressible spaces (<literal>bSawNonSuppressible</literal>) in +<literal>iFlags</literal>.</para> + </listitem> + <listitem> + <para>pass all the info to + <literal>makeBreakPoss</literal> and + <literal>_return_</literal> its breakposs.</para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>Else, <itemizedlist spacing="compact"> + <listitem> + <para>add pending space.</para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>If hypenation is on, get the size of the next + syllable: <itemizedlist spacing="compact"> + <listitem> + <para>get the size of the next syllable, +<itemizedlist spacing="compact"> + <listitem> + <para>if successful, add the flags +<literal>BreakPoss.CAN_BREAK_AFTER</literal> and +<literal>BreakPoss.CAN_BREAK_AFTER</literal> in +<literal>iFlags</literal>,</para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>add the syllable length to the word + <literal>ipd</literal>.</para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>Else look for a legal line-break: breakable +white-space and certain characters such as '-' which can serve as word +breaks; don't look for hyphenation points here though, <itemizedlist spacing="compact"> + <listitem> + <para>for all following characters: <itemizedlist spacing="compact"> + <listitem> + <para>If this is a newline character +<literal>U+0A</literal>, or if <literal>textInfo.bWrap</literal> and +this is a breakable space, or if this is one of the linebreak +characters ("-/") and it is the first character or the preceding +character is a letter or a digit, <itemizedlist spacing="compact"> + <listitem> + <para>add the flag +<literal>BreakPoss.CAN_BREAK_AFTER</literal> to +<literal>iFlags</literal>,</para> + </listitem> + <listitem> + <para>if this is not a space + <literal>U+20</literal>, <itemizedlist spacing="compact"> + <listitem> + <para>move the counter to the next + character,</para> + </listitem> + <listitem> + <para>if this is a newline +<literal>U+0A</literal>, add the flag +<literal>BreakPoss.FORCE</literal> to +<literal>iFlags</literal>,</para> + </listitem> + <listitem> + <para>else add the character width +to the word <literal>ipd</literal>.</para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>if the rest of the text consists +of spaces <literal>U+20</literal>, register that the rest is +suppressible at a line break +(<literal>BreakPoss.REST_ARE_SUPPRESS_AT_LB</literal>) in +<literal>iFlags</literal>,</para> + </listitem> + <listitem> + <para>pass all the info to +<literal>makeBreakPoss</literal> and <literal>_return_</literal> its +breakposs.</para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>Else add the character width to the word + <literal>ipd</literal>,</para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>and continue with the cycle for the next + character.</para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>At the end of the text, pass all the info to +<literal>makeBreakPoss</literal> and <literal>_return_</literal> its +breakposs.</para> + </listitem> + </itemizedlist></para> + </section> + + <section> + <title><literal>TextLayoutManager.makeBreakPoss</literal></title> + + <itemizedlist spacing="compact"> + <listitem> + <para>Make word <literal>ipd</literal> into a + <literal>MinOptMax</literal> object.</para> + </listitem> + <listitem> + <para>Add space <literal>ipd</literal> to it.</para> + </listitem> + <listitem> + <para>Add total <literal>ipd</literal> from previous texts + to it.</para> + </listitem> + <listitem> + <para>Create an <literal>AreaInfo</literal> object for this +text fragment and add it to the vector of <literal>AreaInfo</literal> +objects.</para> + </listitem> + <listitem> + <para>Create a breakposs for this text fragment.</para> + </listitem> + <listitem> + <para>Set the total <literal>ipd</literal> to the current + <literal>ipd</literal>.</para> + </listitem> + <listitem> + <para>If the flags contain +<literal>BreakPoss.HYPHENATED</literal>, set the stacking size to the +<literal>ipd</literal> plus the width of the hyphen character,</para> + </listitem> + <listitem> + <para>Else set the stacking size to the + <literal>ipd</literal>.</para> + </listitem> + <listitem> + <para>Set the non-stacking size to the line height, from the + text info.</para> + </listitem> + <listitem> + <para>Register the descender and ascender with the breakposs +object; this is currently commented out.</para> + </listitem> + <listitem> + <para>If this is the end of the text, <itemizedlist spacing="compact"> + <listitem> + <para>add <literal>BreakPoss.ISLAST</literal> to the + flags,</para> + </listitem> + <listitem> + <para>declare the LM finished.</para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>Register the flags with the breakposs object</para> + </listitem> + <listitem> + <para>Register the pending space or the absence thereof with +the breakposs object.</para> + </listitem> + <listitem> + <para>Register the leading space or the absence thereof with +the breakposs object.</para> + </listitem> + <listitem> + <para>Return the breakposs object.</para> + </listitem> + </itemizedlist> + + </section> + + </chapter> + +<!-- Local Variables: --> +<!-- current-language-environment: UTF-8 --> +<!-- coding: utf-8 --> +<!-- default-input-method: TeX --> +<!-- End: --> diff --git a/src/documentation/content/xdocs/DnI/overview.xml b/src/documentation/content/xdocs/DnI/overview.xml new file mode 100644 index 000000000..aff1bc6c3 --- /dev/null +++ b/src/documentation/content/xdocs/DnI/overview.xml @@ -0,0 +1,152 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * Copyright 2004 The Apache Software Foundation. + * + * Licensed 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$ --> + +<!-- +<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" + "docbookx.dtd"> + --> + + <chapter> + + <title>Overview</title> + + <para>A FOP process has three stages:<orderedlist> + <listitem> + <simpara> building the FO tree,</simpara> + </listitem> + <listitem> + <simpara>building the Area tree,</simpara> + <orderedlist numeration="loweralpha"> + <listitem> + <simpara>The getNextBreakPoss call tree</simpara> + </listitem> + <listitem> + <simpara>The addAreas call tree</simpara> + </listitem> + <listitem> + <simpara>Finishing the page</simpara> + </listitem> + </orderedlist> + </listitem> + <listitem> + <simpara>rendering the pages.</simpara> + </listitem> + </orderedlist></para> + +<para>These stages are preceded by two other stages:<itemizedlist> + <listitem> + <simpara>0. <emphasis>preparation:</emphasis> the objects for +the FOP process are constructed; this phase may be done by FOP (apps +package), or by the calling application;</simpara> + </listitem> + <listitem> + <simpara>X. <emphasis>parsing:</emphasis> this phase is done +by a SAX parser; FOP's own preparation stage uses a JAXP +SAXParserFactory to call an available SAX parser.</simpara> + </listitem> + </itemizedlist></para> + + <para><emphasis>Stage 0.</emphasis> The preparation stage occurs +before the other stages. When it is completed it starts the parsing +stage by calling the parser's <literal>parse</literal> method.</para> + + <para>The parsing stage and stages 1, 2, 3 run concurrently. Each stage +calls into the following stage at appropriate points in its +process. It is feasible that stages 2 and 3 will run in separate +threads.</para> + + <para><emphasis>Stage X.</emphasis> The parser now takes control. +It parses the FO document or walks over the DOM tree. When it +encounters XML events such as the start or end of the document, the +start or end of an XML element, or character data, it makes a call +back into the FO tree builder.</para> + + <para><emphasis>Stage 1.</emphasis> The FO tree builder now takes +control to create or finish the FO node for which the XML event was +fired. When it is done, it returns control to the parser.</para> + + <para>The end events of a few XML elements invoke further actions +of the FO tree builder. When a page-sequence FO node is finished, the +FO tree builder notifies its tree listeners (of which there usually is +only one, the Area tree builder) of this event. Each listener in turn +takes control to process the page sequence.</para> + + <para><emphasis>Stage 2.</emphasis> The Area tree builder (which +is the tree listener) now takes control to lay out the page sequence +and construct the Area tree for it. This stage is divided in three +substages.</para> + + <para><emphasis>Stage 2a.</emphasis> The (pseudo)tree of possible +break points is created. Each node in the FO tree creates a Layout +Manager of the appropriate type. The resulting tree of Layout Managers +is recursed. Each Layout Manager asks each of its child Layout +Managers in turn to return a possible break point, until all child +Layout Managers are finished. This process is started by the Page +Layout Manager, which is tied to the page-sequence FO node that was +just completed in stage 1. Each time when its current child Layout +Manager returns a possible break point, a complete (pseudo)tree of +possible break points for a page has been collected. The next +substage takes control.</para> + + <para><emphasis>Stage 2b.</emphasis> Now the area tree is +created. The (pseudo)tree of possible break points and their Layout +Managers is recursed. Each possible break point may create an area. It +then calls the possible break points of the child LM that fall in this +area, to create and return their area, and adds those areas to its own +area. This process is started by the Page Layout Manager after the +previous substage has finished. When its possible break point returns +its area, the area tree for the flow of the page is complete.</para> + + <para><emphasis>Stage 2c.</emphasis> The Page Layout Manager adds +the static areas and hands the page to the Area tree builder, which +adds it to the root area. The Area tree builder now inspects the set +of complete pages, and fills in forward references to the page just +finished. Pages which are now complete including the forward +references contained in them, are handed over to the renderer, which +now takes control. When the renderer returns control, the Page Layout +Manager starts again in stage 2a to lay out the next page in the page +sequence.</para> + + <para>When all pages of this page sequence are done, this stage +finishes, and the Area tree builder returns control to the FO tree +builder.</para> + + <para><emphasis>Stage 3.</emphasis> The renderer now takes control +to render the finished pages. When it is done with those pages, it +returns control to the Area tree builder.</para> + + <para>This process model is FOP's default process model. It is +completely configurable, through the objects constructed in the +preparation stage. Stage 1 is configured by the content handler that +is registered with the parser. Stage 2 is configured by the listeners +that are registered with the FO tree builder. The layout process in +stage 2 is also configured by the layout strategy that is registered +with the Area tree builder. [It might be more appropriate to say that +stage 2 is controlled by the tree control object. The actual Area tree +builder is assigned by the layout strategy.] Stage 3 is configured by +the selected renderer or output format.</para> + + </chapter> + +<!-- Local Variables: --> +<!-- current-language-environment: UTF-8 --> +<!-- coding: utf-8 --> +<!-- default-input-method: TeX --> +<!-- End: --> diff --git a/src/documentation/content/xdocs/DnI/preparation.xml b/src/documentation/content/xdocs/DnI/preparation.xml new file mode 100644 index 000000000..e34b5452a --- /dev/null +++ b/src/documentation/content/xdocs/DnI/preparation.xml @@ -0,0 +1,470 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * Copyright 2004 The Apache Software Foundation. + * + * Licensed 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$ --> + +<!-- +<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" + "docbookx.dtd"> + --> + + <chapter> + <title>Phase 0: Preparation</title> + + <para>This chapter describes the structure of FOP as it was in the +first quarter of 2004. In the second quarter of that year the top +level structure was strongly refactored. The new situation is not +described here.</para> + + <section> + <title>The preparation process</title> + + <para>FOP's processing model is the SAX parsing model:<itemizedlist> + <listitem> + <simpara>Construct a suitable content handler object of type +<literal>org.xml.sax.ContentHandler</literal>,</simpara> + </listitem> + <listitem> + <simpara>create a parser of type +<literal>org.xml.sax.XMLReader</literal>,</simpara> + </listitem> + <listitem> + <simpara>register the content handler with the parser,</simpara> + </listitem> + <listitem> + <simpara>call the parser's parse method on the input +source.</simpara> + </listitem> + </itemizedlist></para> + + <para>From there on the parser takes control. For every XML +event it passes control to the appropriate content handler methods. +When these methods return, parsing continues until the next XML event +is encountered. Once the parser has taken control, its content handler +is the only entry point into FOP's data structures and methods.</para> + + <para>The preparatory phase of FOP concerns itself with the +construction of a suitable content handler object, whose methods allow +FOP's process to handle the FO elements reported by the parser and +build the required output document.</para> + + <para>An application may choose to deal with the whole +preparatory phase itself, and then call the parser's +<literal>parse</literal> method.</para> + + <para>The input source may be an FO file, which may be fed to +the <literal>parse</literal> method as a string or as an +<literal>org.xml.sax.InputSource</literal> object. Alternatively, a +DOM document object may be used as input, e.g. the output of an XSLT +processor. In that case:<itemizedlist> + <listitem> + <simpara> the parser should be of type +<literal>org.apache.fop.tools.DocumentReader</literal>,</simpara> + </listitem> + <listitem> + <simpara>the input source should be of type +<literal>org.apache.fop.tools.DocumentInputSource</literal>, created +with the DOM document as the argument of the constructor.</simpara> + </listitem> + </itemizedlist></para> + + <para>The classes <literal>Fop</literal> and +<literal>Driver</literal> contain methods which applications may use +as more convenient entry points into FOP.</para> + + <para>The method <literal>Fop.main</literal> may be called with +the input and output file names as arguments. This is mainly useful +for starting Fop from the command line.</para> + + <para>The class <literal>Driver</literal> contains a method +<literal>getContentHandler</literal>, which can be used to create a +suitable content handler. It also contains three +<literal>render</literal> methods which are convenient entry points +for applications.</para> + + <para>These 4 methods may be invoked on a driver object which +already has the following members: <literal>userAgent</literal>, +<literal>renderer</literal>, <literal>log</literal>, +<literal>stream</literal>. In addition, the driver object may have the +following members: a <literal>TreeBuilder</literal> object having a +member <literal>userAgent</literal>, and a <literal>Document</literal> +object, which may have a member <literal>layoutStrategy</literal>. +Using one's own <literal>TreeBuilder</literal> and +<literal>Document</literal> objects allows one to customize FOP's +behaviour in a major way.</para> + + <para>The <literal>render</literal> methods invoke +<literal>getContentHandler</literal> to create a suitable content +handler. They register it as the content handler of the parser. They +register the member <literal>currentDocument</literal> as a tree +listener to the member <literal>foInputHandler</literal>.</para> + + <para>A suitable <literal>org.xml.sax.ContentHandler</literal> +object for FOP processing is an object of type +<literal>org.apache.fop.fo.FOTreeBuilder</literal> and has the +following structure: +<screen> + treeBuilder + | + +--------------+------------------+ + | | | +foInputHandler userAgent foTreeControl + | | +foTreeControl driver +foTreeListeners: usedFonts + [foTreeControl] triplets + fonts + layoutStrategy -- foTreeControl + areaTree -- atModel, foTreeControl + atModel -- renderer + foInputHandler +</screen> +</para> + + <para>The <literal>driver</literal> and +<literal>renderer</literal> objects are complex objects: +<screen> + driver renderer + | | + treeBuilder foTreeControl + renderer userAgent + foInputHandler fontList + ostream ostream + userAgent + foTreeControl +</screen> +</para> + + </section> + + <section> + <title>A detailed overview of the objects</title> + + <screen> + treeBuilder = { + fobjTable: instance of java.util.HashMap(id=589) + namespaces: instance of java.util.HashSet(id=590) + currentFObj: null + rootFObj: null + foInputHandler: instance of org.apache.fop.fo.FOTreeHandler(id=591) + userAgent: instance of org.apache.fop.apps.FOUserAgent(id=592) + foTreeControl: instance of org.apache.fop.apps.Document(id=593) + class$org$apache$fop$fo$ElementMapping: instance of java.lang.Class(reflected class=org.apache.fop.fo.ElementMapping, id=450) +} +</screen> + + <screen> + treeBuilder.foInputHandler = { + collectStatistics: true + MEM_PROFILE_WITH_GC: false + runtime: instance of java.lang.Runtime(id=595) + pageCount: 0 + initialMemory: 0 + startTime: 0 + foTreeListeners: instance of java.util.HashSet(id=596) + org.apache.fop.fo.FOInputHandler.foTreeControl: instance of org.apache.fop.apps.Document(id=593) + org.apache.avalon.framework.logger.AbstractLogEnabled.m_logger: instance of org.apache.avalon.framework.logger.ConsoleLogger(id=597) +} +</screen> + + <screen> + treeBuilder.foTreeControl = "org.apache.fop.apps.Document@125844f" + treeBuilder.foInputHandler.foTreeListeners = "[org.apache.fop.apps.Document@125844f]" +</screen> + + <screen> + treeBuilder.userAgent = { + log: instance of org.apache.avalon.framework.logger.ConsoleLogger(id=597) + defaults: instance of java.util.HashMap(id=601) + handlers: instance of java.util.HashMap(id=602) + baseURL: "" + pdfEncryptionParams: null + px2mm: 0.35277778 +} +</screen> + + <screen> + treeBuilder.foTreeControl = { + driver: instance of org.apache.fop.apps.Driver(id=587) + usedFonts: instance of java.util.HashMap(id=604) + triplets: instance of java.util.HashMap(id=605) + fonts: instance of java.util.HashMap(id=606) + layoutStrategy: instance of org.apache.fop.layoutmgr.LayoutManagerLS(id=607) + areaTree: instance of org.apache.fop.area.AreaTree(id=608) + atModel: instance of org.apache.fop.area.RenderPagesModel(id=609) + bookmarks: null + idReferences: instance of java.util.HashSet(id=610) + foInputHandler: instance of org.apache.fop.fo.FOTreeHandler(id=591) +} +</screen> + + <screen> + treeBuilder.foTreeControl.driver = { + NOT_SET: 0 + RENDER_PDF: 1 + RENDER_AWT: 2 + RENDER_MIF: 3 + RENDER_XML: 4 + RENDER_PRINT: 5 + RENDER_PCL: 6 + RENDER_PS: 7 + RENDER_TXT: 8 + RENDER_SVG: 9 + RENDER_RTF: 10 + treeBuilder: instance of org.apache.fop.fo.FOTreeBuilder(id=588) + rendererType: 1 + renderer: instance of org.apache.fop.render.pdf.PDFRenderer(id=599) + foInputHandler: instance of org.apache.fop.fo.FOTreeHandler(id=591) + source: null + stream: instance of java.io.BufferedOutputStream(id=600) + reader: null + log: instance of org.apache.avalon.framework.logger.ConsoleLogger(id=597) + userAgent: instance of org.apache.fop.apps.FOUserAgent(id=592) + currentDocument: instance of org.apache.fop.apps.Document(id=593) +} +</screen> + + <screen> + treeBuilder.foTreeControl.areaTree = { + model: instance of org.apache.fop.area.RenderPagesModel(id=609) + atControl: instance of org.apache.fop.apps.Document(id=593) + idLocations: instance of java.util.HashMap(id=615) + resolve: instance of java.util.HashMap(id=616) + treeExtensions: instance of java.util.ArrayList(id=617) +} +</screen> + + <screen> + treeBuilder.foTreeControl.atModel = { + renderer: instance of org.apache.fop.render.pdf.PDFRenderer(id=599) + prepared: instance of java.util.ArrayList(id=618) + pendingExt: instance of java.util.ArrayList(id=619) + endDocExt: instance of java.util.ArrayList(id=620) + org.apache.fop.area.StorePagesModel.pageSequence: null + org.apache.fop.area.StorePagesModel.titles: instance of java.util.ArrayList(id=621) + org.apache.fop.area.StorePagesModel.currSequence: null + org.apache.fop.area.StorePagesModel.extensions: instance of java.util.ArrayList(id=622) +} +</screen> + + <screen> + treeBuilder.foTreeControl.atModel.renderer = { + MIME_TYPE: "application/pdf" + pdfDoc: instance of org.apache.fop.pdf.PDFDocument(id=624) + pages: null + pageReferences: instance of java.util.HashMap(id=625) + pvReferences: instance of java.util.HashMap(id=626) + ostream: instance of java.io.BufferedOutputStream(id=600) + pdfResources: null + currentStream: null + currentContext: null + currentPage: null + currentState: null + currentFontName: "" + currentFontSize: 0 + pageHeight: 0 + filterMap: null + textOpen: false + prevWordY: 0 + prevWordX: 0 + prevWordWidth: 0 + wordAreaPDF: instance of java.lang.StringBuffer(id=627) + BPMarginOffset: 0 + IPMarginOffset: 0 + org.apache.fop.render.PrintRenderer.fontInfo: instance of org.apache.fop.apps.Document(id=593) + org.apache.fop.render.PrintRenderer.fontList: null + org.apache.fop.render.AbstractRenderer.userAgent: instance of org.apache.fop.apps.FOUserAgent(id=592) + org.apache.fop.render.AbstractRenderer.producer: "FOP 1.0dev" + org.apache.fop.render.AbstractRenderer.creator: null + org.apache.fop.render.AbstractRenderer.creationDate: null + org.apache.fop.render.AbstractRenderer.options: instance of java.util.HashMap(id=629) + org.apache.fop.render.AbstractRenderer.currentBPPosition: 0 + org.apache.fop.render.AbstractRenderer.currentIPPosition: 0 + org.apache.fop.render.AbstractRenderer.currentBlockIPPosition: 0 + org.apache.fop.render.AbstractRenderer.containingBPPosition: 0 + org.apache.fop.render.AbstractRenderer.containingIPPosition: 0 + org.apache.avalon.framework.logger.AbstractLogEnabled.m_logger: instance of org.apache.avalon.framework.logger.ConsoleLogger(id=597) +} +</screen> + + <screen> + treeBuilder.foTreeControl.layoutStrategy = { + name: "layoutmgr" + addLMVisitor: null + org.apache.fop.layout.LayoutStrategy.name: "undefined" + org.apache.fop.layout.LayoutStrategy.document: instance of org.apache.fop.apps.Document(id=593) +} +</screen> + + <screen> + treeBuilder.foTreeControl.atModel.renderer.ostream = { + buf: instance of byte[512] (id=632) + count: 15 + java.io.FilterOutputStream.out: instance of java.io.FileOutputStream(id=633) +} +</screen> + + <para>For the members <literal>fontList<literal></literal>, +fonts</literal>, <literal>usedFonts<literal></literal> and +triplets<literal></literal> of treeBuilder.foTreeControl</literal>, +see under Fonts.</para> + </section> + + <section> + <title>A detailed overview of the entry methods</title> + + <para>Already created (e.g. in <literal>Fop.main</literal>): an +object of type <literal>Driver</literal> with the members +<literal>userAgent</literal>, <literal>renderer</literal>, +<literal>log</literal>, <literal>stream</literal>.</para> + + <para>To create <literal>userAgent</literal> one may use +<literal>Driver.getUserAgent</literal>: if <literal>driver</literal> +does not have <literal>userAgent</literal>, create a new +<literal>UserAgent</literal>.</para> + + <para>To create <literal>renderer</literal> one may use one of +three methods:<itemizedlist> + <listitem> + <simpara><literal>setRenderer(int +renderer)</literal></simpara> + </listitem> + <listitem> + <simpara><literal>setRenderer(String +rendererClassName)</literal></simpara> + </listitem> + <listitem> + <simpara><literal>setRenderer(Renderer +renderer)</literal></simpara> + </listitem> + </itemizedlist> All three methods set the FOP version on the +<literal>renderer</literal>, and register <literal>userAgent</literal> +with it, which is obtained using +<literal>Driver.getUserAgent</literal>.</para> + + <para><literal>render(InputHandler inputHandler)</literal>:<itemizedlist> + <listitem> + <simpara>creates <literal>XMLReader parser</literal>, +<literal>InputSource source</literal>;</simpara> + </listitem> + <listitem> + <simpara>calls <literal>render(XMLReader parser, +InputSource source)</literal>.</simpara> + </listitem> + </itemizedlist></para> + + <para><literal>render(org.w3c.dom.Document +document)</literal>:<itemizedlist> + <listitem> + <simpara>creates <literal>DocumentReader reader</literal>, +<literal>DocumentInputSource source</literal>;</simpara> + </listitem> + <listitem> + <simpara>calls <literal>render(XMLReader parser, +InputSource source)</literal>.</simpara> + </listitem> + </itemizedlist></para> + + <para><literal>render(XMLReader parser, InputSource +source)</literal>:<itemizedlist> + <listitem> + <simpara>creates content handler by calling +<literal>getContentHandler()</literal>.</simpara> + </listitem> + <listitem> + <simpara>registers the content handler with the parser.</simpara> + </listitem> + <listitem> + <simpara>Adds <literal>currentDocument</literal> as a tree +listener to <literal>foInputHandler</literal>.</simpara> + </listitem> + <listitem> + <simpara>calls <literal>parser.parse(source)</literal>.</simpara> + </listitem> + </itemizedlist></para> + + <para><literal>getContentHandler()</literal>:<itemizedlist> + <listitem> + <simpara>if driver does not have a +<literal>treeBuilder</literal>, call <literal>initialize()</literal>: +create a new <literal>TreeBuilder</literal>, set the +<literal>UserAgent</literal> on it.</simpara> + </listitem> + <listitem> + <simpara>if driver does not have a +<literal>currentDocument</literal>, create a new +<literal>Document</literal>.</simpara> + </listitem> + <listitem> + <simpara>create a new <literal>FOTreeHandler +foInputHandler</literal> using <literal>currentDocument</literal> as +an argument (<literal>currentDocument</literal> is member +<literal>foTreeControl</literal> in +<literal>foInputHandler</literal>).</simpara> + </listitem> + <listitem> + <simpara>create a new <literal>AreaTree</literal> using <literal>currentDocument</literal> as an argument, and +register it with <literal>currentDocument</literal>.</simpara> + </listitem> + <listitem> + <simpara>create a new <literal>RenderPagesModel</literal> +using <literal>renderer</literal> as an argument, and register it with +<literal>currentDocument</literal> and with +<literal>currentDocument.areaTree</literal>.</simpara> + </listitem> + <listitem> + <simpara>register <literal>currentDocument</literal> with +the <literal>renderer</literal> (<literal>currentDocument</literal> is +member <literal>fontInfo</literal> in <literal>renderer</literal>); +setup <literal>fontList</literal> in +<literal>currentDocument</literal>.</simpara> + </listitem> + <listitem> + <simpara>start the <literal>renderer</literal> with the +<literal>outputstream</literal>.</simpara> + </listitem> + <listitem> + <simpara>register <literal>foInputHandler</literal> with +<literal>currentDocument</literal>.</simpara> + </listitem> + <listitem> + <simpara>if <literal>currentDocument</literal> does not +have a <literal>layoutStrategy</literal>, create a new +<literal>LayoutStrategyLS</literal> for it with +<literal>currentDocument</literal> as an argument.</simpara> + </listitem> + <listitem> + <simpara>register <literal>userAgent</literal>, +<literal>foInputHandler</literal> and +<literal>currentDocument</literal> with <literal>treeBuilder</literal> +(<literal>currentDocument</literal> is member +<literal>foTreeControl</literal> in +<literal>treeBuilder</literal>).</simpara> + </listitem> + <listitem> + <simpara>return <literal>treeBuilder</literal>.</simpara> + </listitem> + </itemizedlist></para> + </section> + </chapter> + +<!-- Local Variables: --> +<!-- current-language-environment: UTF-8 --> +<!-- coding: utf-8 --> +<!-- default-input-method: TeX --> +<!-- End: --> diff --git a/src/documentation/content/xdocs/DnI/properties.xml b/src/documentation/content/xdocs/DnI/properties.xml new file mode 100644 index 000000000..632ccf946 --- /dev/null +++ b/src/documentation/content/xdocs/DnI/properties.xml @@ -0,0 +1,2455 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * Copyright 2004 The Apache Software Foundation. + * + * Licensed 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$ --> + +<!-- +<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" + "docbookx.dtd"> + --> + + <chapter id="ch.properties"> + <title>Properties</title> + +<section> + <title>The basic setup of the property subsystem</title> + + <section> + <title>Property values</title> + +<para>The FO nodes in the FO tree contain property values as specified +by the user. Each property value is represented by a object of type +<literal>org.apache.fop.fo.Property</literal>, or of a subtype +thereof.</para> + +<para>There are various types of property values: +<literal>CharacterProperty</literal>, +<literal>ColorTypeProperty</literal>, +<literal>CondLengthProperty</literal>, +<literal>EnumProperty</literal>, <literal>KeepProperty</literal>, +<literal>LengthPairProperty</literal>, +<literal>LengthProperty</literal>, +<literal>LengthRangeProperty</literal>, +<literal>ListProperty</literal>, <literal>NCnameProperty</literal>, +<literal>NumberProperty</literal>, <literal>NumericProperty</literal>, +<literal>RelativeNumericProperty</literal>, +<literal>StringProperty</literal>. The type +<literal>ToBeImplementedProperty</literal> is used for properties that +are not yet implemented. Some of these types have subtypes: +<literal>AutoLength</literal>, <literal>FixedLength</literal>, +<literal>PercentLength</literal>, <literal>TableColLength</literal> +are subclasses of <literal>LengthProperty</literal>; +<literal>SpaceProperty</literal> is a subclass of +<literal>LengthRangeProperty</literal>. Each of these types is a +subtype of <literal>org.apache.fop.fo.Property</literal>. +</para> + + <para>Property values may implement one or more of the interfaces +defined in the package <literal>org.apache.fop.datatypes</literal>: +<literal>Numeric</literal>, <literal>Length</literal>, +<literal>ColorType</literal></para> + + <para>Some properties actually represent a set of properties, such +as a minimum, an optimum and a maximum. These are represented by a +property value which implements the +<literal>CompoundDatatype</literal> interface. They contain a property +value for each member property.</para> + + </section> + + <section> + <title>The property list of an FO node</title> + + <para>Property values are held by the FO node corresponding to +the fo element on which they are specified by the user. FO nodes +contain a property list of type <literal>PropertyList</literal>, which +extends <literal>HashMap</literal>.</para> + + <para>The property types are known by the property +name as used on the FO element, e.g. <literal>font-size</literal>. For +efficiency of implementation, each type of property type is also known by +an <literal>integer</literal>, the <literal>propID</literal>. The +<literal>propID</literal>s are defined in the interface +<literal>org.apache.fop.fo.Constants</literal>, which gives them a +symbolic name of the form <literal>PR_</literal> + property name in +capitals and spaces replaced by underscores, +e.g. <literal>PR_FONT_SIZE</literal>. Wherever possible, the code uses +the <literal>propID</literal>s instead of the property names.</para> + +<para>When an FO requests a property, it does so by +<literal>propId</literal>. The request is eventually answered by +<literal>PropertyList.getExplicitBaseProp</literal>, but before it can +do so, it has to retrieve the property name from +<literal>FOPropertyMapping.getPropertyName</literal>. A particular +inefficiency as a consequence is found in +<filename>FopPropValFunction.java</filename> and some other classes in +the <literal>fo.expr</literal> package: + +<screen> +return pInfo.getPropertyList().get(FOPropertyMapping.getPropertyId(propName)) +</screen> + +Here <literal>propName</literal> -> <literal>propId</literal> mapping +is done, which later is reverted again.</para> + +<screen> + [1] org.apache.fop.fo.FOPropertyMapping.getPropertyName (FOPropertyMapping.java:486) + [2] org.apache.fop.fo.PropertyList.getExplicitBaseProp (PropertyList.java:230) + [3] org.apache.fop.fo.Property$Maker.findProperty (Property.java:281) + [4] org.apache.fop.fo.Property$Maker.get (Property.java:314) + [5] org.apache.fop.fo.PropertyList.get (PropertyList.java:281) + [6] org.apache.fop.fo.PropertyList.get (PropertyList.java:267) + [7] org.apache.fop.fo.FObj.getProperty (FObj.java:261) +</screen> + + </section> + + <section> + <title>Property makers</title> + + <para>Property value objects are created by a property maker of +type <literal>org.apache.fop.fo.PropertyMaker</literal>, or of a +subtype thereof. For each property type there is a property maker +object, which knows the property type, its default value, and some +other characteristics.</para> + + <para>The types of property makers are: +<literal>CharacterProperty.Maker</literal>, +<literal>ColorTypeProperty.Maker</literal>, +<literal>CompoundPropertyMaker</literal>, +<literal>EnumProperty.Maker</literal>, +<literal>LengthProperty.Maker</literal>, +<literal>ListProperty.Maker</literal>, +<literal>NumberProperty.Maker</literal>, +<literal>StringProperty.Maker</literal>, and +<literal>ToBeImplementedProperty.Maker</literal>.</para> + +<para>The property makers are lazily constructed when the +<literal>FObj</literal> constructor wants to create its static member +<literal>propertyListTable</literal>. The constructor calls +<literal>FOPropertyMapping.getGenericMappings()</literal>, which +constructs and returns +<literal>Property.Maker[Constants.PROPERTY_COUNT+1] +s_generics</literal>. The FObj constructor then copies this array of +<literal>PropertyMaker</literal>s into +<literal>propertyListTable</literal>.</para> + + <para><literal>public static PropertyMaker[] +getGenericMappings()</literal> first creates the shorthand property +makers, so that they can be used in the creation of the makers of the +real properties, and a set of generic property makers, which act as +templates for the real property makers. Next it creates the makers for +all property types. Related property types are grouped, +e.g. <literal>createFontProperties()</literal>.</para> + + <para>An example is the creation of the maker for the +<literal>font-size</literal> property type: + +<screen> + m = new LengthProperty.Maker(PR_FONT_SIZE); + m.setInherited(true); + m.setDefault("12pt"); + m.setPercentBase(LengthBase.INH_FONTSIZE); + addPropertyMaker("font-size", m); +</screen> + +Since <literal>font-size</literal> is a length, its maker is a +<literal>LengthProperty.Maker</literal>. It is inherited, and its +default value is 12 pt. If the user specifies the +<literal>font-size</literal> value as a percentage, then the actual +value is calculated from the <literal>font-size</literal> value +inherited from the parent FO node.</para> + + </section> + + <section> + <title>Shorthand properties</title> + + <section> + <title>Overview</title> + + <para>Shorthand properties are properties which are shorthand +for a number of properties. In other words, they specify the value of +a number of properties in a single attribute. All shorthand properties +can take a list of values, which are space separated in the FO +file. The FO spec specifies how this list of values determines the +values of the properties for which this is the shorthand (the target +properties.). The length of the list of values for a single shorthand +property may vary. For each length the attribution of these values to +the target properties is different.</para> + + <para>When the FO tree is constructed, shorthand property +values are parsed and stored like any other property value. Because +the value can be a list, it is always of type +<literal>ListProperty</literal>.</para> + +<para>The meaning of shorthand properties is only dealt with when the +value of one of the target properties is retrieved. For that purpose +each target property maker knows the shorthand properties that may set +its value, and when the target property value is retrieved, its maker +checks with each of its shorthand property makers if it has a +value. Note that the value of a shorthand property is never retrieved +directly, because shorthand properties have no direct meaning for the +layout.</para> + + <para>When the shorthand property value has been retrieved, +the value for the target property must be extracted from the +list. That is done by a shorthand parser, which implements +<literal>ShorthandParser</literal>. There are two implementing types: +<literal>GenericShorthandParser</literal> and +<literal>BoxPropShorthandParser</literal>. Their method +<literal>convertValueForProperty</literal> knows how each specified value +determines the value of the possible target properties. A shorthand +parser object is added to the shorthand property maker when the maker +is created.</para> + + <para>Note that <literal>CompoundPropertyMaker</literal> also +has a member <literal>shorthandMaker</literal>. I am not sure if this +has anything to do with shorthand properties. It seems more related to +<literal>CompoundPropertyMaker</literal> delegating certain tasks to a +subproperty maker, viz. the one which is the +<literal>shorthandMaker</literal>.</para> + + + </section> + + <section> + <title>Example of a shorthand property</title> + + <para>The property <literal>margin</literal> is shorthand for +the four properties <literal>margin-top</literal>, +<literal>margin-right</literal>, <literal>margin-bottom</literal>, +<literal>margin-left</literal>. Its value can consist of 1 to 4 width +values.</para> + +<para>When the property maker for <literal>margin</literal> is +created, it gets a <literal>BoxPropShorthandParser</literal> as +shorthand parser: +<screen> +m = new ListProperty.Maker(PR_MARGIN); +m.setInherited(false); +m.setDefault(""); +m.setDatatypeParser(new BoxPropShorthandParser()); +m.setPercentBase(LengthBase.BLOCK_WIDTH); +addPropertyMaker("margin", m); +</screen> + +When the property maker for <literal>margin-top</literal> is created, +the <literal>margin</literal> maker is registered with it as a +shorthand maker: +<screen> +m = new LengthProperty.Maker(PR_MARGIN_TOP); +m.setInherited(false); +m.setDefault("0pt"); +m.addShorthand(s_generics[PR_MARGIN]); +m.setPercentBase(LengthBase.BLOCK_WIDTH); +addPropertyMaker("margin-top", m); +</screen> +</para> + + <para>The maker for <literal>border-top-width</literal> has +three shorthands: <literal>border-top</literal>, +<literal>border-width</literal>, and <literal>border</literal>: +<screen> + this.shorthands = instance of org.apache.fop.fo.properties.PropertyMaker[3] (id=772) + this.shorthands[0] = "org.apache.fop.fo.properties.ListProperty$Maker@1e1dadb" + this.shorthands[0].propId = 52 + this.shorthands[1] = "org.apache.fop.fo.properties.ListProperty$Maker@bac9b9" + this.shorthands[1].propId = 56 + this.shorthands[2] = "org.apache.fop.fo.properties.ListProperty$Maker@8ceeea" + this.shorthands[2].propId = 18 +</screen></para> + + </section> + + <section> + <title>Parsing a shorthand property</title> + + <para>The value of a shorthand property is parsed and the value of a +target property is extracted in this call stack: + +<screen> + [1] org.apache.fop.fo.BoxPropShorthandParser.convertValueForProperty (BoxPropShorthandParser.java:80) + [2] org.apache.fop.fo.GenericShorthandParser.getValueForProperty (GenericShorthandParser.java:93) + [3] org.apache.fop.fo.properties.PropertyMaker.getShorthand (PropertyMaker.java:617) + [4] org.apache.fop.fo.properties.PropertyMaker.findProperty (PropertyMaker.java:277) + [5] org.apache.fop.fo.properties.PropertyMaker.get (PropertyMaker.java:305) + [6] org.apache.fop.fo.PropertyList.get (PropertyList.java:282) + [7] org.apache.fop.fo.PropertyList.get (PropertyList.java:268) + [8] org.apache.fop.fo.PropertyManager.getMarginProps (PropertyManager.java:301) +</screen> +</para> + + <para>The extraction proceeds as follows: +<itemizedlist spacing="compact"> + <listitem> + <para><literal>PropertyMaker.getShorthand</literal> +<itemizedlist spacing="compact"> + <listitem> + <para><literal>parser.getValueForProperty(propId, +listprop, propertyMaker, propertyList)</literal>; +<literal>propId</literal> is the ID of the target property, +<literal>listprop</literal> is the shorthand property value, of type +<literal>ListProperty</literal>, which was retrieved <itemizedlist +spacing="compact"> + <listitem> + <para>if the shorthand value is +<literal>inherit</literal>, get the value for the target property from +the parent.</para> + </listitem> + <listitem> + <para>else +<literal>convertValueForProperty(propId, listProperty, maker, +propertyList)</literal> <itemizedlist spacing="compact"> + <listitem> + <para>get from the shorthand list of +values the value that corresponds to the target property</para> + </listitem> + <listitem> + <para>if the retrieved value is not +<literal>null</literal>, convert the property, +<literal>maker.convertShorthandProperty(propertyList, p, +null)</literal> <itemizedlist spacing="compact"> + <listitem> + <para>first try to convert it in +the normal way: <literal>maker.convertProperty(prop, propertyList, +fo)</literal></para> + </listitem> + <listitem> + <para>if this gives a +<literal>null</literal> value, test if the value is an enumerated +value or a keyword; if so, process it.</para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + + </section> + + </section> + + <section> + <title>Corresponding properties</title> + + <para>A number of traits can be specified by two alternative +properties, e.g. <literal>border-left-width</literal> and +<literal>border-start-width</literal>. These are called corresponding +properties. One of a pair of corresponding properties is an absolute +property, the other is a relative property. The meaning of the +relative property depends on the writing mode. When the value of a +property is retrieved that has a corresponding property, the value of +that corresponding property should also be taken into account.</para> + + <para>Corresponding properties are registered with the property +maker when it is created: + +<screen> +bwm = new BorderWidthPropertyMaker(PR_BORDER_LEFT_WIDTH); +bwm.useGeneric(genericBorderWidth); +bwm.setBorderStyleId(PR_BORDER_LEFT_STYLE); +bwm.addShorthand(s_generics[PR_BORDER_LEFT]); +bwm.addShorthand(s_generics[PR_BORDER_WIDTH]); +bwm.addShorthand(s_generics[PR_BORDER]); +corr = new CorrespondingPropertyMaker(bwm); +corr.setCorresponding(PR_BORDER_START_WIDTH, PR_BORDER_END_WIDTH, + PR_BORDER_AFTER_WIDTH); +addPropertyMaker("border-left-width", bwm); +</screen> + +There are always three corresponding properties, for the three writing +modes <literal>lr_tb</literal>, <literal>rl_tb</literal>, +<literal>tb_rl</literal>, in this order: + +<screen> + corr = { + baseMaker: instance of org.apache.fop.fo.properties.BorderWidthPropertyMaker(id=702) + lr_tb: 50 + rl_tb: 36 + tb_rl: 22 + useParent: false + relative: false +} +</screen> +</para> + + <para>When a property value is retrieved, the value of the +corresponding property may have priority. This is determined by the +method <literal>corresponding.isCorrespondingForced()</literal>. This +is true if +<itemizedlist spacing="compact"> + <listitem> + <para>this is a relative property</para> + </listitem> + <listitem> + <para>and the corresponding property has been explicitly +specified on this FO node</para> + </listitem> + </itemizedlist> +Relative properties are marked by the fact that their corresponding +property maker has its member <literal>relative</literal> set to +<literal>true</literal>; this is set when the property is +created.</para> + + <para>If the corresponding property has priority, its value is +computed. Otherwise, if the value of the property itself has been +explicitly specified on this FO node, it is used. Otherwise, the +corresponding property is computed. Computation in this connection +means that also the shorthand properties are checked.</para> + +<para>Because shorthand properties only exist for absolute properties, +the values are effectively checked in this order: +<itemizedlist spacing="compact"> + <listitem> + <para>An absolute property <itemizedlist spacing="compact"> + <listitem> + <para>The explicit value of this property.</para> + </listitem> + <listitem> + <para>The explicit value of the corresponding +property.</para> + </listitem> + <listitem> + <para>The value of this property from the shorthand +properties.</para> + </listitem> + </itemizedlist></para> + </listitem> + + <listitem> + <para>A relative property <itemizedlist spacing="compact"> + <listitem> + <para>The explicit value of the corresponding +property.</para> + </listitem> + <listitem> + <para>The explicit value of this property.</para> + </listitem> + <listitem> + <para>The value of the corresponding property from +the shorthand properties.</para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist> +</para> + + </section> + + <section> + <title>Mapping between property names, IDs and makers</title> + +<para>The property subsystem is set up in the class +<literal>FOPropertyMapping</literal>. It creates a property maker +object for each property type, and it creates mappings of +the names, IDs and makers of the property types. It holds the +following static maps: + +<screen> +property name <=> property ID => property maker + | | + s_htSubPropNames (<-) s_htGeneric + s_htPropIds (->) +</screen> + +Each type of FObj holds a copy of <literal>s_htGeneric</literal> as +its static member <literal>FObj.propertyListTable</literal>. According +to design documents an FObj type may have its own specific makers for +certain property types. Probably this is the reason that +<literal>FObj</literal> holds its own copy of the list of makers. This +allows subclasses to hold their own modified copy. As far as I know, +this is not currently the case.</para> + +<para>The mappings are filled in the static method + +<screen> + private static void addPropertyMaker(String name, Property.Maker maker) { + s_generics[maker.getPropId()] = maker; + s_htPropNames.put(name, new Integer(maker.getPropId())); + s_htPropIds.put(new Integer(maker.getPropId()), name); + } +</screen> + +which is called for each property type.</para> + +<para>The constants for property IDs are defined in the interface +<literal>org.apache.fop.fo.Constants</literal>: + +<screen> + int PR_ABSOLUTE_POSITION = 1; + int PR_ACTIVE_STATE = 2; + ... + int PR_FONT_SIZE = 94; + ... + int PROPERTY_COUNT = 247; +</screen> +</para> + +<para>Composite properties are defined by a compound number: + +<screen> + int COMPOUND_SHIFT = 9; + int CP_MAXIMUM = 5 << COMPOUND_SHIFT; + int CP_MINIMUM = 6 << COMPOUND_SHIFT; + int CP_OPTIMUM = 7 << COMPOUND_SHIFT; + ... +</screen> +</para> + + <para>Enumerated property values are also defined here: + +<screen> + int ABSOLUTE = 1; + int ABSOLUTE_COLORMETRIC = 2; + ... + int VISIBLE = 105; + int WRAP = 106; +</screen></para> + + <para>For fast access to important characteristic of property +inheritance, <literal>PropertyList</literal> maintains a static array +<literal>boolean[Constants.PROPERTY_COUNT + 1] +inheritableProperty</literal>, which lists for each property type if +it is inherited. It is constructed by asking the maker of each +property type if it is inherited.</para> + +<para>A few members of the array of <literal>PropertyMaker</literal>s +<literal>s_generics</literal>. It is indexed by the +<literal>propID</literal>. Member 0 is <literal>null</literal>, and +serves for unknown property types. Member 1 is for +<literal>absolute-position</literal>, member 94 for +<literal>font-size</literal>. + +<screen> +main[1] print org.apache.fop.fo.FOPropertyMapping.s_generics + org.apache.fop.fo.FOPropertyMapping.s_generics = instance of org.apache.fop.fo.Property$Maker[248] (id=651) +main[1] print org.apache.fop.fo.FOPropertyMapping.s_generics[0] + org.apache.fop.fo.FOPropertyMapping.s_generics[0] = null +main[1] print org.apache.fop.fo.FOPropertyMapping.s_generics[1] + org.apache.fop.fo.FOPropertyMapping.s_generics[1] = "org.apache.fop.fo.EnumProperty$Maker@12884e0" +main[1] print org.apache.fop.fo.FOPropertyMapping.s_generics[94] + org.apache.fop.fo.FOPropertyMapping.s_generics[94] = "org.apache.fop.fo.LengthProperty$Maker@32efa7" +</screen> +</para> + + <para>A few members of the mapping <literal>s_htPropIds</literal> +from <literal>propID</literal> to property name. The +<literal>s_htPropIds</literal> for compound properties are shifted: + +<screen> +main[1] print org.apache.fop.fo.FOPropertyMapping.s_htPropIds + org.apache.fop.fo.FOPropertyMapping.s_htPropIds = "{ + 1=absolute-position + ... + 94=font-size + ... + 247=z-index + 512=block-progression-direction + 1024=conditionality + ... + 5632=within-page + }" +</screen> +</para> + +<para>A few members of the mappings <literal>s_htPropNames</literal> +and <literal>s_htSubPropNames</literal> from property name to +<literal>propID</literal>. The <literal>propIds</literal> for +compound properties are shifted: + +<screen> +main[1] print org.apache.fop.fo.FOPropertyMapping.s_htPropNames + org.apache.fop.fo.FOPropertyMapping.s_htPropNames = "{ + absolute-position=1 + ... + font-size=94 + ... + z-index=247 + }" +</screen> + +<screen> +main[1] print org.apache.fop.fo.FOPropertyMapping.s_htSubPropNames + org.apache.fop.fo.FOPropertyMapping.s_htSubPropNames = "{ + block-progression-direction=512 + conditionality=1024 + ... + within-page=5632 + }" +</screen> +</para> + + </section> + + <section> + <title>Storing the property values based on their +<literal>PropID</literal></title> + + <para>The class <literal>PropertySets</literal> contains a setup +by which property values may be retrieved by their +<literal>PropId</literal> instead of their name. In this setup +<literal>PropertyList</literal> no longer extends +<literal>HashMap</literal> but contains an array of property objects, +called <literal>values</literal>. In order to prevent that each FObj +should contain an array of size +<literal>Constants.PROPERTY_COUNT</literal>, a mapping is setup from a +static array for all FO types and all property types to an index for +the possible properties of an FO type, +<literal>PropertySets.mapping</literal>.</para> + +<para><literal>PropertySets.mapping</literal> is a +<literal>short[Constants.ELEMENT_COUNT+1][]</literal> matrix, which +for each FO type contains a mapping from <literal>PropID</literal> to +a sparse array of indices, which enumerates the properties that are +valid for this FO type.</para> + +<para>For an element <literal>fo:bar</literal> which supports 2 +properties, <literal>foo</literal>, whose <literal>PropID</literal> is +21, and <literal>baz</literal>, whose <literal>PropID</literal> is +137, the array of indices has the values + +<screen> + indices[21] = 1 + indices[137] = 2 +</screen> + +and all other values are 0. Here indices denotes the row in +<literal>mapping</literal> which corresponds to FO type bar.</para> + +<para>The values are indices into the array +<literal>PropertyList.values</literal>, which then looks like this: + +<screen> + values[0] = null // always null. + values[1] = reference to a 'foo' Property instance + values[2] = reference to a 'baz' Property instance +</screen> +</para> + +<para>Example of <literal>PropertySets.mapping</literal>: + +<screen> +PropID -> | 0 1 2 3 4 5 ... (Contants.PR_XXX) +Element | | + v | +-----------------|-------------------------------------------------- +FO_BASIC_LINK | 2 0 1 0 2 0 +FO_BIDI_OVERRIDE | 3 0 0 1 2 3 +FO_BLOCK | 2 1 0 0 2 0 +... | .... + | +</screen> +</para> + +<para>A property value of an <literal>FONode</literal> can then be +retrieved as <literal>PropertyList.values[indices[propId]]</literal>, +where <literal>indices = PropertySets.getPropertySet(elementId) = +PropertySets.mapping[elementId].</literal></para> + +<para>The matrix <literal>PropertySets.mapping</literal> is +constructed in the routine +<literal>PropertySets.initialize()</literal>.</para> + +<para>First it constructs the <literal>elements</literal> array. For +each FO type this array contains an <literal>Element</literal> +object. This object contains a list of properties which are valid for +this type of FO, and a list of child <literal>Element</literal> +objects. Each child <literal>Element</literal> object corresponds to +an FO type that may occur as a child of this FO type.</para> + +<para>Then the <literal>for (boolean dirty = true; dirty; )</literal> +loop is executed. It effect is as follows (from an email by Finn +Bock). For each FO type the <literal>BitSet</literal> of allowed +properties is merged with the <literal>BitSet</literal> of allowed +properties of its possible direct children. When for any FO type the +<literal>merge</literal> subroutine modifies its +<literal>BitSet</literal>, it sets the boolean variable +<literal>dirty</literal> to <literal>true</literal> to signal that +another iteration of the loop is required. By iterating over the loop +until no further modifications are made, one makes sure that the +merging process propagates from below to the top, that is, from any FO +type to its farthest possible ancestor. This ensures that every FO +type registers the allowed properties of itself and of all FO types +that may ever appear in its subtree.</para> + +<para>The matrix <literal>PropertySets.mapping</literal> is still not +used in <literal>PropertyList</literal>, and the array +<literal>values</literal> does not yet exist (19 May 2004). The +properties are held by name in <literal>PropertyList</literal>, which +extends <literal>HashMap</literal>.</para> + + </section> + + </section> + + <section id="sec.properties.create"> + <title>Creating a property value</title> + + <section> + <title>General</title> + + <para>A property value is created by the maker for the property type, +in its method +<literal>PropertyMaker.make(PropertyList, String, FObj)</literal>, +where the second argument is the property value as a string: +<itemizedlist spacing="compact"> + <listitem> + <para>If the specified value is <literal>inherit</literal>, +get the property value from the parent FObj.</para> + </listitem> + <listitem> + <para>Else if the value is an enumerated value, the corresponding +property value is retrieved (for each possible enumerated value only +one property value object exists, of type EnumProperty).</para> + </listitem> + <listitem> + <para>If this does not retrieve a property value, <itemizedlist +spacing="compact"> + <listitem> + <para>If the value is a shorthand keyword, it is +converted to the corresponding value.</para> + </listitem> + <listitem> + <para>The value is parsed, and a property value is +created.</para> + </listitem> + <listitem> + <para>The method +<literal>PropertyMaker.convertProperty</literal> is called, which is overridden +in subclasses of PropertyMaker. CompoundPropertyMaker uses this method +to convert the simple property value constructed to a compound +property value: <itemizedlist spacing="compact"> + <listitem> + <para>Make a compound property value based on +default values: <literal>PropertyMaker.makeCompound</literal>, +overridden in CompoundPropertyMaker.</para> + </listitem> + <listitem> + <para>Set all components equal to the +simple property value that is being converted.</para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>If this is a compound property maker, convert it to +a compound property as above. (Is this the second time the property +value is converted?)</para> + </listitem> + </itemizedlist> +The property may also record the value as specified in the fo element, +as this may influence the traits of the areas created by this FO node +and FO nodes in the subtree.</para> + +<para>Subclasses of <literal>PropertyMaker</literal> may override this +method. For example, <literal>StringProperty.Maker</literal> has a +much simpler method.</para> + +<para>Attributes of the fo elements are converted to property value +objects in <literal>PropertyList.convertAttributeToProperty</literal>: +<itemizedlist spacing="compact"> + <listitem> + <para>If the property is not a component of a compound +property, <itemizedlist spacing="compact"> + <listitem> + <para>Ask the maker for the property to create the +property value.</para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>Else if the property is a component of a compound +property, <itemizedlist spacing="compact"> + <listitem> + <para>Find the base property by a call to +<literal>Propertylist.findBaseProperty</literal>: <itemizedlist + spacing="compact"> + <listitem> + <para>If the base property value already exists, +return it to <literal>convertAttributeToProperty</literal>.</para> + </listitem> + <listitem> + <para>If the base attribute is also specified +(later) in the list of attributes, retrieve it, ask the maker for the +base property to create the base property value, and return it to +<literal>convertAttributeToProperty</literal>.</para> + </listitem> + <listitem> + <para>Return +null to <literal>convertAttributeToProperty</literal>.</para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>Ask the maker for the subproperty to create the +subproperty value by a call to <literal>PropertyMaker.make(Property, +int, PropertyList, String, FObj)</literal>, where the second argument +is the subproperty ID and the fourth argument is the specified +value. This method is overridden in +<literal>CompoundPropertyMaker</literal>: <itemizedlist +spacing="compact"> + <listitem> + <para>If the base property value does not yet +exist, ask its maker to create it with default values for the +components: <literal>PropertyMaker.makeCompound</literal>, which is +overridden in <literal>CompoundPropertyMaker</literal>: <itemizedlist +spacing="compact"> + <listitem> + <para>Create an empty property value.</para> + </listitem> + <listitem> + <para>Create property values for the +subproperties with default values, and insert them into the compound +property value.</para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>Create the specified subproperty value and +insert it into the compound property value, where it replaces the +default subproperty value.</para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>Add the property to the property list. +</para> + </listitem> + </itemizedlist></para> + + </section> + + <section> + <title>Example of a compound property</title> + +<para>In this example we illustrate the case where first the +base attribute of a compound property is specified, and then the +attribute for one of the components.</para> + +<para>First the user specifies the attribute value +<literal>leader-length="120pt"</literal>.</para> + +<para>A simple length property value is constructed first: +<screen> + p.getClass() = "class org.apache.fop.fo.properties.FixedLength" + p = { + millipoints: 120000 + org.apache.fop.fo.properties.Property.specVal: null +} + p = "120000mpt" +</screen></para> + +<para>Then it is converted into a compound property value. First a +compound property with default component values is created: +<screen> + p.getClass() = "class org.apache.fop.fo.properties.LengthRangeProperty" + p = { + minimum: instance of org.apache.fop.fo.properties.FixedLength(id=759) + optimum: instance of org.apache.fop.fo.properties.FixedLength(id=760) + maximum: instance of org.apache.fop.fo.properties.PercentLength(id=761) + bfSet: 0 + bChecked: true + org.apache.fop.fo.properties.Property.specVal: null +} + p = "LengthRange[min:0mpt, max:100.0%, opt:12000mpt]" +</screen> + +Then all components are set equal to the simple property value: +<screen> + prop.getClass() = "class org.apache.fop.fo.properties.LengthRangeProperty" + prop = { + minimum: instance of org.apache.fop.fo.properties.FixedLength(id=744) + optimum: instance of org.apache.fop.fo.properties.FixedLength(id=744) + maximum: instance of org.apache.fop.fo.properties.FixedLength(id=744) + bfSet: 7 + bChecked: true + org.apache.fop.fo.properties.Property.specVal: null +} + prop = "LengthRange[min:120000mpt, max:120000mpt, opt:120000mpt]" +</screen></para> + +<para>The property makers involved: +<screen> + this = "org.apache.fop.fo.properties.LengthRangeProperty$Maker@55a338" + this.subproperties = instance of org.apache.fop.fo.properties.PropertyMaker[11] (id=766) + getSubpropMaker(org.apache.fop.fo.Constants.CP_MINIMUM) = "org.apache.fop.fo.properties.LengthProperty$Maker@955cd5" + getSubpropMaker(org.apache.fop.fo.Constants.CP_MAXIMUM) = "org.apache.fop.fo.properties.LengthProperty$Maker@1bde4" + getSubpropMaker(org.apache.fop.fo.Constants.CP_OPTIMUM) = "org.apache.fop.fo.properties.LengthProperty$Maker@a77106" +</screen></para> + +<para>Stack dump when making the compound property: +<screen> + [1] org.apache.fop.fo.properties.CompoundPropertyMaker.makeCompound (CompoundPropertyMaker.java:258) + [2] org.apache.fop.fo.properties.CompoundPropertyMaker.convertProperty (CompoundPropertyMaker.java:173) + [3] org.apache.fop.fo.properties.LengthRangeProperty$Maker.convertProperty (LengthRangeProperty.java:68) + [4] org.apache.fop.fo.properties.PropertyMaker.make (PropertyMaker.java:392) + [5] org.apache.fop.fo.properties.CompoundPropertyMaker.make (CompoundPropertyMaker.java:206) + [6] org.apache.fop.fo.PropertyList.convertAttributeToProperty (PropertyList.java:418) + [7] org.apache.fop.fo.PropertyList.addAttributesToList (PropertyList.java:374) + [8] org.apache.fop.fo.FObj.addProperties (FObj.java:133) + [9] org.apache.fop.fo.FObj.processNode (FObj.java:96) + [10] org.apache.fop.fo.FOTreeBuilder.startElement (FOTreeBuilder.java:234) +</screen> +</para> + +<para>Subsequently, the user specifies a component, +<literal>leader-length.maximum="200pt"</literal>.</para> + +<para>First the subproperty is constructed as a simple length property: +<screen> + p.getClass() = "class org.apache.fop.fo.properties.FixedLength" + p = { + millipoints: 200000 + org.apache.fop.fo.properties.Property.specVal: null +} + p = "200000mpt" +</screen> +</para> + + <para>Then it is added to the compound property as the component +<literal>maximum</literal>: +<screen> + prop.getClass() = "class org.apache.fop.fo.properties.LengthRangeProperty" + prop = { + minimum: instance of org.apache.fop.fo.properties.FixedLength(id=755) + optimum: instance of org.apache.fop.fo.properties.FixedLength(id=755) + maximum: instance of org.apache.fop.fo.properties.FixedLength(id=767) + bfSet: 7 + bChecked: true + org.apache.fop.fo.properties.Property.specVal: null +} + prop = "LengthRange[min:120000mpt, max:200000mpt, opt:120000mpt]" +</screen> +</para> + +<para>Stack dump when making the property: +<screen> + [1] org.apache.fop.fo.properties.PropertyMaker.make (PropertyMaker.java:378) + [2] org.apache.fop.fo.properties.CompoundPropertyMaker.make (CompoundPropertyMaker.java:235) + [3] org.apache.fop.fo.PropertyList.convertAttributeToProperty (PropertyList.java:423) + [4] org.apache.fop.fo.PropertyList.addAttributesToList (PropertyList.java:374) + [5] org.apache.fop.fo.FObj.addProperties (FObj.java:133) + [6] org.apache.fop.fo.FObj.processNode (FObj.java:96) + [7] org.apache.fop.fo.FOTreeBuilder.startElement (FOTreeBuilder.java:234) +</screen></para> + + </section> + +<section> + <title>Enumerated property values</title> + + <para>The interface <literal>Constants</literal> defines values +for each possible enumerated value of a property: +<screen> + int ABSOLUTE = 1; + int ABSOLUTE_COLORMETRIC = 2; + ... + int VISIBLE = 105; + int WRAP = 106; +</screen></para> + + <para>In <literal>FOPropertyMapping</literal> a property value +object is constructed for each possible enumerated value. See the +<literal>Property</literal> array <literal>enums</literal> and the +method <literal>makeEnumProperty</literal>. During its construction, +each property maker that can have enumerated values gets a member +<literal>enums</literal>, which, for each of its possible enumerated +values, gets a reference to the appropriate enumerated property value +object. See the method <literal>PropertyMaker.addEnum</literal>.</para> + + <para>Example: The properties <literal>hyphenate</literal> and +<literal>precedence</literal> both have the possible value +<literal>true</literal>. Their makers have a reference to the same +property value object: +<screen> + org.apache.fop.fo.FOPropertyMapping.s_generics + [org.apache.fop.fo.Constants.PR_HYPHENATE]. + enums.get("true").hashCode() = 9236202 + org.apache.fop.fo.FOPropertyMapping.s_generics + [org.apache.fop.fo.Constants.PR_PRECEDENCE]. + enums.get("true").hashCode() = 9236202 + org.apache.fop.fo.FOPropertyMapping.s_generics + [org.apache.fop.fo.Constants.PR_HYPHENATE].enums.get("true") = "100" + org.apache.fop.fo.FOPropertyMapping.s_generics + [org.apache.fop.fo.Constants.PR_HYPHENATE].enums.get("true") = { + value: 100 + org.apache.fop.fo.properties.Property.specVal: null +} +</screen></para> + +<para>Example: <literal>leader-pattern="rule"</literal>. +<screen> + this = "org.apache.fop.fo.properties.EnumProperty$Maker@25c828" + this.enums = "{rule=82, use-content=104, dots=21, space=88}" + this.enums.get("rule").getClass() = "class org.apache.fop.fo.properties.EnumProperty" + this.enums.get("rule") = "82" + this.enums.get("rule") = { + value: 82 + org.apache.fop.fo.properties.Property.specVal: null +} +</screen></para> + +<para>The maker's method <literal>checkEnumValues</literal> returns +the appropriate property value object +<literal>enums.get(value)</literal>: <literal>newProp = +"82"</literal>.</para> + + <screen> + [1] org.apache.fop.fo.properties.PropertyMaker.checkEnumValues (PropertyMaker.java:480) + [2] org.apache.fop.fo.properties.EnumProperty$Maker.checkEnumValues (EnumProperty.java:50) + [3] org.apache.fop.fo.properties.PropertyMaker.make (PropertyMaker.java:383) + [4] org.apache.fop.fo.PropertyList.convertAttributeToProperty (PropertyList.java:418) + [5] org.apache.fop.fo.PropertyList.addAttributesToList (PropertyList.java:374) +</screen> + + </section> + +<section> + <title>Example of a property with keywords</title> + +<para>The value of the property <literal>border-top-width</literal> +can be set to a width, but it can also be indicated by one of the +keywords <literal>thin</literal>, <literal>medium</literal> and +<literal>thick</literal>. The width values to which these keywords +correspond are by default set by the implementation. When the property +maker is constructed in <literal>FOPropertyMapping</literal>, it gets +a hash map of keyword values. +<screen> + this = "org.apache.fop.fo.properties.BorderWidthPropertyMaker@1cf4a2c" + this.propId = 55 + this.keywords = "{medium=1pt, thin=0.5pt, thick=2pt}" +} +</screen> +</para> + +<para>The method <literal>checkValueKeywords</literal> returns the +mapped value: <literal>value = "1pt"</literal>. Subsequently a +property value object is created as if that value had been specified. + + <screen> + [1] org.apache.fop.fo.properties.PropertyMaker.checkValueKeywords (PropertyMaker.java:499) + [2] org.apache.fop.fo.properties.PropertyMaker.make (PropertyMaker.java:387) + [3] org.apache.fop.fo.PropertyList.convertAttributeToProperty (PropertyList.java:418) + [4] org.apache.fop.fo.PropertyList.addAttributesToList (PropertyList.java:374) + [5] org.apache.fop.fo.FObj.addProperties (FObj.java:133) +</screen> +</para> + + </section> + + <section> + <title>Parsing a property with an absolute value</title> + + <para>Property values are parsed in +<literal>PropertyParser.parseProperty</literal>: + <screen> + [1] org.apache.fop.fo.expr.PropertyParser.parseProperty (PropertyParser.java:111) + [2] org.apache.fop.fo.expr.PropertyParser.parse (PropertyParser.java:88) + [3] org.apache.fop.fo.properties.PropertyMaker.make (PropertyMaker.java:389) + [4] org.apache.fop.fo.PropertyList.convertAttributeToProperty (PropertyList.java:418) + [5] org.apache.fop.fo.PropertyList.addAttributesToList (PropertyList.java:374) + [6] org.apache.fop.fo.FObj.addProperties (FObj.java:133) +</screen></para> + + <para>Example: <literal><fo:simple-page-master +master-name="simpleA4" margin="4pt"></literal>, property being parsed: +<literal>margin="4pt"</literal>, <literal>propId</literal> = 134.</para> + +<para>The PropertyParser object: +<screen> + this = "org.apache.fop.fo.expr.PropertyParser@8530b8" + this = { + propInfo: instance of org.apache.fop.fo.expr.PropertyInfo(id=729) + org.apache.fop.fo.expr.PropertyTokenizer.currentToken: 0 + org.apache.fop.fo.expr.PropertyTokenizer.currentTokenValue: null + org.apache.fop.fo.expr.PropertyTokenizer.currentUnitLength: 0 + org.apache.fop.fo.expr.PropertyTokenizer.currentTokenStartIndex: 0 + org.apache.fop.fo.expr.PropertyTokenizer.expr: "4pt" + org.apache.fop.fo.expr.PropertyTokenizer.exprIndex: 0 + org.apache.fop.fo.expr.PropertyTokenizer.exprLength: 3 + org.apache.fop.fo.expr.PropertyTokenizer.recognizeOperator: false +} +</screen></para> + + <para>It has a member of type <literal>PropertyInfo</literal>, +which contains contextual information: +<screen> + propInfo = "org.apache.fop.fo.expr.PropertyInfo@1abcc03" + propInfo = { + maker: instance of org.apache.fop.fo.properties.ListProperty$Maker(id=705) + plist: instance of org.apache.fop.fo.PropertyList(id=737) + fo: instance of org.apache.fop.fo.pagination.LayoutMasterSet(id=738) + stkFunction: null +} +</screen> +<literal>fo</literal> is the parent FO.</para> + +<para>The property list of the current FO node: +<screen> + propInfo.plist = { + writingModeTable: null + writingMode: 0 + inheritableProperty: null + parentPropertyList: instance of org.apache.fop.fo.PropertyList(id=743) + namespace: "http://www.w3.org/1999/XSL/Format" + elementName: "fo:simple-page-master" + fobj: instance of org.apache.fop.fo.pagination.SimplePageMaster(id=746) +} +</screen> +The property list up to now: +<screen> + propInfo.plist = "{master-name=simpleA4}" +</screen> +</para> + + <para>Property <literal>master-name</literal>'s maker is +<literal>StringPropertyMaker</literal>, which does not parse its +value.</para> + + <para>PropertyParser.parseProperty <itemizedlist +spacing="compact"> + <listitem> + <para>next(), which scans the next token; at its return: +<screen> + this = { + propInfo: instance of org.apache.fop.fo.expr.PropertyInfo(id=667) + org.apache.fop.fo.expr.PropertyTokenizer.currentToken: 12 + org.apache.fop.fo.expr.PropertyTokenizer.currentTokenValue: "4pt" + org.apache.fop.fo.expr.PropertyTokenizer.currentUnitLength: 2 + org.apache.fop.fo.expr.PropertyTokenizer.currentTokenStartIndex: 0 + org.apache.fop.fo.expr.PropertyTokenizer.expr: "4pt" + org.apache.fop.fo.expr.PropertyTokenizer.exprIndex: 3 + org.apache.fop.fo.expr.PropertyTokenizer.exprLength: 3 + org.apache.fop.fo.expr.PropertyTokenizer.recognizeOperator: true +} +</screen> +i.e. the whole expression is a single token, it is of type +<literal>PropertyTokenizer.TOK_NUMERIC</literal> (= 12), the unit is 2 +chars long.</para> + </listitem> + <listitem> + <para>Loop forever. <itemizedlist +spacing="compact"> + <listitem> + <para>Analyse the expression. Start with +<literal>parseAdditiveExpr</literal> <itemizedlist spacing="compact"> + <listitem> + <para><literal>parseMultiplicativeExpr</literal> +<itemizedlist spacing="compact"> + <listitem> + <para><literal>parseUnaryExpr</literal> +<itemizedlist spacing="compact"> + <listitem> + <para><literal>parsePrimaryExpr</literal>; +the unit may be a relative unit (em) which must be resolved against +the font size <itemizedlist spacing="compact"> + <listitem> + <para>construct a property +value object: +<screen> + prop = "4000mpt" + prop.getClass() = "class org.apache.fop.fo.properties.FixedLength" +</screen></para> + </listitem> + <listitem> + <para><literal>next()</literal>: +scan the next token; +<screen> + this = { + propInfo: instance of org.apache.fop.fo.expr.PropertyInfo(id=729) + org.apache.fop.fo.expr.PropertyTokenizer.currentToken: 0 + org.apache.fop.fo.expr.PropertyTokenizer.currentTokenValue: null + org.apache.fop.fo.expr.PropertyTokenizer.currentUnitLength: 2 + org.apache.fop.fo.expr.PropertyTokenizer.currentTokenStartIndex: 3 + org.apache.fop.fo.expr.PropertyTokenizer.expr: "4pt" + org.apache.fop.fo.expr.PropertyTokenizer.exprIndex: 3 + org.apache.fop.fo.expr.PropertyTokenizer.exprLength: 3 + org.apache.fop.fo.expr.PropertyTokenizer.recognizeOperator: true +} +</screen> +the next token is of type <literal>currentToken = +PropertyTokenizer.TOK_EOF</literal>.</para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>If <literal>currentToken = +PropertyTokenizer.TOK_EOF</literal>, break the loop.</para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist> +Return the property: <literal>p = "4000mpt"</literal>.</para> + </section> + + </section> + +<section> + <title>Retrieving a property value</title> + + <section> + <title>Overview</title> + + <para>For all FO types the FO spec specifies a large number of +property types for which the user may specify a value in order to +modify the resulting layout of the document. Many of these properties +have a default value, many others inherit their value from the parent +FO if they are not specified. In principle the layout process must +retrieve the value of each possible property type of an FO node in +order to determine the appropriate value of the corresponding +trait.</para> + + <para>Retrieving a property value goes through these steps: +<itemizedlist spacing="compact"> + <listitem> + <para>First determine if the property value was specified +in one or other way. This is done in the method +<literal>propertyMaker.findProperty</literal> <itemizedlist +spacing="compact"> + <listitem> + <para>if this property has a corresponding property +and if the corresponding property is forced, i.e. if this property is +relative and if a value for the corresponding property was explicitly +specified, compute and return it.</para> + </listitem> + <listitem> + <para>else <itemizedlist spacing="compact"> + <listitem> + <para>if a value for this property was +explicitly specified, compute and return it</para> + </listitem> + <listitem> + <para>else if this property has a +corresponding property, compute its value; if it is not null return +it</para> + </listitem> + <listitem> + <para>else if a value for a relevant shorthand +property was specified, compute and return it</para> + </listitem> + <listitem> + <para>else if this property is inheritable, +find it at the parent; this repeats the whole process on the parent, +and possibly its parents, up to the root node; if successful, return +the found property value</para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>If no property value is found, a default property +value object is made; the default value is stored in the property +maker as <literal>defaultValue</literal>: <itemizedlist +spacing="compact"> + <listitem> + <para>if the default property value object was +calculated earlier, it was cached as +<literal>defaultProperty</literal>; return it</para> + </listitem> + <listitem> + <para>else make it in the same way as property value +objects are made when the FO tree is constructed, in +<literal>propertyMaker.make</literal>.</para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + + <para>Compute corresponding, as used in +<literal>findProperty</literal>, proceeds as follows: <itemizedlist +spacing="compact"> + <listitem> + <para>use parent's property list or this property +list?</para> + </listitem> + <listitem> + <para>check explicit or shorthand for corresponding</para> + </listitem> + <listitem> + <para>convert property</para> + </listitem> + </itemizedlist></para> + +<para><literal>PropertyManager</literal>, +<literal>CommonBorderAndPadding</literal>, +<literal>CommonBackground</literal>, +<literal>CommonMarginBlock</literal>, +<literal>CommonHyphenation</literal> are convenience classes used in +the calculation of the traits. <literal>PropertyManager</literal> has +methods to return objects of these types. A +<literal>CommonBorderAndPadding</literal> object and a +<literal>CommonHyphenation</literal> object are cached. A +<literal>CommonBackground</literal> object and a +<literal>CommonMarginBlock</literal> object are calculated when +requested. Similarly for many other convenience classes +<literal>Common*</literal> for which +<literal>PropertyManager</literal> can return an object. These classes +are in package <literal>fo.properties</literal>. Similar classes +called <literal>*Props</literal> are in package +<literal>traits</literal>. Of these <literal>PropertyManager</literal> +can only return a <literal>BlockProps</literal> object.</para> + + </section> + + <section> + <title>Detailed overview</title> + + <para>The retrieval of a property value is started with a call +to <literal>PropertyList.get(int propId)</literal>, which calls +<literal>PropertyList.get(propId, true, true)</literal>.</para> + +<para><literal>PropertyList.get(int propId, boolean bTryInherit, +boolean bTryDefault)</literal>: +<itemizedlist spacing="compact"> + <listitem> + <para>Find the maker for this property as +<literal>FObj.propertyListTable[propId]</literal>, variable +<literal>propertyMaker</literal></para> + </listitem> + <listitem> + <para><literal>propertyMaker.get(int subpropId, +PropertyList propertyList, boolean bTryInherit, boolean +bTryDefault)</literal> <itemizedlist spacing="compact"> + <listitem> + <para><literal>propertyMaker.findProperty(PropertyList +propertyList, boolean bTryInherit)</literal> <itemizedlist +spacing="compact"> + <listitem> + <para>if corresponding and corresponding is +forced <itemizedlist spacing="compact"> + <listitem> + <para>evaluate condition: +<literal>CorrespondingPropertyMaker.isCorrespondingForced +(PropertyList propertyList)</literal> <itemizedlist spacing="compact"> + <listitem> + <para> <itemizedlist +spacing="compact"> + <listitem> + <para>return false if this is +not a relative property +(<literal>corresponding.relative</literal>)</para> + </listitem> + <listitem> + <para>return true if +corresponding property was explicitly specified on this node or on its +parent, depending on the type of property +(<literal>corresponding.useParent</literal>)</para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para><literal>corresponding.compute(PropertyList +propertyList)</literal>; this subroutine and the subroutines it calls +refer to the corresponding property <itemizedlist spacing="compact"> + <listitem> + <para><literal>propertyList.getExplicitOrShorthand(correspondingId)</literal>; +propertyList is that of this node or of the parent, depending on the +type of property (corresponding.useParent) <itemizedlist +spacing="compact"> + <listitem> + <para><literal>propertyList.getExplicitBaseProp(int +correspondingId)</literal> (see below)</para> + </listitem> + <listitem> + <para>if +<literal>(null)</literal> <literal>propertyList.getShorthand(int +correspondingId)</literal> <itemizedlist spacing="compact"> + <listitem> + <para><literal>propertyMaker.getShorthand(this)</literal> +(see below)</para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>if <literal>(not +null)</literal> convert property</para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>else <itemizedlist spacing="compact"> + <listitem> + <para><literal>propertyList.getExplicitBaseProp(int +propId)</literal> from <literal>propertyList</literal> as a hash map; +note that this requires a conversion from <literal>propId</literal> to +<literal>propName</literal> via <literal>s_htPropNames</literal>; +example: <literal>propertyList = +"{master-name=simpleA4}"</literal></para> + </listitem> + <listitem> + <para>if <literal>(null)</literal> +<literal>propertyMaker.compute(PropertyList propertyList)</literal>: +<itemizedlist spacing="compact"> + <listitem> + <para>if +<literal>(corresponding)</literal> +<literal>corresponding.compute(PropertyList propertyList)</literal>, +as above</para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>if <literal>(null)</literal> +<literal>propertyMaker.getShorthand(PropertyList +propertyList)</literal> <itemizedlist spacing="compact"> + <listitem> + <para>if +<literal>(maker.shorthands)</literal> then for each shorthand +<itemizedlist spacing="compact"> + <listitem> + <para><literal>propertyList.getExplicit(int +shorthand.propId)</literal>; a shorthand must be +<literal>ListProperty</literal></para> + </listitem> + <listitem> + <para>if <literal>(not +null)</literal> parse the shorthand property value, +<literal>parser.getValueForProperty(propId, listprop, propertyMaker, +this, propertyList)</literal>; here <literal>propId</literal> is the +<literal>propId</literal> of this property, not of the shorthand; a +shorthand may contain values for several properties, and this method +retrieves the value for the current property; if <literal>(not +null)</literal> return it</para> + </listitem> + </itemizedlist>Note: the first +shorthand property maker in <literal>maker.shorthands</literal> that +returns a good property is used</para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>if <literal>(null && +bTryInherit)</literal> +<literal>propertyMaker.findProperty(parentPropertyList, +true)</literal>: the whole process is repeated on the parent, and +possibly its parents, up to the root node.</para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>if <literal>(null && bTryDefault)</literal> +<literal>propertyMaker.make(PropertyList propertyList)</literal> +<itemizedlist spacing="compact"> + <listitem> + <para>if there is a cached value, +<literal>defaultProperty</literal>, return it</para> + </listitem> + <listitem> + <para><literal>propertyMaker.make(PropertyList +propertyList, String value, FObj fo)</literal>; +<literal>value</literal> is the default value stored in the property +maker, <literal>fo</literal> is the parent FO <itemizedlist +spacing="compact"> + <listitem> + <para>if default value is +<literal>inherit</literal>, +propertyList.getFromParent(<literal>propId</literal>) +<itemizedlist spacing="compact"> + <listitem> + <para>if +<literal>(parentPropertyList != null)</literal> +<literal>parentPropertyList.get(propId)</literal>; the whole process +is repeated on the parent, and possibly its parents, up to the root +node.</para> + </listitem> + <listitem> + <para><literal>propertyMaker.make(PropertyList +propertyList)</literal>; this seems to create an endless recursion; +<literal>parentPropertyList == null</literal> in the root node.</para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>else check enumerated values +<literal>propertyMaker.checkEnumValues(value)</literal>: get the +enumerated property from <literal>propertyMaker.enums</literal></para> + </listitem> + <listitem> + <para>if <literal>(null)</literal> +<itemizedlist spacing="compact"> + <listitem> + <para><literal>propertyMaker.checkValueKeywords(String +value)</literal>; check if the value is a keyword in +<literal>propertyMaker.keywords</literal>; if so, substitute the value +with the value for which the keyword stands</para> + </listitem> + <listitem> + <para>parse the value <literal>p = +PropertyParser.parse(pvalue, new PropertyInfo(propertyMaker, +propertyList, fo))</literal></para> + </listitem> + <listitem> + <para>convert the property +<literal>propertyMaker.convertProperty(p, propertyList, +fo)</literal></para> + </listitem> + <listitem> + <para>if <literal>(null)</literal> +throw <literal>org.apache.fop.fo.expr.PropertyException</literal>, +which immediately is catched and rethrown as +<literal>FOPException</literal> (why?)</para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>catch <literal>FOPException</literal>; this +means that this method may return a <literal>null</literal> +property</para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>catch <literal>FOPException</literal>; this means that +this method may return a <literal>null</literal> property</para> + </listitem> + </itemizedlist></para> + + <para>The call stack at the <literal>findProperty</literal> and +<literal>make</literal>calls is: +<screen> + [1] org.apache.fop.fo.properties.PropertyMaker.findProperty (PropertyMaker.java:240) + [2] org.apache.fop.fo.properties.PropertyMaker.get (PropertyMaker.java:282) + [3] org.apache.fop.fo.PropertyList.get (PropertyList.java:252) + [4] org.apache.fop.fo.PropertyList.get (PropertyList.java:238) + [5] org.apache.fop.fo.FObj.getProperty (FObj.java:163) + [6] org.apache.fop.layoutmgr.PageLayoutManager.createPageAreas (PageLayoutManager.java:745) +</screen> +<screen> + [1] org.apache.fop.fo.properties.PropertyMaker.make (PropertyMaker.java:387) + [2] org.apache.fop.fo.properties.PropertyMaker.make (PropertyMaker.java:369) + [3] org.apache.fop.fo.properties.PropertyMaker.get (PropertyMaker.java:285) + [4] org.apache.fop.fo.PropertyList.get (PropertyList.java:252) + [5] org.apache.fop.fo.PropertyList.get (PropertyList.java:238) + [6] org.apache.fop.fo.FObj.getProperty (FObj.java:163) + [7] org.apache.fop.layoutmgr.PageLayoutManager.createPageAreas (PageLayoutManager.java:745) +</screen> +For properties whose maker is compound property maker: +<screen> + [1] org.apache.fop.fo.properties.PropertyMaker.findProperty (PropertyMaker.java:240) + [2] org.apache.fop.fo.properties.PropertyMaker.get (PropertyMaker.java:282) + [3] org.apache.fop.fo.properties.CompoundPropertyMaker.get (CompoundPropertyMaker.java:146) + [4] org.apache.fop.fo.PropertyList.get (PropertyList.java:252) + [5] org.apache.fop.fo.PropertyList.get (PropertyList.java:238) + [6] org.apache.fop.fo.flow.Leader.getLength (Leader.java:135) + [7] org.apache.fop.layoutmgr.AddLMVisitor.getLeaderAllocIPD (AddLMVisitor.java:305) + [8] org.apache.fop.layoutmgr.AddLMVisitor$2.getAllocationIPD (AddLMVisitor.java:290) + [9] org.apache.fop.layoutmgr.LeafNodeLayoutManager.getNextBreakPoss (LeafNodeLayoutManager.java:143) +</screen></para> + + </section> + + <section> + <title>Examples: Retrieving border and padding values</title> + +<para>In this section we follow in detail how the border and padding +values for the body region are retrieved. The relevant part of the +input FO file is: + +<screen> +<![CDATA[<fo:simple-page-master master-name="simpleA4" margin="4pt"> +<fo:region-body margin="4pt+20%" border="3pt solid black" + border-before-width="2pt" border-right-width="4pt" + border-start-width="inherit"/> +</fo:simple-page-master>]]> +</screen> +</para> + + <para>This section was written after I added the cache to the +look-up of property values.</para> + + <section> + + <title>Retrieving the <literal>margin-top</literal> value on +<literal>region-body</literal></title> + +<para>This what we are retrieving: + +<screen> + propertyList.getFOName() = "fo:region-body" + org.apache.fop.fo.FOPropertyMapping.getPropertyName(propId) = "margin-top" +</screen> + +The margin values are retrieved by the method +<literal>PropertyManager.getMarginProps</literal>. This is the call +stack that leads up to it and on to the retrieval of the value of +<literal>margin-top</literal>: + +<screen> + [1] org.apache.fop.fo.properties.PropertyMaker.findProperty (PropertyMaker.java:240) + [2] org.apache.fop.fo.PropertyList.findProperty (PropertyList.java:289) + [3] org.apache.fop.fo.properties.PropertyMaker.get (PropertyMaker.java:291) + [4] org.apache.fop.fo.PropertyList.get (PropertyList.java:261) + [5] org.apache.fop.fo.PropertyList.get (PropertyList.java:247) + [6] org.apache.fop.fo.PropertyManager.getMarginProps (PropertyManager.java:264) + [7] org.apache.fop.fo.pagination.RegionBody.getViewportRectangle (RegionBody.java:58) + [8] org.apache.fop.layoutmgr.PageLayoutManager.makeRegionViewport (PageLayoutManager.java:811) + [9] org.apache.fop.layoutmgr.PageLayoutManager.createPageAreas (PageLayoutManager.java:784) + [10] org.apache.fop.layoutmgr.PageLayoutManager.createPage (PageLayoutManager.java:721) + [11] org.apache.fop.layoutmgr.PageLayoutManager.makeNewPage (PageLayoutManager.java:441) + [12] org.apache.fop.layoutmgr.PageLayoutManager.doLayout (PageLayoutManager.java:191) +</screen> +</para> + +<para>The retrieval proceeds as follows: +<itemizedlist spacing="compact"> +<listitem> +<para><literal>PropertyList.findProperty</literal>: Is the value in +the cache? No.</para> +</listitem> +<listitem> +<para><literal>PropertyMaker.findProperty</literal>: +<literal>corresponding != null</literal>? No.</para> +</listitem> +<listitem> +<para><literal>PropertyMaker.findProperty</literal>: Is this property +explicitly specified? No.</para> +</listitem> +<listitem> +<para><literal>PropertyMaker.findProperty</literal>: Can the +corresponding property be computed? No, there is no corresponding +property.</para> +</listitem> +<listitem> +<para><literal>PropertyMaker.findProperty</literal>: Is a shorthand +property for this property specified? Yes, <literal>margin</literal> +is a shorthand for it. The property value is retrieved as: +<screen> + listprop = "[(4000mpt +20.0%)]" +</screen> +It is a list property as are all shorthand properties. The +value for <literal>margin-top</literal> is extracted from it as: +<screen> + p = "(4000mpt +20.0%)" +</screen> +</para> +</listitem> +<listitem> +<para><literal>PropertyList.findProperty</literal>: Add the value to +the cache.</para> +</listitem> + </itemizedlist> +</para> + </section> + + <section> + <title>Retrieving the <literal>border-before-style</literal> +value on <literal>region-body</literal></title> + +<para>This what we are retrieving: + +<screen> + propertyList.getFOName() = "fo:region-body" + org.apache.fop.fo.FOPropertyMapping.getPropertyName(propId) = "border-before-style" +</screen> + +The border values are retrieved by the method +<literal>PropertyManager.getBorderAndPadding</literal>. This is the call +stack that leads up to it and on to the retrieval of the value of +<literal>border-before-style</literal>: + +<screen> + [1] org.apache.fop.fo.properties.PropertyMaker.findProperty (PropertyMaker.java:240) + [2] org.apache.fop.fo.PropertyList.findProperty (PropertyList.java:289) + [3] org.apache.fop.fo.properties.PropertyMaker.get (PropertyMaker.java:291) + [4] org.apache.fop.fo.PropertyList.get (PropertyList.java:261) + [5] org.apache.fop.fo.PropertyList.get (PropertyList.java:247) + [6] org.apache.fop.fo.PropertyManager.initBorderInfo (PropertyManager.java:155) + [7] org.apache.fop.fo.PropertyManager.getBorderAndPadding (PropertyManager.java:143) + [8] org.apache.fop.fo.PropertyManager.getMarginProps (PropertyManager.java:289) + [9] org.apache.fop.fo.pagination.RegionBody.getViewportRectangle (RegionBody.java:58) + [10] org.apache.fop.layoutmgr.PageLayoutManager.makeRegionViewport (PageLayoutManager.java:811) + [11] org.apache.fop.layoutmgr.PageLayoutManager.createPageAreas (PageLayoutManager.java:784) + [12] org.apache.fop.layoutmgr.PageLayoutManager.createPage (PageLayoutManager.java:721) + [13] org.apache.fop.layoutmgr.PageLayoutManager.makeNewPage (PageLayoutManager.java:441) + [14] org.apache.fop.layoutmgr.PageLayoutManager.doLayout (PageLayoutManager.java:191) +</screen> +</para> + +<para>The retrieval proceeds as follows: +<itemizedlist spacing="compact"> +<listitem> +<para><literal>PropertyList.findProperty</literal>: Is the value in +the cache? No.</para> +</listitem> +<listitem> +<para><literal>PropertyMaker.findProperty</literal>: +<literal>corresponding != null</literal>, but +<literal>corresponding.isCorrespondingForced()</literal> returns +<literal>false</literal>. The corresponding property is +<literal>border-top-style</literal>, which is not specified: + +<screen> + org.apache.fop.fo.FOPropertyMapping.getPropertyName(correspondingId) = "border-top-style" +</screen> +This is the corresponding property maker: +<screen> + this = { + baseMaker: instance of org.apache.fop.fo.properties.EnumProperty$Maker(id=816) + lr_tb: 54 + rl_tb: 54 + tb_rl: 43 + useParent: false + relative: true +} +</screen> +</para> + </listitem> +<listitem> +<para><literal>PropertyMaker.findProperty</literal>: Is this property +explicitly specified? No.</para> +</listitem> +<listitem> +<para><literal>PropertyMaker.findProperty</literal>: Can the +corresponding property be computed? Yes, it can be derived from the +property <literal>border</literal>, which is a shorthand for the +corresponding property <literal>border-top-style</literal>. The +returned value is <literal>87</literal>, which stands for +<literal>SOLID</literal>.</para> +<para>Note that the shorthand was not used in the +computation of +<literal>corresponding.isCorrespondingForced()</literal>, but it is in +the computation of the specified value of the corresponding +property.</para> +</listitem> +<listitem> +<para><literal>PropertyList.findProperty</literal>: Add the value to +the cache.</para> +</listitem> + </itemizedlist></para> + </section> + + <section> + <title>Retrieving the <literal>border-before-width</literal> +value on <literal>region-body</literal></title> + +<para>This what we are retrieving: + +<screen> + propertyList.getFOName() = "fo:region-body" + org.apache.fop.fo.FOPropertyMapping.getPropertyName(propId) = "border-before-width" +</screen> + +The border values are retrieved by the method +<literal>PropertyManager.getBorderAndPadding</literal>. This is the call +stack that leads up to it and on to the retrieval of the value of +<literal>border-before-width</literal>: + +<screen> +main[1] where + [1] org.apache.fop.fo.properties.PropertyMaker.findProperty (PropertyMaker.java:240) + [2] org.apache.fop.fo.PropertyList.findProperty (PropertyList.java:289) + [3] org.apache.fop.fo.properties.PropertyMaker.get (PropertyMaker.java:291) + [4] org.apache.fop.fo.properties.CompoundPropertyMaker.get (CompoundPropertyMaker.java:146) + [5] org.apache.fop.fo.PropertyList.get (PropertyList.java:261) + [6] org.apache.fop.fo.PropertyList.get (PropertyList.java:247) + [7] org.apache.fop.fo.PropertyManager.initBorderInfo (PropertyManager.java:157) + [8] org.apache.fop.fo.PropertyManager.getBorderAndPadding (PropertyManager.java:143) + [9] org.apache.fop.fo.PropertyManager.getMarginProps (PropertyManager.java:289) + [10] org.apache.fop.fo.pagination.RegionBody.getViewportRectangle (RegionBody.java:58) + [11] org.apache.fop.layoutmgr.PageLayoutManager.makeRegionViewport (PageLayoutManager.java:811) + [12] org.apache.fop.layoutmgr.PageLayoutManager.createPageAreas (PageLayoutManager.java:784) + [13] org.apache.fop.layoutmgr.PageLayoutManager.createPage (PageLayoutManager.java:721) + [14] org.apache.fop.layoutmgr.PageLayoutManager.makeNewPage (PageLayoutManager.java:441) + [15] org.apache.fop.layoutmgr.PageLayoutManager.doLayout (PageLayoutManager.java:191) +</screen> + +The difference with the call stack for +<literal>border-before-style</literal> is that +<literal>border-before-width</literal> is a compound property, with +a <literal>minimum</literal>, an <literal>optimum</literal> and a +<literal>maximum</literal> value. +</para> + +<para>The retrieval proceeds as follows: +<itemizedlist spacing="compact"> +<listitem> +<para><literal>PropertyList.findProperty</literal>: Is the value in +the cache? No.</para> +</listitem> + <listitem> +<para><literal>PropertyMaker.findProperty</literal>: +<literal>corresponding != null</literal>, but +<literal>corresponding.isCorrespondingForced()</literal> returns +<literal>false</literal>. The corresponding property is +<literal>border-top-width</literal>, which is not specified: + +<screen> + org.apache.fop.fo.FOPropertyMapping.getPropertyName(correspondingId) = "border-top-width" +</screen> +</para> + </listitem> + <listitem> + <para><literal>PropertyMaker.findProperty</literal>: Is +this property explicitly specified? Yes. The property value is +retrieved as: +<screen> + p = "CondLength[2000mpt]" +</screen> +The specified value was <literal>2pt</literal>. When this attribute +value was added to the property list, it was converted to a +<literal>CondLength</literal> type. +</para> + </listitem> + +<listitem> +<para><literal>PropertyList.findProperty</literal>: Add the value to +the cache.</para> +</listitem> + </itemizedlist> +</para> + </section> + + <section> + <title>Retrieving the <literal>border-end-width</literal> +value on <literal>region-body</literal></title> + +<para>This what we are retrieving: + +<screen> + propertyList.getFOName() = "fo:region-body" + org.apache.fop.fo.FOPropertyMapping.getPropertyName(propId) = "border-end-width" +</screen> + +The border values are retrieved by the method +<literal>PropertyManager.getBorderAndPadding</literal>. The call stack +that leads up to it and on to the retrieval of the value of +<literal>border-end-width</literal> is identical to the call stack for +<literal>border-before-width</literal>. +</para> + +<para>The retrieval proceeds as follows: +<itemizedlist spacing="compact"> +<listitem> +<para><literal>PropertyList.findProperty</literal>: Is the value in +the cache? No.</para> +</listitem> +<listitem> +<para><literal>PropertyMaker.findProperty</literal>: +<literal>corresponding != null</literal>, and +<literal>corresponding.isCorrespondingForced()</literal> returns +<literal>true</literal>. The corresponding property is +<literal>border-right-width</literal>, which is explicitly specified: + +<screen> + org.apache.fop.fo.FOPropertyMapping.getPropertyName(correspondingId) = "border-right-width" +</screen> +</para> + </listitem> +<listitem> +<para><literal>PropertyMaker.findProperty</literal>: Compute the +corresponding property value. It is retrieved as: +<screen> + p = "CondLength[discard, 4000mpt]" +</screen> +The specified value was <literal>4pt</literal>. When this attribute +value was added to the property list, it was converted to a +<literal>CondLength</literal> type.</para> + </listitem> +<listitem> +<para><literal>PropertyList.findProperty</literal>: Add the value to +the cache.</para> +</listitem> + </itemizedlist> +</para> + </section> + + </section> + + </section> + +<!-- +The implementation before bug 26778: Properties leader-length + +leader-length.maximum="30%" +leader-length.minimum="20%" +leader-length.optimum="25%" + +basePropertyName = "leader-length" +subPropertyName = "maximum" +propId = 124 +subpropId = 2560 + +main[1] where + [1] org.apache.fop.fo.flow.Leader.getLength (Leader.java:167) + [2] org.apache.fop.layoutmgr.AddLMVisitor.getLeaderAllocIPD (AddLMVisitor.java:361) + [3] org.apache.fop.layoutmgr.AddLMVisitor$2.getAllocationIPD (AddLMVisitor.java:342) + [4] org.apache.fop.layoutmgr.LeafNodeLayoutManager.getNextBreakPoss (LeafNodeLayoutManager.java:166) + [5] org.apache.fop.layoutmgr.LineLayoutManager.getNextBreakPoss (LineLayoutManager.java:215) + [6] org.apache.fop.layoutmgr.BlockLayoutManager.getNextBreakPoss (BlockLayoutManager.java:240) + [7] org.apache.fop.layoutmgr.FlowLayoutManager.getNextBreakPoss (FlowLayoutManager.java:111) + [8] org.apache.fop.layoutmgr.PageLayoutManager.getNextBreakPoss (PageLayoutManager.java:261) + [9] org.apache.fop.layoutmgr.PageLayoutManager.doLayout (PageLayoutManager.java:226) + +propId = Constants.PR_LEADER_LENGTH | Constants.CP_MAXIMUM + = 2684 = 124 + 2560 + +In this older implementation the base value is obtained from the +layout context and propagated to the calculation: + +LeafNodeLayoutManager.getNextBreakPoss: + ipd = getAllocationIPD(context.getRefIPD()); +AddLMVisitor.getLeaderAllocIPD: + node.getLength(Constants.PR_LEADER_LENGTH | Constants.CP_MAXIMUM, ipd); +Leader.getLength: + length = (int)(((PercentLength) maxlength).value() * dim); + +This is wrong because it does not find out at which node the property +is specified and from which node the base length should be +obtained. In the new implementation LengthBase contains this +information as member parentFO: +main[1] dump maxlength + maxlength = { + factor: 0.3 + lbase: instance of org.apache.fop.datatypes.LengthBase(id=773) + org.apache.fop.fo.properties.Property.specVal: null +} +main[1] dump maxlength.lbase + maxlength.lbase = { + parentFO: instance of org.apache.fop.fo.flow.Block(id=776) + propertyList: instance of org.apache.fop.fo.PropertyList(id=777) + iBaseType: 3 +} + +Result: +ipd = "MinOptMax: min=67520; opt=84400; max=101280" +--> + + <section> + <title>Percent-based and mixed property values</title> + + <section> + <title>Overview</title> + + <para>Properties may have relative values, expressed as a +percentage. The value is relative to a trait of the layout. Therefore +relative values can only be evaluated when the layout is +created. The FO tree must store them as an expression.</para> + + <para>The FO spec specifies for each property that can have a +relative value, which trait is the basis for the evaluation of the +relative value. FOP maintains that information in the property maker, +in its member <literal>percentBase</literal>. This is set when the +maker is created, see <literal>FOPropertyMapping</literal>.</para> + + <para>When the maker creates a relative property value object, +it stores its own member <literal>percentBase</literal> in the +property as member <literal>iBaseType</literal>. In this way the +property value contains the information that is needed at layout time to +find the trait that is the basis for the calculation of the actual +value.</para> + + <para>The possible values of the member +<literal>percentBase</literal> are listed in class +<literal>LengthBase</literal>. Both the interface +<literal>PercentBase</literal> and the class +<literal>LengthBase</literal> define static constants which are used +as types. The difference is as follows (from an email by Finn Bock, +edited by me): The idea is that the <literal>PercentBase.XXX</literal> +types name the stored values and the <literal>LengthBase.XXX</literal> +types name the algorithms for looking up a base value. Most of the +time these map one-to-one to each other, but for some I imaged that +they would be different. For example, <literal>margin-top</literal> +should really use an algorithm like +<literal>BLOCK_IPD_OR_PAGEHEIGHT</literal>, which would look for +either <literal>PercentBase.BLOCK_IPD</literal> or +<literal>PercentBase.PAGE_HEIGHT</literal>, depending on the FO +element.</para> + + <para>A <literal>LengthBase</literal> object contains a +reference to a parent FO node and a reference to a property list. In +this manner the <literal>LengthBase</literal> value contains the +information that is needed at layout time to locate the FO node or +property list which contains the trait that is the basis for the +calculation of the actual value, irrespective of the FO node at which +the property is resolved.</para> + + <para>The method <literal>LengthBase.getBaselength</literal> +uses the base type, member <literal>iBaseType</literal>, to determine +relative to which layout trait the value should be resolved. If the +trait is a property value, it is retrieved from the property list, in +the usual manner. If it is a layout dimension, it is taken from the +parent FO.</para> + + <para>The interface <literal>Numeric</literal>, which is +implemented by all classes that can participate in numeric operations, +uses the notion of <literal>dimension</literal>, which denotes the +type of numeric: for integers <literal>dimension = 0</literal>, for +lengths <literal>dimension = 1</literal>.</para> + + <para>The constructor of +<literal>RelativeNumericProperty</literal> calculates the dimension of +the new property value object as a combination of the dimensions of +the operands, depending on the operation: +<itemizedlist spacing="compact"> + <listitem> + <para>multiplication adds dimensions: 0+0=0, 0+1=1+0=1,</para> + </listitem> + <listitem> + <para>division subtracts dimensions: 0-0=0, 1-0=1, 1-1=0,</para> + </listitem> + <listitem> + <para>other (addition, subtraction) does not change the +dimensions</para> + </listitem> + </itemizedlist></para> + + <para>A <literal>RelativeProperty</literal> contains the +operation between the operands in its member +<literal>operation</literal>. It is an integer. Names for the possible +integer values are listed as static members of class +<literal>RelativeProperty</literal>.</para> + + <para>Relative and mixed property values are retrieved in the +usual manner. After retrieval they must be resolved against the +relevant layout traits. This happens in the method +<literal>getValue</literal> of <literal>Property</literal> and its +subclasses.</para> + + <para>A <literal>RelativeNumericProperty</literal> is resolved +as follows: <itemizedlist spacing="compact"> + <listitem> + <para><literal>RelativeNumericProperty.getValue</literal> +<itemizedlist spacing="compact"> + <listitem> + <para><literal>RelativeNumericProperty.getNumericValue</literal> +<itemizedlist spacing="compact"> + <listitem> + <para><literal>RelativeNumericProperty.getResolved</literal>. +This evaluates the expression tree by recursion. The nodes in the tree +are <literal>RelativeNumericProperty</literal> objects. The leaf nodes +are <literal>FixedLength</literal> and +<literal>PercentLength</literal> objects. On each node +<literal>getNumericValue</literal> is called. <itemizedlist +spacing="compact"> + <listitem> + <para>The relative numeric property +values call <literal>getResolved</literal> again, which descends the +tree and calls <literal>getNumericValue</literal> on its child +nodes.</para> + </listitem> + <listitem> + <para>The fixed lengths return their +millipoints.</para> + </listitem> + <listitem> + <para>The percent lengths return +<literal>factor * lbase.getBaseLength()</literal> <itemizedlist +spacing="compact"> + <listitem> + <para><literal>factor</literal> is +a member of the percent length object.</para> + </listitem> + <listitem> + <para><literal>LengthBase.getBaselength</literal> +gets the base length from the parent FO <itemizedlist spacing="compact"> + <listitem> + <para><literal>FObj.getLayoutDimension</literal>. +The value is retrieved from the <literal>Map +layoutDimension</literal>. If that does not contain the desired layout +dimension, then its parent is consulted, all the way up to +<literal>fo:root</literal>.</para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + + </section> + + <section> + <title>Parsing a mixed property value</title> + + <para>Example: <literal><fo:region-body +margin="4pt+20%"/></literal>, property being parsed: +<literal>margin="4pt+20%"</literal>, <literal>propId</literal> = +134.</para> + +<para><literal>PropertyParser.parseProperty</literal> +<itemizedlist spacing="compact"> + <listitem> + <para><literal>next()</literal>, which scans the next token; +at its return: +<screen> + this = { + propInfo: instance of org.apache.fop.fo.expr.PropertyInfo(id=736) + org.apache.fop.fo.expr.PropertyTokenizer.currentToken: 12 + org.apache.fop.fo.expr.PropertyTokenizer.currentTokenValue: "4pt" + org.apache.fop.fo.expr.PropertyTokenizer.currentUnitLength: 2 + org.apache.fop.fo.expr.PropertyTokenizer.currentTokenStartIndex: 0 + org.apache.fop.fo.expr.PropertyTokenizer.expr: "4pt+20%" + org.apache.fop.fo.expr.PropertyTokenizer.exprIndex: 3 + org.apache.fop.fo.expr.PropertyTokenizer.exprLength: 7 + org.apache.fop.fo.expr.PropertyTokenizer.recognizeOperator: true +} +</screen> +i.e. the whole expression is a single token, it is of type +<literal>PropertyTokenizer.TOK_NUMERIC</literal> (= 12), the unit is +2 chars long.</para> + </listitem> + <listitem> + <para>Loop forever. <itemizedlist spacing="compact"> + <listitem> + <para>Analyse the expression. Start with +<literal>parseAdditiveExpr</literal> <itemizedlist spacing="compact"> + <listitem> + <para><literal>parseMultiplicativeExpr</literal> +<itemizedlist spacing="compact"> + <listitem> + <para><literal>parseUnaryExpr</literal> +<itemizedlist spacing="compact"> + <listitem> + <para><literal>parsePrimaryExpr</literal>; +the unit may be a relative unit (em) which must be resolved against +the font size <itemizedlist spacing="compact"> + <listitem> + <para>construct a property +value object: +<screen> +prop = "4000mpt" +prop.getClass() = "class org.apache.fop.fo.properties.FixedLength" +</screen></para> + </listitem> + <listitem> + <para><literal>next()</literal>: +scan for the next token; +<screen> + this = { + propInfo: instance of org.apache.fop.fo.expr.PropertyInfo(id=736) + org.apache.fop.fo.expr.PropertyTokenizer.currentToken: 8 + org.apache.fop.fo.expr.PropertyTokenizer.currentTokenValue: null + org.apache.fop.fo.expr.PropertyTokenizer.currentUnitLength: 2 + org.apache.fop.fo.expr.PropertyTokenizer.currentTokenStartIndex: 3 + org.apache.fop.fo.expr.PropertyTokenizer.expr: "4pt+20%" + org.apache.fop.fo.expr.PropertyTokenizer.exprIndex: 4 + org.apache.fop.fo.expr.PropertyTokenizer.exprLength: 7 + org.apache.fop.fo.expr.PropertyTokenizer.recognizeOperator: false +} +</screen> +the next token is of type <literal>currentToken = +PropertyTokenizer.TOK_PLUS</literal>.</para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para><literal>next()</literal>: +scan for the next token; +<screen> + this = { + propInfo: instance of org.apache.fop.fo.expr.PropertyInfo(id=736) + org.apache.fop.fo.expr.PropertyTokenizer.currentToken: 14 + org.apache.fop.fo.expr.PropertyTokenizer.currentTokenValue: "20%" + org.apache.fop.fo.expr.PropertyTokenizer.currentUnitLength: 2 + org.apache.fop.fo.expr.PropertyTokenizer.currentTokenStartIndex: 4 + org.apache.fop.fo.expr.PropertyTokenizer.expr: "4pt+20%" + org.apache.fop.fo.expr.PropertyTokenizer.exprIndex: 7 + org.apache.fop.fo.expr.PropertyTokenizer.exprLength: 7 + org.apache.fop.fo.expr.PropertyTokenizer.recognizeOperator: true +} +</screen> +the next token is of type <literal>currentToken = +PropertyTokenizer.TOK_PERCENT</literal>. +The currentTokenValue <literal>20%</literal> is analysed:</para> + </listitem> + <listitem> + <para><literal>parseMultiplicativeExpr</literal> +<itemizedlist spacing="compact"> + <listitem> + <para><literal>parseUnaryExpr</literal> +<itemizedlist spacing="compact"> + <listitem> + <para><literal>parsePrimaryExpr</literal> +<itemizedlist spacing="compact"> + <listitem> + <para><literal>propInfo.getPercentBase</literal>: +create a PercentBase property +<itemizedlist spacing="compact"> + <listitem> + <para><literal>propInfo.getFunctionPercentBase</literal> +uses a stack of functions stkFunction, which currently <literal>== +null</literal></para> + </listitem> + <listitem> + <para><literal>if (null) +maker.getPercentBase(fo, plist)</literal>: create and return a +<literal>LengthBase</literal> property, which implements +<literal>PercentBase</literal> +<screen> + pcBase = "org.apache.fop.datatypes.LengthBase@171f189" + pcBase = { + parentFO: instance of org.apache.fop.fo.pagination.SimplePageMaster(id=786) + propertyList: instance of org.apache.fop.fo.PropertyList(id=807) + iBaseType: 5 +} +</screen> +the value of <literal>iBaseType</literal> is derived from +<literal>maker.percentBase == 5 == +LengthBase.BLOCK_WIDTH</literal>.</para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para><literal>pcBase.getDimension</literal>; +dimension: type of integer, int → 0, length → 1; used by +<literal>PercentBase</literal> and <literal>NumericProperty</literal>; +<literal>LengthBase</literal> has a dimension of 1</para> + </listitem> + <listitem> + <para>create a +<literal>PercentLength(pcval, pcBase)</literal>: +<screen> + prop = "20.0%" + prop = { + factor: 0.2 + lbase: instance of org.apache.fop.datatypes.LengthBase(id=751) + org.apache.fop.fo.properties.Property.specVal: null +} +</screen> +<literal>factor</literal> comes from <literal>pcval</literal>, +<literal>lbase = pcBase</literal></para> + </listitem> + <listitem> + <para><literal>next()</literal>: +scan for the next token; the next token is of type +<literal>currentToken = PropertyTokenizer.TOK_EOF</literal>.</para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>return the <literal>LengthBase</literal> +property value object</para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para><literal>evalAddition(NumericProperty op1, +NumericProperty op2)</literal>. <literal>op1</literal> and +<literal>op2</literal> are now <literal>Numeric</literal>, which is an +interface implemented by <literal>LengthProperty</literal>, of which +<literal>FixedLength</literal> and <literal>PercentLength</literal> +are subclasses: +<screen> +op1 = instance of org.apache.fop.fo.properties.FixedLength(id=744) +op2 = instance of org.apache.fop.fo.properties.PercentLength(id=757) +</screen> <itemizedlist spacing="compact"> + <listitem> + <para><literal>NumericOp.addition</literal> +<itemizedlist spacing="compact"> + <listitem> + <para>Construct a new +<literal>RelativeNumericProperty</literal> by adding the two +properties: +<literal>RelativeNumericProperty(RelativeNumericProperty.ADDITION, +op1, op2)</literal></para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist></para> + </listitem> + <listitem> + <para>If <literal>currentToken = +PropertyTokenizer.TOK_EOF</literal>, break the loop.</para> + </listitem> + </itemizedlist></para> + </listitem> + </itemizedlist> +return the <literal>RelativeNumericProperty</literal>: +<screen> + prop = "(4000mpt +20.0%)" + prop = { + operation: 1 + op1: instance of org.apache.fop.fo.properties.FixedLength(id=744) + op2: instance of org.apache.fop.fo.properties.PercentLength(id=757) + dimension: 1 + org.apache.fop.fo.properties.Property.specVal: null +} +</screen> +The value 1 for the operation corresponds to +<literal>RelativeProperty.ADDITION</literal>. The value 1 for the +dimension indicates that this is a length. PropertyList: +<screen> + this = "{margin=[(4000mpt +20.0%)]}" +</screen></para> + </section> + + <section> + <title>Resolving a mixed property value</title> + + <para>Example: Resolving the value of the property +<literal>margin-left</literal> of the FO node +<literal>fo:region-body</literal>. This value was specified as +<literal><fo:region-body margin="4pt+20%"/></literal>. +<literal>margin</literal> is a shorthand property for +<literal>margin-left</literal>.</para> + +<para>The property list of <literal>fo:region-body</literal> reads: +<screen> + this = "{margin=[(4000mpt +20.0%)]}" +</screen> +The retrieved property value is a +<literal>RelativeNumericProperty</literal>: +<screen> + prop = "(4000mpt +20.0%)" + prop = { + operation: 1 + op1: instance of org.apache.fop.fo.properties.FixedLength(id=817) + op2: instance of org.apache.fop.fo.properties.PercentLength(id=818) + dimension: 1 + org.apache.fop.fo.properties.Property.specVal: null +} +</screen> +The value 1 for the operation corresponds to +<literal>RelativeProperty.ADDITION</literal>. The value 1 for the +dimension indicates that this is a length. +<screen> + op2 = "20.0%" + op2 = { + factor: 0.2 + lbase: instance of org.apache.fop.datatypes.LengthBase(id=751) + org.apache.fop.fo.properties.Property.specVal: null +} + lbase = "org.apache.fop.datatypes.LengthBase@171f189" + lbase = { + parentFO: instance of org.apache.fop.fo.pagination.SimplePageMaster(id=786) + propertyList: instance of org.apache.fop.fo.PropertyList(id=807) + iBaseType: 5 +} +</screen> +</para> + +<para>The <literal>RelativeNumericProperty</literal> is resolved in +the method call +<screen> + props.marginLeft = + this.propertyList.get(PR_MARGIN_LEFT).getLength().getValue(); +</screen> +in <literal>PropertyManager.getMarginProps()</literal>. +<literal>getLength()</literal> is a sort of cast; it returns the +property value if it is a length. The <literal>getValue()</literal> +method invoked is +<literal>RelativeNumericProperty.getValue()</literal>. +This calls +<literal>RelativeNumericProperty.getNumericValue()</literal>, which +calls <literal>RelativeNumericProperty.getResolved()</literal>. This +invokes the operation on its two operands, +<literal>NumericOp.addition2</literal>, which invokes +<literal>getNumericValue()</literal> on each +operand. <literal>PercentLength.getNumericValue()</literal> calls +<literal>LengthBase.getBaseLength</literal> on its member +<literal>lbase</literal>.</para> + +<para>Due to its value <literal>iBaseType == 5 == +LengthBase.BLOCK_WIDTH</literal> this invokes +<literal>parentFO.getLayoutDimension(PercentBase.BLOCK_IPD).intValue()</literal> +on its parent FO. The simple page master FO node does not have any +layout dimensions, its member <literal>layoutDimension</literal> is +<literal>null</literal>. Therefore it consults its parent FO. This +goes all the way up to the root FO node.</para> + +<para>The root FO node does have the required layout dimensions, which +are the page dimensions. These have been set on it +by the <literal>PageLayoutManager</literal> when the page was created +in its +method <literal>createPageAreas</literal>: +<screen> +((FObj) fobj.getParent()).setLayoutDimension(PercentBase.BLOCK_IPD,pageWidth) +((FObj) fobj.getParent()).setLayoutDimension(PercentBase.BLOCK_BPD,pageHeight) +PercentBase.BLOCK_IPD = 2, PercentBase.BLOCK_BPD = 3 +</screen> +As a result: +<screen> + layoutDimension = "{2=576000, 3=792000}" + key = "2" + getName() = "fo:root" +</screen> +</para> + +<screen> + [1] org.apache.fop.fo.FObj.getLayoutDimension (FObj.java:241) + [2] org.apache.fop.datatypes.LengthBase.getBaseLength (LengthBase.java:120) + [3] org.apache.fop.fo.properties.PercentLength.getNumericValue (PercentLength.java:82) + [4] org.apache.fop.fo.expr.NumericOp.addition2 (NumericOp.java:52) + [5] org.apache.fop.fo.expr.RelativeNumericProperty.getResolved (RelativeNumericProperty.java:105) + [6] org.apache.fop.fo.expr.RelativeNumericProperty.getNumericValue (RelativeNumericProperty.java:132) + [7] org.apache.fop.fo.expr.RelativeNumericProperty.getValue (RelativeNumericProperty.java:170) + [8] org.apache.fop.fo.PropertyManager.getMarginProps (PropertyManager.java:267) +</screen> + +<para><literal>PercentLength.getNumericValue()</literal> returns the +page width, which is multiplied by the requested factor of 0.2, and +added to the value of the fixed length, 4000. The resulting value is +returned and used for the variable <literal>marginLeft</literal>: + +<screen> + value = 119200.0 + props.marginLeft = 119200 +</screen> +</para> + + </section> + + </section> + +</chapter> + +<!-- Local Variables: --> +<!-- current-language-environment: UTF-8 --> +<!-- coding: utf-8 --> +<!-- default-input-method: TeX --> +<!-- End: --> diff --git a/src/documentation/content/xdocs/DnI/rendering.xml b/src/documentation/content/xdocs/DnI/rendering.xml new file mode 100644 index 000000000..82f3b429c --- /dev/null +++ b/src/documentation/content/xdocs/DnI/rendering.xml @@ -0,0 +1,90 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + * Copyright 2004 The Apache Software Foundation. + * + * Licensed 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$ --> + +<!-- +<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" + "docbookx.dtd"> + --> + +<chapter> + <title>Phase 3: Rendering the pages</title> + + <para>It is the task of the rendering phase to describe the area +tree in the target page description language, so that viewers for that +language can render the pages. Rendering is done page by page. For +each page the rendering system is handed a PageViewport, and it walks +the area subtree below it. For each area it retrieves the traits and +data, and generates the required output.</para> + + <para>The layout of a page is not finished until all forward +references on that page have been resolved. As a consequence pages are +finished out of pagination order. Some renderers support out of +order rendering of pages, +<literal>AbstractRenderer.supportsOutOfOrder()</literal>. If a +renderer does, a finished page is handed over to it +immediately. Otherwise, the layout system keeps finished pages until +all preceding pages are also finished and have been handed over to the +renderer. In principle, the PDF renderer supports out of order +rendering. In current FOP (27 June 2004) this has been disabled +because the support is broken.</para> + + <para>This stack at a deep position, rendering a leader in a block +in a flow in the body region, shows some details of rendering. Note +how the hierarchy of the area tree can be recognized. The lower +frames show how the rendering system is called by the layout system: + +<screen> +main[1] where + [1] org.apache.fop.render.pdf.PDFRenderer.renderLeader (PDFRenderer.java:1,266) + [2] org.apache.fop.render.AbstractRenderer.serveVisitor (AbstractRenderer.java:832) + [3] org.apache.fop.area.inline.Leader.acceptVisitor (Leader.java:118) + [4] org.apache.fop.render.AbstractRenderer.renderLineArea (AbstractRenderer.java:610) + [5] org.apache.fop.render.pdf.PDFRenderer.renderLineArea (PDFRenderer.java:830) + [6] org.apache.fop.render.AbstractRenderer.renderBlocks (AbstractRenderer.java:547) + [7] org.apache.fop.render.AbstractRenderer.renderBlock (AbstractRenderer.java:588) + [8] org.apache.fop.render.pdf.PDFRenderer.renderBlock (PDFRenderer.java:513) + [9] org.apache.fop.render.AbstractRenderer.renderBlocks (AbstractRenderer.java:538) + [10] org.apache.fop.render.AbstractRenderer.renderFlow (AbstractRenderer.java:473) + [11] org.apache.fop.render.AbstractRenderer.renderMainReference (AbstractRenderer.java:456) + [12] org.apache.fop.render.AbstractRenderer.renderBodyRegion (AbstractRenderer.java:392) + [13] org.apache.fop.render.AbstractRenderer.renderRegionViewport (AbstractRenderer.java:338) + [14] org.apache.fop.render.AbstractRenderer.renderPageAreas (AbstractRenderer.java:310) + [15] org.apache.fop.render.pdf.PDFRenderer.renderPage (PDFRenderer.java:471) + [16] org.apache.fop.area.RenderPagesModel.addPage (RenderPagesModel.java:117) + [17] org.apache.fop.area.AreaTree.addPage (AreaTree.java:143) + [18] org.apache.fop.layoutmgr.PageLayoutManager.finishPage (PageLayoutManager.java:532) + [19] org.apache.fop.layoutmgr.PageLayoutManager.doLayout (PageLayoutManager.java:231) +</screen></para> + + <para>Obviously there is a lot to be documented about the rendering +system, and about each renderer separately. Because I do not (yet) +know much about the rendering system, I will have to leave that task +to others. I only add the obvious: Rendering requires precise +programming: spacing and progress calculations, saving and restoring +dimensions, etc. It also requires tracking the state in the output +format.</para> + +</chapter> + +<!-- Local Variables: --> +<!-- current-language-environment: UTF-8 --> +<!-- coding: utf-8 --> +<!-- default-input-method: TeX --> +<!-- End: --> |